Integración GPG, C# con The Legion of the Bouncy Castle

 

1. Introducción.

Una de las alternativas más usadas en el cifrado y firmado de ficheros mediante el esquema clave pública – privada es GnuPG[1], una aplicación open source de los algoritmos GPG de cifrado que, a día de hoy, solo dispone de una utilidad para línea de comando, poco usable si queremos integrarlo en nuestros programas .NET.

Por suerte, esta disponble Bouncy Castle, un paquete también open source de implementaciones criptográficas. Una de ellas, la que nos interesa, es PGP, y que por “suerte”, se lleva muy bien con GPG.

En este artículo veremos cómo realizar las operaciones básicas de encriptación / desencriptación tanto con GPG desde línea de comandos, como con Bouncy Castle desde nuestro código C#

2. Invitamos a los amigos GPG y Bouncy Castle

Para empezar la fiesta primero tenemos que descargarnos tanto GnuGP como Bouncy Castle de sus respectivas páginas web.

De GnuPG nos bajaremos los binarios para Windows [3] y de BouncyCastle, el código fuente junto con los ejemplos. Cuidado porque, debido a ciertas leyes estadounidenses, puedes bajar el paquete con o sin la implementación del algoritmo IDEA. Si resides fuera de Estados Unidos, te recomiendo el que lleva la implementación. [4]

Una vez descargados, procederemos a la típica instalación de GnuPG dando doble click, y descomprimiremos BouncyCastle en un directorio para después abrir la solución con Visual Studio. Seguramente tendremos que portar esta solución ya que está realizada con un Visual Studio anterior a 2008.

3. Primer invitado, GPG

Lo primero que tenemos que tener claro es que GnuGP es una aplicación bastante extensa de la cual nosotros vamos a utilizar un apenas 0,5% y lo que nos interesa a nosotros es su capacidad para generar las claves públicas/privadas, como las almacena y es capaz de exportarlas, y la encriptación-desencriptacion propiamente dicha.

Vamos a generar nuestro primer par de claves privada/publica. Nos situamos en el directorio de instalación de GnuPG y escribimos.

$gpg –-gen-key

Escogeremos la clave RSA and RSA (default) como algoritmos de encriptación y firmado, la expiración de la clave, en nuestro caso 0 y escribiremos nuestro nombre, email y comentarios para que sirve la clave. El “real name” es importante ya que es el nombre de la clave en sí para usarla con GPG, por tanto yo recomiendo un nombre sin espacios (puntos en vez de espacios) y sin caracteres raros.

image

A continuación nos pedirá una contraseña para proteger nuestra clave. Es la contraseña que se nos pedirá cada vez que queramos usar nuestra clave privada (recordemos que cuando generamos una clave, en realidad obtenemos un par de claves, privada y pública).

En mi caso no voy a poner ninguna contraseña, pero sería recomendable su uso.

Una vez terminado el proceso, nuestro sistema ya contiene nuestra nueva clave pública/privada, pero ¿Dónde? Pues GnuPG almacena todas las claves en c:Users$usernameAppDataRoaminggnupgsecring.gpg

Ese fichero en concreto, en la jerga, se llama anillo de claves o keyring. Básicamente es un fichero con todas las claves, una detrás de otra.

¿Se pueden ver en claro? Sí, pero si abrimos el fichero con el notepad el contenido es ininteligible. Debemos exportar las claves para poder verlas, guardarlas, transportalas etc..

En concreto, con el siguiente comando:

$gpg.exe --armor --output privkey.txt --export-secret-key

Conseguimos en el fichero privkey.txt nuestra clave privada (nos pedirá la contraseña si la hemos usado en la creación.

Y con este otro, la clave pública

$ gpg.exe --armor --output pubkey.txt --export nombreClave

Donde pone nombreClave, debemos escribir el nombre que le dimos nosotros. En pubkey.txt tendremos nuestra clave pública, lista para ser enviada a quien queramos para que cifre ficheros que solo puedan ser descifrados con nuestra clave privada. La clave privada deberemos guardarla, nunca publicarla.

Y ahora para cifrar/descifrar un fichero, tan sencillo como

$gpg –e –r nombreClave ficheroAEncriptar

El fichero encriptado se llamara igual que el origen, pero con la extension gpg y el nombre de la clave, nuevamente, deberá ser el que escribimos al crear la clave otra vez.

4. Segundo invitado, BouncyCastle

BouncyCastle ya trae ejemplos creados para trabajar encriptando/desencriptando ficheros, en concreto en $/crypto/tests/src/openpgp/examples/keyBaseFileProcessor.cs

En este fichero, tenemos unos métodos llamados EncryptFile y DecryptFile, donde se muestra como realizar estas tareas. Si queremos montar nuestro propio sistema está claro que este es el punto de partida para empezar a sacar ideas. Como en este mismo fichero ya tenemos un Main montando, vamos a probarlo. Para ello, en el proyecto crypto-test, en su método main, he comentado todas las llamadas a los métodos y lo he reemplazado por esto:

   1:  [STAThread]
   2:  static void Main(string[] args)
   3:  {
   4:     DateTime before = DateTime.Now;
   5:     try
   6:     { 
   7:      Org.BouncyCastle.Bcpg.OpenPgp.Examples.KeyBasedFileProcessor.Main(args);
   8:     }
   9:  
  10:   

Dejando el resto igual. Si compilamos la aplicación, veremos como BouncyCastle es capaz de usar el mismo fichero de claves de GnuPG para encriptar o desencriptar archivos, llamándolo de esta forma:

$crypto-test.exe –e ficheroAEncriptar c:Users$usernameAppDataRoaminggnupgsecring.gpg

O

$crypto-test.exe –d ficheroAEncriptar c:Users$usernameAppDataRoaminggnupgsecring.gpg “contraseña”

(La contraseña es la elegida cuando se generó la clave privada, si no se escribió ninguna, usar “” a secas)

Pero, también podría realizar la misma acción con las claves exportadas por si quisiésemos realizar la tarea de cifrado/descifrado en otra máquina donde ni siquiera tuviese instalado GnuPG

$crypto-test.exe –e ficheroAEncriptar pubkey.txt

O

$crypto-test.exe –d ficheroAEncriptar privkey.txt “”

Atención, porque lo lógico es encriptar con la clave pública y que solo el poseedor de la clave privada, nosotros, pudiera desencriptarlo.

Asi pues, con estos sencillos pasos, tenemos una solución de encriptado, desencriptado integrada en nuestras aplicaciones y con posibilidad de, en caso de necesidad, usar aplicaciones de terceros como GnuPG al usar algoritmos 100% compatibles.

[1]http://www.gnupg.org/

[2] http://www.bouncycastle.org/csharp/

[3] ftp://ftp.gnupg.org/gcrypt/binary/gnupg-w32cli-1.4.10b.exe

[4] http://www.bouncycastle.org/csharp/download/bccrypto-net-1.6.1-src-ext.zip

VS2010 tarda en lanzar una aplicacion en modo debug.

Si al lanzar una aplicacion en modo debug VS2010 se queda mucho tiempo mostrando los mensajes de output relativos al QTAgent32.exe, en concreto:

 

‘QTAgent32.exe’ (Managed (v4.0.30319)): Loaded ‘C:Program FilesMicrosoft Visual Studio 10.0Common7IDEPrivateAssembliesMicrosoft.VisualStudio.TeamSystem.Licensing.dll’

entre otras, desactivando el JIT optimization on module load se puede evitar dicho tiempo de espera.

 

¿Como hacer esto?

Debug->Options and settings

Dentro del apartado Debugging, General, Suppress JIT optimization on module load(Managed only) (desactivarlo)

En internet no hay muchas soluciones al respecto, por tanto este workaround puede valer para ir tirando.