domingo, 7 de mayo de 2017

Introducción a GPG - Cifrado Asimétrico


Continuando con el artículo que comencé sobre cifrado simétrico con GPG y cuya lectura recomiendo encarecidamente antes de leer éste (lo dejo en las referencias al final) ya que haré asunciones sobre determinados conceptos, voy a centrarme ahora en el cifrado asimétrico o de clave pública, mucho más complejo e interesante.

Como rápido recordatorio, la diferencia entre el cifrado simétrico y el asimétrico es que en el primero se utiliza la misma clave para cifrar y descifrar un mensaje (entendiéndose por mensaje cualquier tipo de archivo), mientras que en el segundo se utilizan dos claves distintas. A la clave que usamos para cifrar la llamamos clave pública, y a la que usamos para descifrar, clave privada.

Cuando se quiere enviar un mensaje, el emisor busca la clave pública del receptor, cifra su mensaje con esa clave, y una vez que el mensaje cifrado llega al receptor, este se ocupa de descifrarlo usando su clave privada. De este modo, únicamente el receptor es capaz de leer el mensaje que le ha sido enviado, siendo muy parecido a lo que ocurre con los buzones postales: cualquier persona puede introducir una carta en un buzón, pero a partir de ese momento solo el poseedor de la llave podrá abrir el buzón y leer la carta.


Una de las mayores ventajas que nos ofrece este tipo de cifrado es la firma digital, pero antes de eso, tenemos que realizar la configuración inicial y generación de nuestras claves, lo que nos obliga, claro está, a elegir en primer lugar los algoritmos que queremos utilizar.


¿Qué cifrado asimétrico utilizar?


Aunque la tecnología está en constante evolución y de hecho a partir de la versión 2.1 de GPG se ha incluido ya la moderna criptografía de curvas elípticas, vamos a centrar este apartado en los dos principales algoritmos que más se utilizan a día de hoy: RSA y ElGamal.

RSA es el más utilizado del mundo, permite implementar cifrado de archivos y firma digital sin ningún problema. Los certificados emitidos por CERES actualmente trabajan con claves RSA de 2048 bits, consideradas suficientemente seguras, aunque la longitud máxima que permite la versión actual de GPG es de 4096 bits. La seguridad de RSA radica en la dificultad de factorización de grandes números primos.

ElGamal por otro lado es también ampliamente utilizado y admite variantes con curvas elípticas, lo que lo hace mucho más interesante y complejo. A pesar de que se puede implementar cifrado y firma digital con ElGamal, el algoritmo que propuso su creador para la firma digital no se aplica en la práctica, y se suele utilizar en su lugar el algoritmo DSA (Digital Signature Algorithm), estándar del gobierno de los EE.UU. La seguridad de ElGamal radica en la dificultad de hallar el logaritmo discreto de un número.

Cualquiera de los dos esquemas, DSA + ElGamal o RSA, es válido y seguro.


Claves maestras, subclaves y redes de confianza


Antes de comenzar a generar nuestras claves de cifrado y firma, hay que pararse en el concepto de subclaves. GPG organiza nuestras claves (pares de claves en realidad, recordemos que siempre se utiliza una pública y una privada) en dos jerarquías distintas: maestras y subclaves.

Las claves maestras, también llamadas primarias o principales, sirven en general para firmar, mientras que las subclaves se pueden generar bien para firmar, bien para cifrar. Toda subclave está asociada a una clave maestra.

La razón de ser de esta clasificación es sencilla, aunque requiere la introducción del concepto de redes de confianza: Cuando empecemos a interactuar con otras personas intercambiando claves y mensajes, nuestra clave maestra representará nuestra identidad online. Es decir, cualquier mensaje que firmemos con dicha clave nos identificará sin ninguna duda como remitentes originales inequívocos del mismo; podemos establecer una analogía entre la clave maestra y el DNI.

La diferencia entre ambos es que, en el caso del DNI es el estado quien nos identifica y da fe de quiénes somos (mediante la toma de huellas dactilares por ejemplo), y como todos confiamos en la rigurosidad del estado, damos por válido el DNI y no lo cuestionamos como documento acreditativo de la identidad de una persona. Sin embargo, en el caso de una clave pública autogenerada como es el que nos ocupa, donde el estado no interviene en absoluto, necesitamos que alguien dé fe de que esa clave es auténticamente nuestra, y de que por tanto cualquier mensaje firmado con dicha clave nos pertenece y no hay nadie suplantando nuestra identidad.

Bueno pues, dado que no existe una única autoridad suprema de certificación de identidad en internet, se requiere de un método alternativo para poder confiar en las claves y las personas a las que supuestamente identifican. Esto se logra mediante la creación de redes de confianza, que explicaré con un ejemplo: Supongamos tres personas que, por simplicidad, llamaremos Alicia, Bob y Carlos.

Carlos acaba de entrar en el mundo de la criptografía asimétrica y acaba de generar su par de claves de firma, y va por ahí escribiendo en foros que su clave pública de firma es X. Como todos sabemos que uno no puede fiarse ni de la mitad de lo que hay en internet, nadie le hace caso a Carlos, ya que la palabra de un anónimo en internet diciendo quién es y que todo el mundo debe confiar en que su clave es X, no vale nada.

Pero resulta que Carlos tiene un buen amigo, Bob, que ya lleva un tiempo en el mundo de PGP y puede ayudarle a introducirle. ¿Cómo? Dando fe de que Carlos es quien dice ser. Para ello, Bob, con su clave de firma, firma la clave X de Carlos, de modo que ahora, a ojos del mundo, Bob está certificando que todas las firmas realizadas con la clave X han sido efectuadas por Carlos.

A todo esto, Alicia, que es amiga de Bob pero no conoce de nada a Carlos, ve que el primero ha firmado la clave del segundo, y como confía en Bob, por extensión, también confía en que la clave X es de Carlos. Por tanto Alicia tiene ahora la opción también de firmar ella misma la clave de Carlos (añadiendo así solidez a la identidad de Carlos, ya que ahora son dos las personas que certifican su identidad en lugar de una), simplemente porque se fía de la palabra de Bob, o bien de esperar a conocer a Carlos ella misma en persona y, con algún documento de identidad mediante (DNI, pasaporte, carnet de conducir), asegurarse ella misma de que es quien dice ser, y firmar su clave. A su vez, los amigos de Alicia ahora confían también, por transitividad, en la clave de Carlos, y de nuevo se puede repetir la operación de que la firmen sin más o de asegurarse en persona.

A este proceso que acabamos de describir se le conoce como crear una red de confianza y, a efectos prácticos, permite a una persona construir su identidad y su reputación en internet. Es muy importante pues que, cuando generamos nuestro par de claves, éste permanezca absolutamente seguro, ya que es sobre ese par donde vamos a construir nuestra identidad online, y la posibilidad de que nuestras claves se vean comprometidas pondría en peligro toda la red de confianza construida a nuestro alrededor y nos obligaría a empezar de cero.

Cuando alguien quiere ampliar el círculo de personas que certifican su clave, suele acudir a una de las llamadas fiestas de firmado de claves (o key‑signing party en inglés), en las cuales los asistentes presentan sus claves PGP a otros participantes de la fiesta junto con algún documento de identificación oficial, quienes, tras verificar la identidad de la persona propietaria de la clave, procederán a firmar digitalmente el certificado PGP conteniendo la clave pública de la persona, su nombre, e‑mail, etc.

Conociendo ahora la suma importancia de proteger nuestra clave maestra en el lugar más seguro de la Tierra, ya que ella representará quiénes somos en internet, necesitamos algo con lo que poder operar día a día sin el temor a ser suplantados. Para ello, GPG nos permite crear subclaves, tantas como queramos, asociadas a una clave maestra. Nuestras subclaves serán firmadas por nosotros mismos, lo que les dará autenticidad, y con ellas podremos manejarnos en nuestro día a día, ya sea para firmar o para cifrar datos. Si en algún momento creemos que alguna de nuestras subclaves ha sido comprometida, o sencillamente queremos desecharla y utilizar una nueva, nos bastará con generar un certificado de revocación (hablaremos más adelante de ello) de la subclave a ser anulada y publicarlo. De este modo todo el mundo sabrá que ya no se puede confiar en dicha clave.

Y es con esta sencilla pero potente idea de claves desechables con la que jugaremos, manteniendo siempre nuestra clave maestra original a buen recaudo y utilizándola lo mínimo posible, ya que es un hecho que cuanto más utilizas una clave, más revelas sobre la misma. Y, a pesar de estar trabajando con algoritmos y sistemas bien seguros y probados, computacionalmente imposibles de romper a día de hoy, nunca está de más añadir capas extra de seguridad, sobre todo si se trata de algo tan sencillo como utilizar una subclave desechable en cualquier momento.


Generación, importación y exportación local de claves


Para generar un nuevo par de claves maestras viendo todas las opciones disponibles, abrimos un terminal y escribimos lo siguiente:

En cuanto seleccionemos la que más nos interese, se nos hará una serie de preguntas acerca de la longitud en bits de clave que deseamos (evidentemente, cuanto más larga, más segura, aunque también más lenta a la hora de ser usada), la caducidad de la clave (que podemos cambiar en cualquier momento en el futuro, incluso si ya ha caducado), datos personales (nombre, apellidos, correo electrónico) y una contraseña que sirva para cifrar localmente nuestra clave (y así evitar que cualquiera pueda acceder al archivo que la contiene y copiarla en claro sin más):

Es importante generar suficiente entropía en el ordenador mientras se generan las claves, para que éstas sean lo suficientemente aleatorias. En mi caso, he puesto una película por streaming en Firefox mientras que en el LibreOffice Writer escribía cosas al azar casi aporreando el teclado, todo esto mientras abría multitud de pestañas en Chrome.

Vamos a listar ahora todas las claves públicas que tenemos actualmente almacenadas localmente, junto con sus subclaves:

Vemos que se marca como pub (pública, maestra) la clave de firma DSA de 3072 bits que antes creamos, y se marca como sub (subclave) la clave de cifrado ElGamal de 4096 bits.

Además, la clave DSA está marcada como [SC], que implica que puede ser usada tanto para Firma de mensajes (Sign) como para Certificación (firma de claves de otras personas, como hemos explicado anteriormente). La clave ElGamal está marcada en cambio como [E], es decir, que puede ser usada para cifrar mensajes (Encrypt). Adicionalmente, existe el flag [A] de autenticación (firma de desafíos o challenge–response authentication), que nos permite teóricamente utilizar nuestra clave GPG para autenticarnos en servidores como SSH utilizando el GPG Agent como si fuese el SSH Agent, si bien la documentación oficial sobre esta opción es prácticamente inexistente. Dejo en las referencias un enlace que profundiza en el tema.

Algunas de las opciones que más nos pueden interesar llegados a este punto son:

  • ‑a, ‑‑armor : Colocando esta opción al inicio de cualquier instrucción que genere una salida, ya sea por consola o a un fichero, en lugar de generarse un binario (en el caso de salida a fichero) se generará un ASCII codificado en base64. El archivo generado ocupará más espacio en consecuencia, pero será legible desde cualquier editor de textos.

  • ‑‑delete‑keys : Elimina la clave pública maestra con el ID que le pasemos. Si la clave pública tiene una clave privada asociada, no nos dejará eliminarla hasta que eliminemos primero la privada. Esto también eliminará todas las subclaves asociadas a la clave maestra indicada. Esta opción no permite eliminar subclaves individualmente; veremos cómo se acomete esto más adelante.

  • ‑‑delete‑secret‑keys : Elimina la clave privada maestra con el ID que le pasemos. Esto también eliminará todas las subclaves privadas asociadas a la clave maestra indicada. Esta opción no permite eliminar subclaves individualmente; veremos cómo se acomete esto más adelante.

  • ‑‑delete‑secret‑and‑public‑keys : Elimina la clave pública maestra con el ID que le pasemos. Si la clave pública tiene una clave privada asociada, también la eliminará. Esto también eliminará todas las subclaves asociadas a la clave maestra indicada. Esta opción no permite eliminar subclaves individualmente; veremos cómo se acomete esto más adelante.

  • ‑‑desig‑revoke : Al pasar un ID de clave maestra a esta opción, si alguna de nuestras claves primarias ha sido sido habilitada para poder crear un certificado de revocación de dicha clave (sin ser el propietario de la clave), generamos dicho certificado. Es decir, hace lo mismo que la opción ‑‑gen‑revoke, pero para claves que no son nuestras.

  • ‑‑edit‑key : Al pasar un ID de clave maestra a esta opción, se abre un prompt donde podemos realizar varias funciones sobre dicha clave y sus subclaves. Veremos estas funciones más adelante.

  • ‑‑expert : Permite al usuario realizar algunas opciones extra al ejecutar otra opción, como firmar una clave caducada o revocada, o ampliar la variedad de algoritmos con los que se pueden generar claves.

  • ‑‑export : Utilizándolo en conjunto con ‑‑output e indicándole el ID de la clave pública maestra que nos interese, exportamos dicha clave, junto con todas sus subclaves (siempre públicas) a un archivo. Si no indicamos un ID explícitamente, se exportan todas las claves públicas que tengamos almacenadas. Si queremos exportar una o varias subclaves concretas en lugar de todo el conjunto formado por clave maestra y todas sus subclaves, deberemos pasarle los IDs de las subclaves que nos interesen acompañados de una exclamación: ID1! ID2! ...
    Con esta opción siempre se exporta la clave pública maestra.

  • ‑‑export‑ownertrust : Exporta los valores de confianza que tengamos establecidos para cada clave de nuestro anillo local a un fichero de texto. Es necesario redireccionar la salida manualmente a un archivo de texto, ya que la opción ‑‑output no funciona con esta instrucción.

  • ‑‑export‑secret‑keys : Utilizándolo en conjunto con ‑‑output e indicándole el ID de la clave privada maestra que nos interese, exportamos dicha clave junto con todas sus subclaves a un archivo. Si no indicamos un ID explícitamente, se exportan todas las claves privadas que tengamos almacenadas. Si queremos exportar una o varias subclaves concretas en lugar de todo el conjunto formado por clave maestra y todas sus subclaves, deberemos pasarle los IDs de las subclaves que nos interesen acompañados de una exclamación: ID1! ID2! ...
    Cada vez que se exporta una clave privada, también se exporta su pública aparejada implícitamente. Con esta opción siempre se exporta la clave privada maestra.

  • ‑‑export‑secret‑subkeys : Idéntico a ‑‑export‑secret‑keys salvo porque en este caso nunca se exportan las claves privadas maestras, únicamente las públicas maestras y las subclaves al completo.

  • ‑‑gen‑revoke : Crea un certificado de revocación de la clave maestra que le indiquemos, que deberemos mantener a salvo para ser utilizado en caso de que ésta se vea comprometida. De este modo, estaremos anunciando públicamente que esa clave ya no es de confianza y que no debe utilizarse más. Esta opción no permite crear certificados de revocación para subclaves individuales; veremos cómo se acomete esto más adelante.

  • ‑‑import : Importa las claves del archivo que le indiquemos.

  • ‑‑import‑ownertrust : Actualiza la base de datos de confianza de nuestro anillo local de claves con el fichero que le pasemos. Se sobreescribirán los valores ya existentes.

  • ‑k, ‑‑list‑keys, ‑‑list‑public‑keys : Lista la clave pública maestra y todas las subclaves del ID de clave maestra que le pasemos, o bien de todas las claves públicas que tengamos almacenadas localmente junto con todas sus subclaves si no le indicamos ningún ID explícitamente.

  • ‑K, ‑‑list‑secret‑keys : Lista la clave privada maestra y todas las subclaves del ID de clave maestra que le pasemos, o bien de todas las claves privadas que tengamos almacenadas localmente, que figurarán como sec (secreta), junto con todas sus subclaves, que aparecerán señaladas como ssb (secret subkey). Si en alguna clave primaria secreta apareciera una almohadilla delante, es decir, que viéramos #sec en lugar de sec, es indicativo de que la clave privada maestra no está disponible. Esto ocurre por ejemplo cuando importamos una subclave privada, pero no la clave privada de su clave maestra asociada.

  • ‑u, ‑‑local‑user : Con esta opción indicamos el ID de la clave maestra que utilizaremos para ejecutar la función que corresponda (por ejemplo, para firmar con una clave distinta de la principal marcada por el programa), o bien el ID de la subclave que queramos usar, siempre que la acompañemos de una exclamación: ID!

  • ‑o, ‑‑output : Especifica el nombre del archivo generado. Si se utiliza esta opción, debe colocarse en primer lugar.

  • ‑‑version : Imprime información sobre la versión del programa, así como los algoritmos de cifrado simétricos y asimétricos soportados, los algoritmos de resumen (hash) y los tipos de compresión admitidos.

Para exportar una clave secreta al completo con todas sus subclaves y todas las públicas aparejadas, y que además sea legible en un archivo de texto, ejecutamos lo siguiente:

Y para importar un archivo contenedor de claves, independientemente de si son públicas o privadas, basta con ejecutar la siguiente instrucción:



Editar una clave maestra y sus subclaves


Vamos a ver ahora las funciones más interesantes que podemos ejecutar cuando estamos en modo edición de clave (usando la opción ‑‑edit‑key anteriormente descrita). Estas funciones nunca toman parámetros (exceptuando key y uid); si los necesitan, los solicitan sobre la marcha una vez iniciadas:

  • addkey : Añade una nueva subclave. Siempre que creemos una nueva subclave, se nos pedirá una contraseña para que sea almacenada de manera segura. Cada subclave puede tener su propia contraseña diferente de la de las demás.

  • addphoto : Añade una imagen JPEG asociada a la clave maestra. Hay que tener cuidado con esta opción pues la imagen se almacenará en la clave pública, lo que puede hacer que el tamaño de la clave pública crezca considerablemente. Se recomienda usar una imagen con unas dimensiones aproximadas de 240x288 px. La imagen se almacenará como si fuese otro identificador de usuario (UID) más asociado a la clave.

  • addrevoker : Si en nuestro sistema tenemos varias claves públicas maestras instaladas, habilita aquella que seleccionemos para generar un certificado de revocación de la clave con la que estamos trabajando actualmente. Este certificado se generará usando la opción ‑‑desig‑revoke anteriormente vista. Una vez concedido el permiso de revocación a una clave, no puede ser retirado. Usar con precaución.

  • adduid : Añade otro identificador de usuario (nombre, apellidos, e‑mail y comentario) asociado a la clave.

  • check : Lista todos los usuarios que han firmado la clave y comprueba que dichas firmas son correctas. Para que esta instrucción funcione correctamente, es requisito indispensable tener importadas las claves públicas de los usuarios que hayan firmado la clave. El estado de verificación de cada firma se indica justo detrás de la etiqueta sig en cada línea. Un símbolo ! indica que la firma se ha verificado correctamente, un indica que la firma es incorrecta y un % indica que ha habido un error en la comprobación de la firma (por utilizar un algoritmo no soportado por ejemplo).

  • clean : Elimina de la clave las firmas no válidas, revocadas o no presentes en el anillo local de claves, así como todas las autofirmas redundantes en caso de haberlas (sólo deja la más reciente). Esta función resulta muy útil ejecutarla justo antes de enviar la clave al servidor. Así nos aseguramos de que la enviamos lo más "limpia" posible.

  • delkey : Elimina las subclaves que tengamos seleccionadas en ese momento (con la opción key) de nuestro anillo local. Si las subclaves ya han sido subidas a un servidor de claves, no podremos eliminarlas de allí. En ese caso, lo que podemos hacer, si las subclaves son nuestras y poseemos la clave maestra asociada, es revocarlas con la instrucción revkey.

  • delsig : Elimina una o varias firmas realizadas sobre el UID que tengamos seleccionado en ese momento (con la opción uid) de nuestro anillo local (el programa va preguntando una por una qué firmas deberían ser eliminadas). Si una firma ya ha sido subida a un servidor de claves, no podremos eliminarla de allí. En ese caso, lo que podemos hacer, si la firma la hemos realizado nosotros, es revocarla con la instruccion revsig.

  • deluid : Elimina los identificadores de usuario que tengamos seleccionados en ese momento (con la opción uid) de nuestro anillo local. Si los UIDs ya han sido subidos a un servidor de claves, no podremos eliminarlos de allí. En ese caso, lo que podemos hacer, si los UIDs son nuestros y poseemos la clave maestra, es revocarlos con la instrucción revuid.

  • disable : Desactiva la clave maestra. Esto la vuelve inutilizable a efectos prácticos hasta que volvamos a activarla.

  • enable : Activa la clave maestra.

  • expire : Cambia la fecha de caducidad de la clave maestra o de las subclaves seleccionadas con la opción key.

  • fpr : Muestra la huella digital de la clave maestra.

  • grip : Muestra el keygrip de la clave maestra y de todas sus subclaves.

  • key : Marca o desmarca la subclave que le indiquemos numéricamente: key 1

  • keyserver : Establece el servidor de claves preferido para los identificadores de usuario que tengamos seleccionados en ese momento (con la opción uid). Esto permite al resto del mundo saber de dónde deseamos que obtengan las últimas actualizaciones que realicemos sobre nuestras claves. Si establecemos "none" como el valor del servidor, se elimina cualquier servidor que hubiéramos establecido anteriormente. Este campo no tiene ninguna utilidad práctica más allá de la meramente informativa. GPG no lo tiene en cuenta en ningún momento.

  • list : Lista la clave maestra, todas sus subclaves y todos los identificadores de usuario.

  • lsign : Hace lo mismo que sign pero firmando sólo localmente. Esto significa que si exportamos la clave firmada, con la opción ‑‑export por ejemplo, la firma que hemos realizado no se exportará con ella.

  • lnrsign : Aplica combinadamente lsign y nrsign.

  • minimize : Elimina de la clave todas las firmas, exceptuando la autofirma más reciente. Esta función resulta muy útil ejecutarla justo antes de exportar la clave para almacenarla en un archivo. Así nos aseguramos de que exportamos la información mínima imprescindible.

  • nrsign : Hace lo mismo que sign pero haciendo la firma irrevocable. Como su propio nombre indica, esta firma es definitiva y una vez efectuada no se puede dar marcha atrás, por lo que más vale estar muy seguro de lo que se hace. No es una opción que se suela utilizar.

  • passwd : Cambia la contraseña con la que se cifran las claves localmente. El comportamiento de esta opción puede parecer errático y complicado, así que dejamos abajo un ejemplo práctico para cambiar las contraseñas de varias subclaves.

  • primary : Marca el identificador de usuario seleccionado actualmente (con la opción uid) como el principal.

  • quit : Sale del menú actual.

  • revkey : Revoca la clave maestra o las subclaves seleccionadas, siempre que poseamos la clave privada maestra.

  • revsig : Revoca una o varias firmas realizadas sobre el UID que tengamos seleccionado en ese momento (con la opción uid), o bien sobre todos los UIDs si no hemos seleccionado ninguno (el programa va preguntando una por una qué firmas deberían ser revocadas). Para revocar una firma es imprescindible poseer la clave privada que ha efectuado dicha firma.

  • revuid : Revoca los identificadores de usuario que tengamos seleccionados en ese momento (con la opción uid), siempre que poseamos la clave privada maestra.

  • save : Guarda los cambios realizados y sale del menú actual.

  • setpref : Establece las preferencias de cifrado, resumen y compresión que le indiquemos a los UIDs seleccionados (con la opción uid) o a todos los UIDs si no hemos seleccionado ninguno. Las preferencias se las pasamos a la instrucción en orden de prioridad como una cadena de texto. Si no le pasamos argumento a esta función, se establecerán las preferencias por defecto que el programa determine. Si le pasamos "none" como argumento, se establecerán como preferencias mínimas 3DES, SHA1, ZIP y Sin compresión. En mi caso, lanzaré la función con la siguiente lista:

    Realmente todos los algoritmos de resumen que establezcamos en esta lista de preferencias no sirven para absolutamente nada. En el artículo de cifrado simétrico que escribí en su día explico el porqué.

  • showphoto : Muestra la foto que hayamos añadido con la función addphoto. Si hemos añadido más de una, tendremos que seleccionar previamente cuál queremos visualizar seleccionando el UID correspondiente (con la opción uid), o bien se mostrarán todas (una tras otra) si no marcamos ningún UID. Si da error al mostrar la foto porque no encuentre el programa para abrirla, deberemos abrir el archivo gpg.conf y añadir una línea indicando qué programa utilizar. Por ejemplo, en mi caso:


  • showpref : Muestra las preferencias de cifrado, resumen y compresión de los UIDs seleccionados (con la opción uid), o de todos los UIDs si no hemos seleccionado ninguno. Estas preferencias sirven para indicar al resto del mundo qué algoritmos pretendemos que utilicen para comunicarse con nosotros.

  • sign : Firma los UIDs que tengamos seleccionados junto con su clave maestra. Si no tenemos ningún UID seleccionado, se firman todos.

  • trust : Establece el nivel de confianza que tenemos sobre el propietario de la clave maestra a la hora de verificar las claves que firma de otras personas. El funcionamiento de las redes de confianza en GPG es algo intrincado, así que dejamos abajo una explicación detallada de su comportamiento.

  • uid : Marca o desmarca el identificador de usuario que le indiquemos numéricamente: uid 1

Redes de confianza


Antes de empezar, quiero dejar claro que existen varios modelos distintos de redes de confianza. El modelo que voy a explicar aquí es el modelo PGP estándar actual, utilizado en las versiones de PGP 5.X y posteriores.

Dicho esto, lo primero que tenemos que tener en cuenta es que en PGP existen dos conceptos relacionados pero diferentes: confianza y validez. El primero influye sobre el segundo.

La confianza es algo que establecemos personalmente en cada clave maestra individualmente utilizando la función trust. El nivel de confianza no se exporta junto con las claves. De hecho, no se almacena en los anillos de claves sino en una base de datos aparte, que podemos exportar e importar con los métodos ‑‑import‑ownertrust y ‑‑export‑ownertrust anteriormente descritos.

Cuando utilizamos la función trust sobre una clave, se nos pide que establezcamos un nivel de confianza del 1 al 5 en que el propietario de la clave verifique correctamente las claves de otros usuarios antes de firmarlas. Es decir, en que sea meticuloso a la hora de asegurarse de que una persona es quien dice ser (comprobando el DNI, el pasaporte, el carnet de conducir...), y es propietaria de la clave que afirma ser suya (pidiéndole que firme algo con ella para que podamos comprobarlo). Cada nivel de confianza indica lo siguiente:
  1. Desconocido : No se sabe nada sobre el dueño de la clave. Las claves recién importadas tendrán al principio este nivel de confianza. Es el nivel establecido por defecto para todo el mundo (excepto para las claves que nosotros mismos generemos).

  2. No confiable : Sabemos que el propietario de la clave ha firmado claves ajenas sin hacer las debidas comprobaciones de identidad.

  3. Dudoso : Suponemos que el propietario de la clave sabe lo que hace cuando firma una clave ajena y adopta las medidas adecuadas para asegurarse de la identidad de alguien, pero no confiamos plenamente en él. Es un nivel de confianza algo ambiguo, aunque nos inclina a pensar que el propietario suele hacer las cosas bien. Si podemos evitar este nivel, probablemente aumentaremos la seguridad de nuestra red de confianza.

  4. Total : El propietario de la clave es alguien que conoce bien el sistema de firma de claves ajenas y sabemos que siempre se asegura de la identidad de las personas cuyas claves firma. Confiamos plenamente en sus firmas.

  5. Absoluta : Este nivel de confianza lo emplearemos única y exclusivamente para nuestras propias claves.
La validez es un concepto que se aplica a los pares de identificadores de usuario (UIDs) con sus claves maestras correspondientes, y posee un valor calculado en base a unas determinadas condiciones que ahora explicaremos. La validez de un par 〈Clave, UID〉 es una medida de la certeza que tenemos de que ese par pertenece realmente a la persona que creemos.

Antes de explicar los distintos estados que puede tener el campo de validez de un par, vamos a definir un camino de firmas o un camino de claves firmadas, de longitud n, como una sucesión de claves K, K, ..., K donde K firma a K, K firma a K, ..., y Kₙ₋₁ firma a K. A las distintas claves que componen el camino las llamaremos nodos. Un nodo es descendiente directo de otro cuando ha sido firmado por éste.

Cabe destacar también que, cuando ahora pasemos a describir los estados de validez de un par, siempre que hagamos referencia o hablemos de nuestra clave maestra, podemos en realidad asumir que se aplica a cualquier clave donde tengamos establecido un nivel de confianza absoluto (nivel 5). Pero, como ya dijimos antes, sólo deberíamos marcar con este nivel únicamente nuestras propias claves.

La validez de un par aparece entre corchetes al lado de cada UID cuando listamos todas las claves disponibles en nuestro anillo local, y se puede clasificar en cinco niveles:
  1. Desconocida : No tenemos absolutamente ninguna certeza de que el par pertenezca a quien nosotros creemos. No podemos confiar en el par. Este estado aparece en cualquiera de los siguientes supuestos:
    • No existe ningún camino de claves firmadas desde nuestra clave maestra hasta el par objetivo.

    • El camino más corto de firmas que unen nuestra clave maestra hasta el par objetivo es de longitud 7 o más (se contabilizan en el camino, evidentemente, la clave maestra y el par objetivo).

    • El par objetivo desciende directamente de un nodo con validez desconocida, caducada, revocada, no definida o dudosa en cualquiera de los caminos de firmas que lo unen a nuestra clave maestra.

  2. Caducada / Revocada : Alguno de los elementos que conforman el par ha sido revocado, o bien la clave ha expirado. No podemos confiar en el par.

  3. No definida : No tenemos absolutamente ninguna certeza de que el par pertenezca a quien nosotros creemos. No podemos confiar en el par. Este estado aparece únicamente en el siguiente supuesto:
    • El par objetivo desciende directamente de un nodo con un nivel de confianza desconocido (nivel 1) o no confiable (nivel 2) en cualquiera de los caminos de firmas de longitud menor que 7 que lo unen a nuestra clave maestra.

  4. Dudosa : Es probable que el par pertenezca a quien creemos, pero no tenemos una certeza total de ello. Deberíamos proceder con precaución a la hora de confiar en el par. Este estado aparece únicamente en el siguiente supuesto:
    • El par objetivo desciende directamente de uno o, a lo sumo, dos nodos con niveles de confianza dudosos (nivel 3), y la longitud de los caminos que unen el par objetivo a nuestra clave maestra pasando por dichos nodos es menor que 7.

  5. Total : El par pertenece con total seguridad a quien creemos. Podemos confiar plenamente en él. Este estado aparece en cualquiera de los siguientes supuestos:
    • El par objetivo ha sido firmado directamente por nuestra clave maestra.

    • El camino más corto que une nuestra clave maestra con el par objetivo es de longitud menor que 7 y todos los nodos intermedios tienen un nivel de confianza total (nivel 4).

    • El par objetivo desciende directamente de, al menos, tres nodos con niveles de confianza dudosos (nivel 3), y la longitud de los caminos que unen el par objetivo a nuestra clave maestra pasando por dichos nodos es menor que 7.

  6. Absoluta : Si marcamos una clave con nivel de confianza absoluta, entonces también se asumirá la validez absoluta de cualquier par que la contenga.


Estableciendo contraseñas en las subclaves


Vamos a suponer un caso de uso práctico de la función passwd. Supongamos que tenemos una clave maestra con identificador AAA y cuatro subclaves cuyos identificadores serían, en orden: BBB, CCC, DDD y EEE. Supongamos por simplicidad que la clave maestra y todas las subclaves comparten contraseña de almacenamiento inicialmente, que sería 1111.

Si ahora decidimos que queremos que la subclave CCC tenga por contraseña 3333, lo que debemos hacer es lanzar la función passwd, tras lo cual se nos abrirá una ventana que nos pedirá que introduzcamos la contraseña de la clave AAA. En ese momento, debemos darle al botón de cancelar, lo que provocará que el programa nos abra una ventana idéntica a la anterior, pero esta vez solicitando la contraseña de la clave BBB. Volvemos a pulsar Cancelar una vez más, y ya nos pedirá la contraseña de la clave CCC. Cuando se la proporcionemos, nos preguntará cuál es la nueva contraseña que queremos asignar. Una vez que le digamos la nueva contraseña y aceptemos, el programa finalizará, sin preguntarnos nada acerca de las claves DDD y EEE.

Lo que ha ocurrido es que el programa ha modificado todas las claves en cascada a partir de aquella que hemos cambiado, es decir, ahora no solo CCC tiene la contraseña 3333, sino también DDD y EEE. Y para cambiar las de DDD y EEE el programa se ha valido de la contraseña que habíamos introducido en CCC (ha probado a ver si funcionaba y, como así ha sido, ha proseguido sin preguntar).

Si ahora decidimos que queremos que AAA, BBB, DDD y EEE tengan por contraseña 2222, al lanzar la función passwd y abrírsenos la ventana que nos pida la contraseña actual de AAA, se la proporcionamos y luego le decimos qué nueva contraseña queremos establecer. Automáticamente se modificará también la contraseña de BBB (ya que compartía la contraseña inicial 1111 con AAA, y por lo tanto no necesita preguntar). Acto seguido, se nos pedirá la contraseña actual de CCC: Si se la damos (recordemos que era 3333 porque la cambiamos antes), automáticamente se establecerán las contraseñas de CCC, DDD y EEE a 2222. Si pulsamos Cancelar, el programa pasará a la siguiente clave, que será DDD, y nos volverá a preguntar por la contraseña de almacenamiento (recordemos que también es 3333 porque se cambió en cascada al cambiar CCC anteriormente). Si se la proporcionamos, DDD y EEE verán sus contraseñas modificadas, y finalizará la ejecución.

En conclusión: La manera más óptima de establecer una contraseña diferente para cada subclave es cambiándolas de abajo hacia arriba, de forma que así sabremos que las contraseñas nunca se modifican en cascada a menos que lo permitamos explícitamente introduciendo las contraseñas de las claves que quedan por debajo, que se suponen ya modificadas.


Cifrado, Firma y Huella Digital


Vamos a ver la lista de opciones que nos ofrece gpg relativas al cifrado, la firma y la huella digital (o dactilar), y unos ejemplos de casos de uso:

  • ‑‑ask‑cert‑expire : Al usar esta opción en conjunto con ‑‑sign‑key al firmar una clave, nos pregunta cuánto tiempo debería ser válida la firma antes de caducar. Por defecto la firma no caduca nunca. Si una firma caduca, siempre podemos volver a firmar y reemplazar la firma anterior. No es una opción que se suela utilizar.

  • ‑‑ask‑cert‑level : Al usar esta opción en conjunto con ‑‑sign‑key al firmar una clave, nos pregunta cuán rigurosos hemos sido (en un nivel entre 0 y 3) a la hora de comprobar la identidad de la persona cuya clave estamos a punto de firmar. Por defecto no se añade ninguna información a la firma a este respecto. Deberíamos usar siempre esta opción al firmar una clave.

  • ‑‑ask‑sig‑expire : Al usar esta opción en conjunto con ‑‑sign al firmar un archivo, nos pregunta cuánto tiempo debería ser válida la firma antes de caducar. Por defecto la firma no caduca nunca.

  • ‑‑cert-digest-algo : Se usa en conjunto con la firma de claves ajenas, pasándole el algoritmo de hash que queremos forzar que sea utilizado a la hora de firmar las claves.

  • ‑‑check‑sigs : Es un alias para ‑‑list‑keys ‑‑with‑sig‑check.

  • ‑‑clearsign : Realiza una firma de texto en claro. Esto quiere decir que el archivo firmado que se genere contendrá el texto en claro original seguido de la firma digital, y podrá abrirse con cualquier editor de textos. Esta opción sólo se debe utilizar para firmar ficheros que puedan ser abiertos con un editor de textos, ya que si intentamos cifrar un binario de esta manera, el archivo puede acabar corrupto. Esta opción es incompatible con cualquier tipo de cifrado.

  • ‑d, ‑‑decrypt : Obtiene el archivo original a partir del archivo cifrado y/o firmado que le pasemos como argumento. Si el fichero que le pasemos está firmado, comprueba que la firma sea correcta. Esta opción se debe usar en conjunto con la opción ‑‑output para indicar dónde almacenar el archivo de salida generado.

  • ‑‑decrypt‑files : Hace lo mismo que ‑‑decrypt, pero pudiendo pasarle varios archivos cifrados y/o firmados como argumentos en lugar de solo uno. En esta opción no utilizamos ‑‑output sino que los archivos de salida se guardan en la misma carpeta automáticamente con el mismo nombre que los de entrada.

  • ‑‑default‑cert‑expire : Al usar esta opción en conjunto con ‑‑sign‑key al firmar una clave, podemos indicarle directamente cuánto tiempo debería ser válida la firma antes de caducar. Si una firma caduca, siempre podemos volver a firmar y reemplazar la firma anterior.

  • ‑‑default‑cert‑level : Al usar esta opción en conjunto con ‑‑sign‑key al firmar una clave, podemos indicarle directamente cuán rigurosos hemos sido (en un nivel entre 0 y 3) a la hora de comprobar la identidad de la persona cuya clave estamos a punto de firmar.

  • ‑‑default‑sig‑expire : Al usar esta opción en conjunto con ‑‑sign al firmar un archivo, podemos indicarle directamente cuánto tiempo debería ser válida la firma antes de caducar.

  • ‑b, ‑‑detach‑sign : Firma el archivo que le indiquemos almacenando la firma en un archivo separado; decimos en este caso que la firma está desacoplada del archivo al que está referida. Serán necesarios el archivo original y el archivo de firma para verificar que ésta es correcta.

  • ‑e, ‑‑encrypt : Cifra asimétricamente el archivo que le indiquemos. Debemos utilizar previamente la opción ‑‑recipient o ‑‑hidden‑recipient (tantas veces como queramos) para indicar quienes podrán descifrarlo utilizando sus claves privadas. Se puede combinar con ‑‑symmetric, de tal modo que el archivo pueda ser descifrado bien utilizando la clave privada de los destinatarios, bien la contraseña que establezcamos. Los destinatarios del mensaje deben tener, evidentemente, alguna clave de cifrado para que esta opción funcione.

  • ‑‑encrypt‑files : Hace lo mismo que ‑‑encrypt, pero pudiendo pasarle varios archivos a la vez.

  • ‑‑fingerprint : Es un alias para ‑‑list‑keys ‑‑with‑fingerprint. Podemos pasar este parámetro dos veces para ver las huellas digitales de las subclaves.

  • ‑R, ‑‑hidden‑recipient : Hace lo mismo que ‑‑recipient pero ocultando los IDs de las claves de los destinatarios del mensaje a cifrar. Esto quiere decir que, cuando nos llegue un mensaje cifrado e intentemos descifrarlo, el programa no sabrá a priori si el mensaje va o no dirigido a nosotros. Para descifrar este tipo de mensajes es necesario pasar la opción ‑‑try‑all‑secrets junto con ‑‑decrypt. Podemos ver los IDs de las claves de los destinatarios de un mensaje cifrado que no han sido ocultados usando la opción ‑‑list‑packets.

  • ‑‑keyserver : Esta opción puede acompañar a las opciones ‑‑recv‑keys, ‑‑refresh‑keys y ‑‑send‑keys y permite indicar el servidor de claves con el que se quiere trabajar para realizar una operación concreta. A partir de GPG 2.1 esta opción está marcada como obsoleta y se desrecomienda su uso en favor de la configuración directa del servidor en el fichero dirmngr.conf.

  • ‑‑list‑packets : Imprime por pantalla información sobre el archivo cifrado y/o firmado que le proporcionemos. No necesitamos usar esta opción para nada.

  • ‑‑list‑sigs : Es un alias para ‑‑list‑keys ‑‑with‑sig‑list.

  • ‑‑lsign‑key : Hace lo mismo que ‑‑sign‑key pero firmando sólo localmente. Esto significa que si exportamos la clave firmada, con la opción ‑‑export por ejemplo, la firma que hemos realizado no se exportará con ella.

  • ‑r, ‑‑recipient : Indica el destinatario de un mensaje cifrado asimétricamente. Siempre acompaña a la opción ‑‑encrypt. Podemos indicar el destinatario usando su clave primaria o indicando explícitamente la subclave con la que queremos cifrar el mensaje, utilizando el símbolo de exclamación: ID1!

  • ‑‑recv‑keys : Descarga del servidor la clave maestra que le indiquemos a través de su fingerprint a nuestro anillo local.

  • ‑‑refresh‑keys : Descarga del servidor las últimas actualizaciones disponibles de las claves que tenemos instaladas localmente (nuevas firmas, revocaciones, etc.).

  • ‑‑send‑keys : Envía al servidor la clave maestra que le indiquemos a través de su fingerprint. Esto sirve tanto para enviar una clave por primera vez como para enviar una actualización de la misma (una firma que hayamos realizado, una nueva subclave, etc.). La clave que enviemos al servidor no tiene por qué ser necesariamente nuestra.

  • ‑‑sign : Firma el archivo que le indiquemos. El archivo resultante obtenido (un binario, a no ser que le indiquemos que lo queremos en ASCII usando la opción ‑‑armor) contiene tanto el archivo original como la firma que hemos realizado sobre el mismo; decimos en este caso que la firma está acoplada al archivo.

  • ‑‑sign‑key : Firma el par 〈Clave, UID〉 que le indiquemos a través de su clave. Si no le indicamos el UID, y hay varios asociados a la clave, nos preguntará si queremos firmarlos todos. Si no deseamos firmarlos todos, se nos abrirá un prompt del menú ‑‑edit‑key donde deberemos seleccionar a través de la opción uid cuáles queremos firmar, tras lo cual escribiremos sign para proceder con la firma de los pares una vez seleccionados.

  • ‑‑try-all-secrets : Esta opción se debe ejecutar junto con ‑‑decrypt cuando recibamos un mensaje cifrado donde seamos un destinatario oculto del mismo (donde se haya usado la opción ‑‑hidden-recipient). Esta opción hará que GPG compruebe, una por una, todas las claves privadas que tenemos en nuestro anillo local, hasta que alguna sea capaz de descifrar el mensaje.

  • ‑v, ‑‑verbose : Proporciona más información durante el procesamiento de cualquier función. Debe especificarse al principio de la instrucción. Si se pasa este parámetro dos veces, la información mostrada es aún más detallada.

  • ‑‑verify : Al pasarle un archivo firmado (con la firma acoplada), hace una comprobación de la firma. Si queremos comprobar una firma desacoplada del archivo, debemos pasar como primer parámetro el archivo contenedor de la firma y como segundo parámetro el fichero a comprobar.

  • ‑‑verify‑files : Hace lo mismo que ‑‑verify, pero pudiendo pasarle varios archivos firmados como argumentos en lugar de solo uno. Esta función sólo se ejecuta para firmas incrustadas en los archivos originales, no para firmas desacopladas.

  • ‑‑with‑fingerprint : Al usar esta opción en conjunto con ‑‑list‑keys o ‑‑list‑secret‑keys se imprime la huella digital (fingerprint) de cada una de las claves primarias especificadas en la llamada (o todas, si no se especifica ninguna). Si queremos ver también las huellas digitales de las subclaves, debemos pasar este parámetro dos veces.

  • ‑‑with‑keygrip : Al usar esta opción en conjunto con ‑‑list‑keys o ‑‑list‑secret‑keys se imprime el keygrip de cada una de las claves primarias y subclaves especificadas en la llamada (o todas, si no se especifica ninguna).

  • ‑‑with‑sig‑check : Al usar esta opción en conjunto con ‑‑list‑keys o ‑‑list‑secret‑keys se imprime la lista de claves primarias especificadas en la llamada (o todas, si no se especifica ninguna) junto con todos los usuarios que la han firmado, y además se comprueban dichas firmas. Para que esta instrucción funcione correctamente, es requisito indispensable tener importadas las claves públicas de los usuarios que hayan firmado la clave. Esta función se comporta de modo idéntico a la función check del menú ‑‑edit‑key anteriormente vista.

  • ‑‑with‑sig‑list : Al usar esta opción en conjunto con ‑‑list‑keys o ‑‑list‑secret‑keys se imprime la lista de claves primarias especificadas en la llamada (o todas, si no se especifica ninguna) junto con todos los usuarios que la han firmado.

Veamos ahora algunos ejemplos de cómo se ejecutan las principales funciones. Para ello, supondremos que contamos con la siguiente lista de usuarios en nuestro anillo local.

Podemos resaltar que John Watson posee dos identificadores con dos correos electrónicos. Irene Adler por otro lado posee dos subclaves de cifrado, una RSA y otra ElGamal, y una subclave de firma DSA. James Moriarty utiliza una única clave maestra RSA que le sirve para firmar y para que le cifren mensajes.


Huella digital


Llamamos huella digital (fingerprint) de una clave pública al resultado de aplicar un algoritmo de hash sobre el conjunto formado por dicha clave pública e información adicional sobre la clave.

Actualmente, en PGP existen dos versiones de claves: PGP Version 3 (V3) y PGP Version 4 (V4). El estándar OpenPGP se basa en V4, refiriéndose a él como el formato nuevo, mientras que a V3 se refiere como el formato antiguo.

En la V4 de las claves se utiliza SHA1 como algoritmo de resumen de la huella digital. La información que se tiene en cuenta de la clave a la hora de ser resumida es:
  • Versión de la clave: 4
  • Sello temporal del instante de creación de la clave
  • Algoritmo asimétrico asociado a la clave: 3 = RSA (ejemplo para clave RSA que sólo firma)
  • Los campos que componen la clave en sí. En RSA por ejemplo serían:
    • El módulo n utilizado.
    • El exponente público e de cifrado.

Alternativamente, existe un concepto muy parecido al de huella digital, aunque mucho menos documentado, conocido como keygrip. El keygrip es el resultado de hashear únicamente la clave pública, sin información adicional como en el caso de la huella digital. Esto convierte al keygrip de una clave en algo independiente de la implementación del algoritmo que se emplee para dicha clave, por lo que, teóricamente, una misma clave empleada en OpenSSH y en OpenPGP debería arrojar el mismo keygrip, pero no el mismo fingerprint.

El objetivo tanto del fingerprint como del keygrip es el de poder identificar exclusivamente una clave. Podemos utilizar cualquiera de ellos para hacer una comprobación rápida de la clave de una persona, sin tener que examinar dicha clave por completo bit a bit. Y, aunque ambos utilizan SHA1 actualmente en sus implementaciones y ésto puede generar colisiones con cierto grado de probabilidad (SHA1 consta de 160 bits), la probabilidad real de que una persona sea capaz de generar unas claves operativas que arrojen el mismo fingerprint y/o keygrip que los de otra persona con el fin de suplantarla es prácticamente inexistente, debido a la inviabilidad computacional del cálculo de todas las posibilidades hasta hallar una válida.

Veamos un ejemplo que nos muestre la huella digital y el keygrip de todas las claves y subclaves del usuario Sherlock Holmes:

Quiero resaltar que, si nos fijamos en las líneas que comienzan con pub y sub, se puede ver un "identificador corto" de cada clave, que no es más que los últimos 4 bytes en hexadecimal del fingerprint de cada una, tal y como podemos apreciar.

También quiero destacar que para filtrar únicamente las claves de Sherlock, ha bastado con poner su nombre acompañando a la instrucción de listado. También funcionaría poner el e-mail o cualquier otro dato que lo identifique exclusivamente (el apellido por ejemplo). Todo esto se debe al potente detector de expresiones regulares que viene integrado en GPG, y que nos permite filtrar un usuario de esta manera tan sencilla. Dejo más información acerca de cómo localizar a un usuario en las referencias, extraídas directamente del manual de GPG.

Para un usuario doméstico corriente, utilizar el identificador corto en lugar del fingerprint completo a la hora de seleccionar una clave no suele suponer ningún problema, ya que la probabilidad de que tengamos instaladas en nuestro anillo local dos claves que compartan los últimos 32 bits no es demasiado elevada. No obstante, si estamos programando o manejando GPG de alguna manera automatizada, deberíamos utilizar siempre el fingerprint al completo (y sin espacios entre cada par de bytes).


Cifrar un archivo


Una de las cosas que mucha gente no sabe respecto a los algoritmos de cifrado asimétricos es que son muy lentos en comparación con los simétricos. Tampoco es difícil imaginarlo, visto que incluso las claves son tremendamente largas en comparación (256 bits en AES frente a 4096 bits en RSA como topes).

Es por esto que, cuando utilizamos las opciones ‑‑recipient y ‑‑encrypt para cifrar un mensaje de forma asimétrica para uno o varios usuarios, el mensaje en sí se cifra de forma simétrica con alguno de los algoritmos que el receptor tenga en su lista de preferencias (y si hay varios receptores, se busca un algoritmo que sea común a todos), generando una clave aleatoria para dicho cifrado. Y es esta clave la que se cifra de forma asimétrica utilizando la clave pública del destinatario del mensaje.

Todo esto es gestionado internamente por GPG de forma automática, de modo que para el receptor del mensaje, el descifrado de la clave simétrica y posterior descifrado real del mensaje se efectúa de manera transparente.

Aquí tenemos un ejemplo de un mensaje escrito por Watson, cifrado en binario, y dirigido a Sherlock Holmes e Irene Adler, forzando además el uso de la clave ElGamal de Irene en lugar de dejar que el programa decida (añadimos la opción ‑‑verbose para que el programa nos informe de lo que ocurre entre medias):

Vemos que el programa nos indica que las claves nos pertenecen. Esto se debe a que tenemos instaladas las claves privadas de Sherlock e Irene en nuestro anillo local. También vemos que se utiliza AES256 para cifrar el archivo.

Podemos combinar el cifrado asimétrico con un cifrado simétrico para que el archivo pueda ser descifrado por cualquiera que conozca la contraseña simétrica, sin necesidad de ser un receptor explícito del mensaje, como en este ejemplo donde le escribimos a Moriarty pero permitimos que cualquiera con la contraseña pueda leer el mensaje. Además, el mensaje cifrado se almacena esta vez como ASCII en base64 y no como binario:

Es fácil descifrar cualquier archivo, ya que GPG se encargará de mirar si somos destinatarios o no del mismo, o si viene cifrado simétricamente para que únicamente tengamos que introducir la contraseña. Además, si no estamos seguros de qué extensión tiene el archivo sin cifrar a la hora de usar la opción ‑‑output, podemos pasarle la opción ‑‑decrypt-files, que guardará el archivo descifrado con la extensión correcta en la misma carpeta que el cifrado:


Firmar un archivo


La firma digital es un sistema que nos permite implementar dos características muy importantes e interesantes en computación: integridad y no repudio en origen.

Decimos que, en el transcurso de una comunicación entre dos partes, un mensaje es íntegro cuando no ha sido modificado por terceros: el mensaje enviado por el emisor es el mismo que el recibido por el receptor, sin alteraciones por el camino. También decimos que un mensaje no puede ser repudiado en origen cuando el emisor del mensaje no puede negar su autoría tras haberlo enviado.

La firma digital funciona en la práctica y dicho de forma muy simplificada, como un "cifrado a la inversa". El emisor de un mensaje lo cifra con su clave privada, y cualquier persona puede descifrarlo usando la clave pública del emisor: cualquiera puede verificar la firma realizada.

De este modo, como el mensaje sólo puede ser descifrado con la clave pública del emisor, sabemos que es él realmente quien lo ha firmado: no puede negar su autoría. Y, de igual modo, si en el transcurso de una comunicación entre dos partes, un tercero interfiriese y decidiese suplantar a una de las partes modificando los mensajes entre medias, al no poseer la clave privada de dicha persona, no podría firmarlos en su nombre, por lo que la otra parte se daría cuenta instantáneamente del engaño.

Habiendo establecido ya que firmar un archivo en realidad es sólo otro mecanismo de cifrado más, quiero ser más específico e indicar que lo que realmente se firma no es el archivo en sí, sino un resumen del mismo efectuado con algún algoritmo de hash (SHA1, SHA256, SHA512...). Esto no debería suponernos ninguna sorpresa a estas alturas tras saber ya que el cifrado asimétrico de un archivo no es tal en realidad, sino un envoltorio para un cifrado simétrico subyacente.

Por el mismo motivo que antes, esto se hace así debido al excesivo tiempo de cómputo que requiere cifrar (firmar) un mensaje con un algoritmo asimétrico, por lo que decidimos sencillamente firmar un resumen de dicho mensaje, ya que no requerimos en realidad de la ocultación de los datos originales si lo que pretendemos es estrictamente firmar digitalmente (aunque podemos combinar firma y encriptación de los datos, como ahora veremos).

De este modo, el procedimiento para comprobar una firma consiste en calcular por nuestros medios (GPG lo hace automáticamente por nosotros) el hash del archivo a comprobar, y luego descifrar la firma recibida para obtener el hash del archivo que el emisor del mensaje firmó originalmente, y comprobar que ambos coincidan.

Vamos a ver un ejemplo de cómo obtener la firma binaria de un archivo (bastaría con añadir la opción ‑‑armor para que pudiera ser abierta con cualquier editor de textos) realizada por la subclave de firma de Irene Adler y por Sherlock Holmes (sí, un archivo puede ir firmado por varias personas):

Podemos verificar las firmas, o bien extraer el mensaje del archivo firmado (que incluye también verificar las firmas) del siguiente modo:

Si decidimos firmar un archivo pero mantener la firma desacoplada del mismo, tal que así:

entonces tendremos que pasarle a la opción ‑‑verify tanto el archivo de firma como el archivo original, para que haga la comprobación:

También podemos firmar un archivo en claro, siempre y cuando dicho archivo pueda ser abierto con un editor de textos de antemano. Si no es así (en el caso de un binario por ejemplo como un documento de LibreOffice), el archivo se corromperá casi con total seguridad:

Lo que, al abrirlo con un editor de textos, nos mostraría lo siguiente:

Este archivo firmado en claro puede ser verificado o puede desacoplarse el mensaje en sí de la firma con las opciones ‑‑verify y ‑‑decrypt o ‑‑decrypt-files que hemos visto.


Firmar una clave


Supongamos que Sherlock desea firmar la clave de Watson y que, además, se ha asegurado al 100% de que su nombre es realmente John Watson y que su correo electrónico es el que se indica en el UID que lleva ese nombre exacto. Sin embargo, Sherlock nunca ha oído que Watson tuviese un segundo nombre que empezase por H, de modo que decide que no va a firmar ese segundo UID suyo. En ese caso, Sherlock procedería del siguiente modo:

Pero ahora llega Irene Adler y decide que quiere firmar únicamente y además de manera irrevocable, el UID que marca John H. Watson, pero que sólo ha hecho una comprobación informal de su identidad; no ha sido tan meticulosa como Sherlock. En ese caso podría hacer lo siguiente, evitando además que GPG le pregunte por su nivel de rigor a la hora de certificar a Watson, ya que lo indica explícitamente en la llamada a la función de firma:

Moriarty por su parte desea certificar los dos UIDs de John, pero sólo localmente, y además no ha verificado en absoluto su identidad:

Ahora, para ver y comprobar la validez de la lista de firmas de John, hacemos lo siguiente:

Vemos una R al lado de la firma de Irene, que indica que la firma es irrevocable, y una L al lado de la firma de Moriarty, que indica que la firma sólo tiene validez localmente; no puede ser exportada.

Es muy importante que todas nuestras claves vayan firmadas por nosotros mismos (GPG lo hace automáticamente al crearlas), ya que, dado que la distribución de nuestra clave pública la puede hacer cualquiera en cualquier medio, es posible para un atacante anexar un UID o una clave arbitrarios a nuestra clave maestra e intentar hacerlo pasar como nuestros sin nuestro conocimiento.

A modo de ejemplo, podríamos suponer que Moriarty intenta hacerse pasar por Sherlock, y distribuye esta clave de Sherlock modificada por él, donde ha añadido un e-mail suyo para intentar engañar a todos los que reciban la clave, y le escriban a él en lugar de a Sherlock:

Lo único que Moriarty no puede hacer es autofirmar el nuevo UID que ha añadido, ya que no tiene la clave privada de Sherlock. De este modo vemos cómo el autofirmado es realmente una primera línea de defensa frente a la suplantación de identidad.

Por último, quiero dejar muy claro que para firmar la clave de otra persona siempre se utiliza una clave primaria, nunca una subclave.


Servidores de claves


Una forma cómoda y fácil de distribuir nuestras claves y de obtener claves de otras personas, es a través de los servidores de claves PGP. Además, si realizamos alguna modificación sobre nuestra clave maestra (extender la fecha de caducidad, añadir una subclave, revocación de un uid o una clave, cambios en las preferencias de los algoritmos de cifrado, etc.) podemos resubir nuestra clave con las actualizaciones pertinentes, y el resto del mundo podrá descargar dichos cambios desde el servidor central, sin necesidad de que se lo comuniquemos personalmente.

Además, existe una ventaja añadida en el uso de servidores PGP, y es que la mayoría de ellos están sincronizados entre sí. De modo que aunque sólo subamos nuestros cambios a uno de ellos, eventualmente, todos estarán actualizados sin tener que hacerlo manualmente nosotros.

También podemos subir claves ajenas a los servidores PGP si, por ejemplo, las hemos firmado. O incluso si hemos revocado una firma sobre una clave ajena, también deberemos informar al servidor de ello, para que todas las personas que se conectan al servidor para mantener sus claves actualizadas reciban dichos cambios.

En mi caso, voy a utilizar uno de los servidores de claves más populares que existen, el del MIT (https://pgp.mit.edu) aunque el de RedIRIS es también una buena opción (https://pgp.rediris.es/) y, como ya he dicho, se mantienen sincronizados entre sí.

Así que, sin más dilación, vamos a enviar la clave de James Moriarty al servidor del MIT. Unos minutos después podremos ver cómo aparece en RedIRIS y en otros tantos servidores PGP:

Al enviarse una clave pública, se envía todo: firmas sobre la clave, subclaves, UIDs y posibles revocaciones sobre alguna subclave o sobre la clave maestra.

Si queremos que se utilice siempre el servidor del MIT sin tener que indicarlo explícitamente en cada llamada, podemos modificar la siguiente línea del archivo ~/.gnupg/dirmngr.conf:

sustituyéndola por esta otra:

Tras lo cual será necesario matar el servicio dirmngr para forzarlo a cargar la nueva configuración. Nada más sencillo para ello que escribir lo siguiente en el terminal:

Si queremos importar una clave del servidor conociendo su huella digital, basta con hacer:

Si queremos actualizar las claves de nuestro anillo en caso de que una clave haya recibido nuevas firmas, o el propietario haya revocado algún certificado o añadido alguna nueva subclave:

Resulta práctico ejecutar de vez en cuando la función clean sobre las claves de nuestro anillo local, para optimizar el espacio utilizado por cada una y no almacenar una gran cantidad de firmas inútiles para nosotros:

Como vemos, al ejecutar esta función se han eliminado tres autofirmas de la clave por ser redundantes, y sólo ha dejado la más reciente, con lo que hemos ahorrado espacio en disco sin perder información.


Revocación de claves


Una de las primeras cosas que hay que hacer tras generar nuestro par de claves, es generar el correspondiente certificado de revocación para tenerlo a buen recaudo en caso de necesitarlo. Para ello, escribimos lo siguiente en un terminal, indicando la ID de la clave maestra cuyo certificado de revocación queramos crear. Vamos a generar el certificado de revocación de la clave maestra de Moriarty:

Los certificados de revocación se guardan como ficheros ASCII. Una vez revocada una clave maestra, no hay vuelta atrás.

Si estamos muy seguros de lo que estamos haciendo, podemos revocar nuestra clave maestra importando el certificado de revocación generado y posteriormente subiendo la clave ya revocada al servidor:

Si ahora listamos las claves, veremos que la de Moriarty aparece ya como revocada:

Si por el contrario sólo queremos revocar una subclave nuestra, o una firma realizada a otra persona, deberemos hacerlo desde el menú de ‑‑edit‑key y luego subir los cambios al servidor. En este ejemplo, Sherlock Holmes revoca la firma que había realizado sobre John Watson:


¡Y se acabó! He intentado cubrir absolutamente todo lo que es importante en GPG. He invetido muchísimas horas en este artículo / manual, y espero de verdad que pueda resultar de mucha ayuda.

Honestamente, considero GPG como una grandísima herramienta, compleja a la par que potente, que todo el mundo, y no sólo los informáticos, debería saber usar en la era en la que vivimos.

Si aún tienes dudas, siempre está la sección de comentarios para plantear lo que sea. Y si te ha gustado el artículo, ¡compártelo!


Referencias:
  • Challenge–response authentication [Link]
  • Crear, publicar, firmar y más comandos para gestionar claves GPG en Linux [Link]
  • GNU Privacy Guard Documentation [Link]
  • GPG Encryption Guide - Part 1 [Link]
  • GPG - why am I encrypting with subkey instead of primary key? [Link]
  • Grafo de Sincronización de los Servidores PGP [Link]
  • How to Specify a User Id [Link]
  • How to use a GPG key for SSH authentication [Link]
  • Internet Security: Cryptographic Principles, Algorithms and Protocols [Link]
  • Introducción a GPG - Cifrado Simétrico [Link]
  • Introducción a la criptografía. ¿Es necesario cifrar? Criptografía simétrica y asimétrica. [Link]
  • Is it possible to use a GPG or SSH key for web based authentication in a secure fashion? [Link]
  • Keygrip v fingerprint? [Link] [Link 2]
  • Manual de GPG: cifra, firma y envía datos de forma segura [Link]
  • MIT PGP Public Key Server [Link]
  • OpenPGP Best Practices [Link]
  • PGP and SSH keys on a Yubikey NEO [Link]
  • PGP Web of Trust: Core Concepts Behind Trusted Communication [Link]
  • Public key fingerprint [Link]
  • RFC 4880 - OpenPGP Message Format: 9.1. Public-Key Algorithms [Link]
  • RFC 4880 - OpenPGP Message Format: 12.2. Key IDs and Fingerprints [Link]
  • RFC 4880 - OpenPGP Message Format: 13.3.2. Hash Algorithm Preferences [Link]
  • Subkeys - Debian Wiki [Link]
  • The GNU Privacy Guard [Link]
  • Understanding Key Versions [Link]
  • Using GnuPG (2.1) for SSH authentication [Link]
  • Validating other keys on your public keyring [Link]
  • What is validity in terms of PGP 6.5.8? [Link]
  • Why should I sign my own public key? [Link]

No hay comentarios:

Publicar un comentario