¿Es posible firmar un archivo con una clave ssh?

36

Yo uso SSH (OpenSSH 5.5p1 en Linux, para ser precisos). Tengo una clave, en la que tengo una frase de contraseña. Lo uso para el inicio de sesión habitual en las cosas de las computadoras.

¿Puedo usarlo también para firmar archivos?

Según tengo entendido, una clave SSH es una clave RSA (o DSA), y durante el proceso de inicio de sesión SSH, se utiliza para firmar mensajes enviados al servidor. Entonces, en principio y en la práctica, se puede usar para firmar cosas; de hecho, ese es su único propósito.

Pero hasta donde puedo ver, no hay forma de usar la clave para firmar un archivo arbitrario (como lo haría con PGP, por ejemplo). Hay alguna manera de hacer esto?

Tom Anderson
fuente
¿OpenSSH no usa Ed25519 como protocolo de datos ? Parece solo una cuestión de herramientas.
Pablo A

Respuestas:

24

Es posible que no haya una manera de hacer esto solo con las herramientas de OpenSSH.

Pero se puede hacer con bastante facilidad con las herramientas OpenSSL. De hecho, hay al menos dos formas de hacerlo. En los ejemplos a continuación, ~/.ssh/id_rsaes su clave privada.

Una forma es usar dgst :

openssl dgst -sign ~/.ssh/id_rsa some-file

El otro está usando pkeyutl :

openssl pkeyutl -sign -inkey ~/.ssh/id_rsa -in some-file

Ambos escriben una firma binaria en la salida estándar. dgst toma una -hexopción imprimirá una representación textual, con algunos detalles sobre la forma de la firma. pkeyutl toma una -hexdumpopción que es un poco menos útil. Ambos aceptarán las claves RSA y DSA. No tengo idea de cuál es el formato de la salida. Los dos comandos producen diferentes formatos. Tengo la impresión de que pkeyutl se considera más moderno que dgst .

Para verificar esas firmas:

openssl dgst -verify $PUBLIC_KEY_FILE -signature signature-file some-file

y:

openssl pkeyutl -verify -inkey $PUBLIC_KEY_FILE -sigfile signature-file -in some-file

El problema aquí es $PUBLIC_KEY_FILE. OpenSSL no puede leer el formato de clave pública de OpenSSH, por lo que no puede usarlo id_rsa.pub. Tienes algunas opciones, ninguna ideal.

Si tiene una versión de OpenSSH de 5.6 o posterior, aparentemente puede hacer esto:

ssh-keygen -e -f ~/.ssh/id_rsa.pub -m pem

Que escribirá la clave pública en la salida estándar en formato PEM, que OpenSSL puede leer.

Si tiene la clave privada, y es una clave RSA, puede extraer la clave pública de ella (supongo que el archivo de clave privada codificada por PEM incluye una copia de la clave pública, ya que no es posible derivar la clave pública de la clave privada en sí), y use eso:

openssl rsa -in ~/.ssh/id_rsa -pubout

No sé si hay un equivalente DSA. Tenga en cuenta que este enfoque requiere cierta cooperación del propietario de la clave privada, que tendrá que extraer la clave pública y enviarla al posible verificador.

Por último, puede usar un programa Python escrito por un tipo llamado Lars para convertir la clave pública de OpenSSH a formato OpenSSL.

Tom Anderson
fuente
1
Solo me gustaría señalar que "no es posible derivar la clave pública de la clave privada" no es cierto. En la práctica (es decir, en todos los sistemas criptográficos que realmente se utilizan), la clave pública se deriva fácilmente de la clave privada la mayor parte del tiempo.
kirelagin
@kirelagin: No lo sabía. ¿Podría decirme o vincularme a más información sobre cómo se puede hacer eso?
Tom Anderson
1
No estoy seguro de si hay alguna lectura en particular sobre este tema ... Pensemos en ello. Tome cualquier criptosistema basado en registro discreto (ElGamal). En este caso, la clave privada es (tamaño del grupo, generador, potencia) y la clave pública es (tamaño del grupo, generador, generador ^ potencia). Por lo tanto, el registro es difícil, pero el poder no lo es, solo calcule.
kirelagin
En el caso de RSA, esta inversión es realmente difícil, pero aquí la situación es ligeramente diferente. La clave pública es (n, d) y la clave privada es (n, d ^ (- 1) mod phi (n)). Invertir d también sería difícil si no almacenaras phi (n), pero aquí está el truco: casi todos usan e = 65537 (cuando generas una clave hay una opción para cambiar este valor predeterminado, pero nunca he visto cualquiera que lo use porque no tiene ningún sentido práctico), por lo que derivar una clave pública de una privada es trivial.
kirelagin
Con las curvas elípticas, en realidad es lo mismo que con el registro discreto y la potencia, invertir es fácil. Dicho esto, no estoy seguro acerca de otros criptosistemas, pero esos tres son los que se usan en la práctica.
kirelagin
10

La respuesta de @ Tom me ayudó a comenzar, pero no funcionó de manera inmediata.

Estos comandos funcionarán con:

  • OpenSSL 1.0.1 14 de marzo de 2012
  • OpenSSH_5.9p1

Usando pkeyutl

# openssl pkeyutl -sign -inkey ~/.ssh/id_sample -in $1 > $1.sig
# ssh-keygen -e -f ~/.ssh/id_sample.pub -m PKCS8 > pub
# openssl pkeyutl -verify -pubin -inkey pub -in $1 -sigfile $1.sig
Signature Verified Successfully

Usando dgst

# openssl dgst -sign ~/.ssh/id_sample $1 > $1.sig
# ssh-keygen -e -f ~/.ssh/id_sample.pub -m PKCS8 > pub
# openssl dgst -verify pub -signature $1.sig $1
Verified OK

La versión pkeyutl solo puede firmar archivos de pequeño tamaño. Mientras que dgst puede firmar archivos arbitrariamente grandes, porque toma un resumen antes de firmar el resultado.

stephen.z
fuente
Para mí también, la respuesta de Stephen.z funcionó de manera inmediata. Primero seguí jugando con la respuesta de Tom por un tiempo y finalmente encontré que la respuesta de Stephen.z funcionaba perfectamente para mí. Gracias Stephen.z!
Grzegorz Wierzowiecki
PD: aquí he compartido mis fragmentos: gist.github.com/gwpl/2c7636f0b200cbfbe82cc9d4f6338585
Grzegorz Wierzowiecki
¿Intentaste usar pkeyutl para firmar solo el hash del archivo?
Gaia
-3

Para verificar esas firmas : solución más fácil:

La forma más fácil de asegurarse de que un documento firmado sea el mismo, es volver a generar el archivo de firma digital y luego usar diff para verificar si los dos archivos de firma son iguales.

Ehrhardt Le Grange
fuente
3
Estás pensando en hashes , no en firmas . Similar, pero no igual: el hash solo verifica que el archivo no haya cambiado; una firma también verifica de dónde vino.
Piskvor