Hace unos meses que
Stephen Weis, a quien tengo la suerte de tener de compañero en Google, junto con Arkajit Dey y la ayuda de otros, publicó
Keyczar.
Keyczar es una biblioteca, disponible para Java, Python y C++ [1] -los tres principales lenguajes de programación que se usan en Google-, que facilita enormemente el uso de las cuatro funciones criptográficas principales (cifrado, descifrado, firma y verificación de la firma) y el cambio y versionado de las claves utilizadas.
Todos los que nos dedicamos a la seguridad aprendemos rápido que los principales problemas del uso de la criptografía no están en la fortaleza de los algoritmos, sino en la implementación y uso de los mismos y en la gestión de las claves. Keyczar intenta que, como se dice en inglés, sea difícil dispararnos en nuestro propio pie al usar criptografía en nuestras aplicaciones.
Que Google restrinja los lenguajes usados en producción a tres tiene sus ventajas e incovenientes (interesados en una flamewar pueden leer
este artículo de Steve Yegge). En este caso el resultado indirecto es que Keyczar no está disponible para
.NET.
Dándole vueltas un poco a cómo podría cambiar esto -C# es un lenguaje que me gustó mucho cuando programé un poco con él, igual que MonoDevelop)-, se me ocurrieron varias opciones. Por orden: portar el código a C# u otro lenguaje
.NET, compilar la versión de C++ como una dll, o usar la versión de Java.
Un
port sería lo mejor, pero también parece muy trabajoso, no tengo mucho tiempo libre, y hace ya mucho desde que programé (sólo un poco) en C#. Estoy en las mejores condiciones para hacer portar el código y hacerlo mal.
La versión de C++ sólo puede usarse en Linux. Aunque para mí no sería problema, me pareció un esfuerzo menos útil que una versión que pudiera ejecutarse en varios sistemas operativos.
Así que decidí probar con la biblioteca en Java.
Alguien que se encontró en una situación similar, escribió
IKVM.NET, un interesante proyecto que proporciona interoperatibilidad (hasta cierto punto) entre Java y
.NET. Una de las herramientas que IKVM.NET incluye es
ikvmc, un compilador de bytecode Java a
.NET. Básicamente, como su página de manual indica, un programa que transforma aplicaciones y ficheros JAR en ensamblados (assemblies)
.NET. Así que la idea era usar ikvm para convertir la biblioteca Keyczar en un
assembly .NET.
Para ello, hay que descargar los siguientes archivos JAR.
Ahora, instalamos los paquetes necesarios. Yo lo he hecho en mi Debian Squeeze y aparte de mono, monodevelop, etc. el más importante es el paquete ikvm.
Creamos el directorio ~/keyczar y copiamos los JAR dentro. En este directorio, ejecutamos ikvm:
~/keyczar$ ikvmc -target:library keyczar06b-1.6-052809.jar jss-4.jar gson-1.3.jar log4j-1.2.15.jar
Warning IKVMC0107: skipping resource (name clash): "META-INF/MANIFEST.MF"
Note IKVMC0002: output file is "keyczar06b-1.6-052809.dll"
Warning IKVMC0100: class "javax.jms.Message" not found
Warning IKVMC0100: class "javax.jms.Destination" not found
Warning IKVMC0100: class "javax.jms.JMSException" not found
Warning IKVMC0100: class "javax.mail.Session" not found
Warning IKVMC0100: class "javax.mail.internet.MimeMessage" not found
Warning IKVMC0100: class "javax.mail.Message" not found
Warning IKVMC0100: class "javax.mail.MessagingException" not found
Warning IKVMC0100: class "javax.mail.internet.InternetAddress" not found
Warning IKVMC0100: class "javax.mail.Address" not found
Warning IKVMC0100: class "javax.mail.Message$RecipientType" not found
Warning IKVMC0105: unable to compile class "org.apache.log4j.net.SMTPAppender$1"
(missing class "javax.mail.Authenticator")
Warning IKVMC0100: class "org.apache.log4j.net.SMTPAppender$1" not found
Warning IKVMC0100: class "javax.mail.Authenticator" not found
Warning IKVMC0100: class "javax.mail.internet.AddressException" not found
Warning IKVMC0100: class "javax.mail.internet.MimeBodyPart" not found
Warning IKVMC0100: class "javax.mail.internet.MimeMultipart" not found
Warning IKVMC0100: class "javax.mail.Multipart" not found
Warning IKVMC0100: class "javax.mail.BodyPart" not found
Warning IKVMC0100: class "javax.mail.Part" not found
Warning IKVMC0100: class "javax.mail.Transport" not found
Warning IKVMC0100: class "com.sun.jdmk.comm.HtmlAdaptorServer" not found
Warning IKVMC0100: class "com.sun.jdmk.comm.CommunicatorServer" not found
Warning IKVMC0105: unable to compile class "org.apache.log4j.net.JMSSink"
(missing class "javax.jms.MessageListener")
Warning IKVMC0100: class "javax.jms.TopicConnectionFactory" not found
Warning IKVMC0100: class "javax.jms.TopicConnection" not found
Warning IKVMC0100: class "javax.jms.TopicSession" not found
Warning IKVMC0100: class "javax.jms.Topic" not found
Warning IKVMC0100: class "javax.jms.TopicPublisher" not found
Warning IKVMC0100: class "javax.jms.Connection" not found
Warning IKVMC0100: class "javax.jms.Session" not found
Warning IKVMC0100: class "javax.jms.ObjectMessage" not found
~/keyczar$
Los mensajes de error se deben a que ikvmc utiliza las clases java implementadas por la
OpenJDK, y la biblioteca log4j depende de ellos. Aún así podremos utilizar la DLL resultante, salvo que configuremos log4j de forma que los use (por ejemplo para que envíe correo electrónico).
Para ello, creamos un proyecto en Monodevelop (yo lo he llamado keyczarusage) y le añadimos el
assembly que hemos creado, keyczar06b-1.6-052809.dll. Además, hay que escribir esta clase Main.cs:
using System;
using org.keyczar;
namespace Keyczarusage
{
class MainClass
{
public static void Main(string[] args)
{
Crypter crypter = new Crypter(args[0]);
System.Console.WriteLine(crypter.encrypt("Hello World!"));
System.Console.WriteLine("Please, copy & paste that string below:");
String ciphertext = System.Console.ReadLine();
System.Console.WriteLine("That decrypts to:");
System.Console.WriteLine(crypter.decrypt(ciphertex t));
}
}
}
Para poder usar este programa, hay que crear una clave de cifrado. Para ello, usamos la herramienta KeyczarTool:
~/keyczar$ mkdir -p keys/crypt
~/keyczar$ java -cp log4j-1.2.15.jar:gson-1.3.jar:keyczar06b-1.6-05280 9.jar org.keyczar.KeyczarTool create --location=~/keyczar/keys/crypt --purpose=crypt
~/keyczar$ java -cp log4j-1.2.15.jar:gson-1.3.jar:keyczar06b-1.6-05280 9.jar org.keyczar.KeyczarTool addkey --location=~/keyczar/keys/crypt --status=primary
Ahora ya podemos ejecutar el programa, pasándole la dirección de las claves como parámetro:
~/Projects/keyczarusage/keyczarusage/bin/Debug$ ./keyczarusage.exe ~/keyczar/keys/crypt
log4j:WARN No appenders could be found for logger (org.keyczar.Keyczar).
log4j:WARN Please initialize the log4j system properly.
ALJM94ibZlsXDepUUhRahyLgAWMaWSecgP7Fz1I IA-A0M55rlTL4Vc5wtOw3XM3ylG7oDTFFb2ac
Please, copy & paste that string below:
ALJM94ibZlsXDepUUhRahyLgAWMaWSecgP7Fz1IIA- A0M55rlTL4Vc5wtOw3XM3ylG7oDTFFb2ac
That decrypts to:
Hello World!
La verdad es que no he probado mucho la biblioteca, sólo esta prueba. Habría que ver si las claves asimétricas funcionan, y probar varias combinaciones, pero en principio parece que es posible usar Keyczar en
.NET sin muchas dificultades. Teóricamente, la DLL creada puede usarse tanto en Mono como en
.NET en Windows sin ninguna modificación.
--
[1] La versión de C++ sólo funciona actualmente bajo Linux.