¿Cómo firmar archivos con las herramientas de línea de comandos de Ubuntu y mis propias claves?

14

Quiero firmar algunos archivos de código Python que escribí, porque son módulos enchufables para uno de mis proyectos. Para distribuirlo, quiero que el usuario pueda estar seguro de que un complemento está verificado y seguro (porque lo escribí yo o alguien en quien confío) y no fue modificado.

El software es solo un proyecto de hobby de código abierto, por lo tanto, no quiero gastar dinero para comprar un certificado oficial. En cambio, supongo que el programa principal siempre es válido y se puede confiar sin verificación adicional. Si alguien lo descarga desde cualquier otra ubicación que no sea mi repositorio GitHub, es su culpa.

Por lo que he leído, la firma generalmente se realiza creando un par de claves asimétricas, calculando un valor hash criptográfico fuerte (por ejemplo, SHA-512) del archivo de código, encriptando el hash usando mi clave privada y almacenando esa firma en un archivo separado para ser enviado con el archivo de código original.
El programa principal tendrá que descifrar la firma utilizando la clave pública que se guarda en texto plano en el código fuente del programa principal, calcular la misma función hash del archivo de código y luego compararla con la descifrada. Si coinciden, se puede confiar en el complemento.

Entonces ahora mi pregunta:

¿Cómo puedo crear fácilmente un par de claves asimétricas fuertes con las herramientas de Ubuntu y cómo puedo calcular fácilmente un valor criptográfico hash de un archivo?
Automatizar el proceso de firma en un script (usando siempre la misma clave) sería genial.

Byte Commander
fuente

Respuestas:

19

Gran parte de esta respuesta está arrancada de Arch Wiki y de la documentación de GnuPG . Cualquier recomendación en esta respuesta es puramente mi opinión, y debe tomarse con una tonelada de sal.

Crear una clave PGP

GUI

  1. Abra la aplicación Contraseñas y claves (también conocido como seahorse), y haga clic +(o vaya a Archivo -> Nuevo , o presione CtrlN) para ver:

    diálogo de nuevo elemento para Seahorse

  2. Seleccione la clave PGP e ingrese sus datos. Me estoy haciendo pasar por Byte Commander:

    diálogo de detalles clave

    RSA y 2048 bits están bien para la mayoría de los propósitos. Si solo desea usarlo para firmar, elija la opción RSA (solo firmar) del menú desplegable, pero no debería necesitarlo; esto se puede manejar usando subclaves . Puedes dejar un comentario. Mantener una fecha de caducidad en su clave también es útil. Haga clic Create.

  3. Ingrese una contraseña adecuadamente larga (y quiero decir larga , mi ejemplo es corto, IMO), y haga clic en Ok:

    diálogo de entrada de contraseña

    Seahorse no parece tener ningún comentario, a diferencia de la CLI. Espere un momento, haciendo lo que quiera hacer, mientras recoge la entropía y crea una clave. Podría tomar un tiempo. Después de lo cual, verá que ingresan en la sección Claves PGP :

    lista de claves pgp

CLI

Para generar una clave desde la línea de comando, simplemente ejecute gpg --gen-key. Le pedirá los mismos detalles que hizo la GUI:

$ gpg --gen-key 
gpg (GnuPG) 1.4.16; Copyright (C) 2013 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 
Requested keysize is 2048 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 1y
Key expires at Tuesday 27 September 2016 03:45:19 PM IST
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and E-mail Address in this form:
    "Heinrich Heine (Der Dichter) <[email protected]>"

Real name: Byte Commander
E-mail address: [email protected]
Comment: 
You selected this USER-ID:
    "Byte Commander <[email protected]>"

Change (N)ame, (C)omment, (E)-mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.

passphrase not correctly repeated; try again.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, use the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy!  (Need 186 more bytes)
.....+++++
+++++
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, use the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy!  (Need 80 more bytes)
....+++++

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy!  (Need 83 more bytes)
...+++++
gpg: key 8AE670A6 marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   2  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: next trustdb check due at 2016-09-26
pub   2048R/8AE670A6 2015-09-28 [expires: 2016-09-27]
      Key fingerprint = 82D9 0644 B265 8E75 1E01  538B B479 3CF4 8AE6 70A6
uid                  Byte Commander <[email protected]>
sub   2048R/0E2F4FD8 2015-09-28 [expires: 2016-09-27]

Observe cómo GnuPG nos dice que necesita más entropía. Deseo caballito de mar también. Pero, de nuevo, parece que GnuPG está actuando como Oliver Twist. :PAG

Publicando su clave

Ahora, necesitamos obtener nuestra clave pública, para que las personas puedan verificar las cosas que la usan.

GUI

Regrese a la lista de claves PGP en la seahorseaplicación (vea la última captura de pantalla). Seleccione las claves que desea exportar y, en el menú Remoto , seleccione Sincronizar y publicar claves :

ingrese la descripción de la imagen aquí

El Syncbotón se desactivará si no ha seleccionado un servidor para publicar. Hazlo haciendo clic en el Key Serversbotón:

ingrese la descripción de la imagen aquí

Elegí el servidor de Ubuntu.

Ahora, puede hacer clic en el Syncbotón y publicarlo en el servidor de claves de Ubuntu (¡perdón por el spam, Ubuntu!).

CLI

Con la CLI, necesita la ID de la clave que desea publicar. Es la última línea de la salida al crear la clave ( 8AE670A6). Si no recuerdas qué es, solo corre gpg --list-keys. A publicar:

$ gpg  --keyserver pgp.mit.edu --send-keys 8AE670A6
gpg: sending key 8AE670A6 to hkp server pgp.mit.edu

Lo siento, MIT .

Firma

Todavía no conozco un método GUI conveniente para firmar un documento.

Una vez que haya creado el archivo que desea firmar, diríjase a la terminal. Prueba gpg --list-keys:

$ gpg --list-keys       
/home/muru/.gnupg/pubring.gpg
---------------------------
pub   2048R/F7878B0C 2015-09-28 [expires: 2016-09-26]
uid                  Byte Commander <[email protected]>
sub   2048R/345B9A4F 2015-09-28 [expires: 2016-09-26]

Puede firmar el archivo usando dos métodos:

Firmando con encriptación

$ gpg --sign --output examples.sig examples.desktop 

You need a passphrase to unlock the secret key for
user: "Byte Commander <[email protected]>"
2048-bit RSA key, ID F7878B0C, created 2015-09-28

gpg: Invalid passphrase; please try again ...

You need a passphrase to unlock the secret key for
user: "Byte Commander <[email protected]>"
2048-bit RSA key, ID F7878B0C, created 2015-09-28

Si estás en una sesión de escritorio, es probable que te reciban con una solicitud de contraseña gráfica. Por ejemplo, en GNOME:

ingrese la descripción de la imagen aquí

Si el destinatario tiene su clave pública, puede verificarla u obtener el contenido descifrado:

$ gpg --verify examples.sig
gpg: Signature made Monday 28 September 2015 03:25:00 PM IST using RSA key ID F7878B0C
gpg: Good signature from "Byte Commander <[email protected]>"
$ gpg --decrypt examples.sig
[Desktop Entry]
Version=1.0
Type=Link
Name=Examples
Name[aa]=Ceelallo
...
URL=file:///usr/share/example-content/
Icon=folder
X-Ubuntu-Gettext-Domain=example-content

gpg: Signature made Monday 28 September 2015 03:25:00 PM IST using RSA key ID F7878B0C
gpg: Good signature from "Byte Commander <[email protected]>"

Firmando con texto claro

Es posible que no desee cifrar el contenido, por ejemplo, al enviar un correo. En cuyo caso, use la --clearsignopción:

$ gpg --clearsign examples.desktop 

You need a passphrase to unlock the secret key for
user: "Byte Commander <[email protected]>"
2048-bit RSA key, ID F7878B0C, created 2015-09-28

$ cat examples.desktop.asc 
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

[Desktop Entry]
Version=1.0
Type=Link
Name=Examples
Name[aa]=Ceelallo
...
URL=file:///usr/share/example-content/
Icon=folder
X-Ubuntu-Gettext-Domain=example-content

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQEcBAEBAgAGBQJWCRAaAAoJEGUZkqX3h4sMBWsH/1yw+G0v5Ck+T3PBS90SkvC8
5C0FJeGVr0AgYQohhsE3zEGQ7nn53N7JsvNlF6VccvN99DZIp18JbrJ+qs5hWjtg
KU/ACleR5dvVrJgfjppkuC8Q3cAudvqciKlLjA7Xycr3P49oCNCy8k/ue2TrgCvS
mMb5IS/kqpO7wrOMBAR0c/2CjQsA91S1/YK7DbuUqeNgEzW1grsI7XZPhiDGpAib
D20HWrbdLhklAEJuo1EvuOIggW6MF6ksxDoVapsUzQalD0TWEq6OnvzIS5qhITrc
XaDPQJpiHyCyINnL5aZCUwr2uon7osJ+2a8Ahp1REpzIZTdND9jA5NWSel5+yAs=
=ZrtB
-----END PGP SIGNATURE-----

Firma, con un archivo separado para la firma (firma separada)

Por último, para algunos archivos, no puede tener la firma en el documento. Por ejemplo, los archivos de empaquetado o los metadatos para un repositorio, ambos tienen contenido de una naturaleza específica que no permite fácilmente las firmas incrustadas. En este caso, usa la --detached-sigopción:

$ gpg --output examples.desktop.sig --detach-sign examples.desktop

You need a passphrase to unlock the secret key for
user: "Byte Commander <[email protected]>"
2048-bit RSA key, ID F7878B0C, created 2015-09-28

$ gpg --verify examples.desktop.sig examples.desktop
gpg: Signature made Monday 28 September 2015 03:35:55 PM IST using RSA key ID F7878B0C
gpg: Good signature from "Byte Commander <[email protected]>"

Nota

En cifrado + firma y en firmas separadas, la salida de gpges binaria. Puede hacer que GnuPG envíe datos codificados en base64 utilizando la --armoropción (blindado ASCII).

Automatización

Para firmar el script, puede:

  • use una frase de contraseña vacía para la clave
  • dependiendo de su versión de GnuPG, envíe la frase de contraseña a través de stdin. Vea esta publicación de Unix y Linux para algunas opciones.
muru
fuente
Muy buena y detallada respuesta. Pero sobre las claves de ejemplo que creaste ... No sé si estoy muy contento con el hecho de que hay un conjunto de claves no utilizadas para mi seudónimo. Si quiero crear claves reales con ese nombre más tarde y usarlas, las personas que las buscan pueden confundirse. Supongo que sus claves de ejemplo y mis claves reales podrán coexistir debido a diferentes direcciones de correo electrónico y, por lo tanto, obtendrán una ID diferente, pero aún así ... ¿Es posible que pueda eliminar esas claves nuevamente?
Byte Commander
@ByteCommander el término es revocar . Me ocuparé de revocarlos. Para el caso, debo agregar una sección sobre revocación de claves.
muru
@ByteCommander lo siento, eliminé la clave que publiqué (y no había emitido un certificado de revocación (error clásico n00b), así que no puedo revocar esa clave. Sin embargo, tiene una caducidad de un año, así que, bueno, cualquier confusión se resolverá en un año.
Muru
De acuerdo, bueno, eso sucede. No estoy seguro de si debería estar molesto o solo reírme de ese estúpido error ... Creo que para mi proyecto en cuestión preferiría usar el módulo Python rsaque permite fácilmente firmar datos sin tener que lidiar con todas las cosas de GPG. Eso podría ser muy útil una vez que comience a publicar y empaquetar software de verdad, pero probablemente sea demasiado para mi propósito en este momento. Entonces, hasta entonces, ¡probablemente expire! :)
Byte Commander
@ByteCommander ambos, supongo. Aunque te sugiero que uses tu nombre real al crear tu clave, y dejes el nick para el campo de comentario.
muru
4
  1. Crea una clave asimétrica con gpg

    gpg --gen-key
    
  2. Use gpg para firmar su archivo (se usa su clave privada)

    gpg --output foo.sig --detach-sig foo.py
    
  3. Probar el archivo de firma (se usa su clave pública)

    gpg --verify foo.sig foo.py
    

    Salida de ejemplo

    % gpg --verify foo.sig foo.py 
    gpg: Signature made Mo 28 Sep 2015 12:46:04 CEST using RSA key ID 89B30DEC
    gpg: Good signature from "Your Name <[email protected]>"
    
    % echo "bad" >> foo.py
    
    % gpg --verify foo.sig foo.py
    gpg: Signature made Mo 28 Sep 2015 12:46:04 CEST using RSA key ID 89B30DEC
    gpg: BAD signature from "Your Name <[email protected]>"
    
AB
fuente