4.5.4. Autenticación de clave pública

Nota

Una perfecta compresión de este apartado exige tener unos conocimineots mínimos sobre Criptografía.

Las técnicas de cifrado asimétrico se usan en el protocolo SSH para la autenticación tanto de servidor como de cliente. En el caso del segundo, también es posible la autenticación con contraseña, que es justamente la que hemos visto hasta ahora.

Cuando se usa autenticación con clave pública hay dos posibilidades:

  • Una solución basada exclusivamente en el uso de claves asimétricas

  • Otra que, sobre la base de la anterior, genera certificados digitales a partir de las claves públicas utilizando una infraestructura PKI.

Como para analizar la segunda solución es conveniente conocer la primera, analizaremos la primera y, sobre ella, expondremos la segunda.

4.5.4.1. Claves

Analicemos por separado cómo se identifica el servidor ante el cliente y cómo lo hace el cliente ante el servidor.

4.5.4.1.1. Identificación del servidor

Ya se ha mencionado anteriormente que para evitar ataques man-in-the-middle mediante la suplantación de la identidad del servidor, éste envía al cliente su clave pública. En la primera conexión aceptar la clave pública de un servidor es un acto de fe, a menos que se haya obtenido esa clave pública de algún modo seguro. Sea como sea, el cliente, por su parte, puede almacenar las claves públicas de todos los servidores a los que se conecta, de modo que si se produce una segunda conexión compara la clave pública que le vuelve a enviar el servidor con la que previamente tiene almacenada. En realidad lo que compara es el fingerprint o huella dactilar de la clave pública, una sucesión de pares de números hexadecimales que se obtiene a partir de ella: si coinciden, el cliente se fiará de que el servidor es quien dice ser; si no coinciden, entonces sospechará que hay una suplantación y, o bien avisará (caso de putty), o bien, se negará en rotundo a conectar hasta que no se elimine del cliente la clave pública antigua (caso del cliente de openssh).

Del párrafo anterior, hay dos ideas que es necesario remarcar y que se desglosarán bajo los siguientes epígrafes:

  1. El servidor tiene una pareja de claves pública/privada que le sirven para identificarse ante el cliente (también sirven para cifrar la clave simétrica, pero esto importa poco a los efectos de esta discusión).

  2. El cliente almacena las claves públicas de los servidores para comprobar las identidades de éstos cuando intenta una conexión.

4.5.4.1.1.1. Claves en el servidor

Se ha afirmado que el servidor tiene una pareja de claves. Esto no es del todo cierto, en realidad, las versiones modernas del servidor openssh tiene varias parejas de claves, cada una de cuales usa un algoritmo diferente de cifrado[1]. Estas claves está almacenadas en el directorio /etc/ssh:

$ ls -1 /etc/ssh/ssh_host_*
/etc/ssh/ssh_host_ecdsa_key
/etc/ssh/ssh_host_ecdsa_key.pub
/etc/ssh/ssh_host_ed25519_key
/etc/ssh/ssh_host_ed25519_key.pub
/etc/ssh/ssh_host_rsa_key
/etc/ssh/ssh_host_rsa_key.pub

Los ficheros de extensión .pub son los que almacenan las claves públicas. Paralelamente, en el fichero de configuración debe indicarse que estas serán las claves de identificación[2]:

$ /usr/sbin/sshd -T | grep -i ^HostKey
hostkey /etc/ssh/ssh_host_rsa_key
hostkey /etc/ssh/ssh_host_ecdsa_key
hostkey /etc/ssh/ssh_host_ed25519_key

Cuál de estas parejas se use para la validación depende del cliente: él le indicará al servidor por orden que algoritmos prefiere y el servidor usará el primero que tenga disponible. Se ha dicho también que en realidad lo que se compara es el fingerkey obtenido a partir de la clave pública. De hecho, la primera vez que se conecta el cliente al servidor, se encontrará con esto:

pepe@cliente$ ssh usuario@servidor
The authenticity of host 'servidor (192.168.1.11)' can't be established.
ECDSA key fingerprint is SHA256:vOef4Mo/0obxdDeS9iNIZ5+kQpMB+krMf9XTedRMUbE.
Are you sure you want to continue connecting (yes/no)

Aceptarlo implicará almacenar en el cliente tal fingerprint. Tal huella digital es posible obtenerla manualmente gracias a ssh-keygen:

$ ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub
256 SHA256:vOef4Mo/0obxdDeS9iNIZ5+kQpMB+krMf9XTedRMUbE root@servidor (ECDSA)

que obviamente coincide con el fingerprint que observó pepe desde el cliente. El primer número (256) indica la longitud de la clave.

Advertencia

Las claves identifican al servidor, así que es mejor no cambiarlas a menos que las sospechemos comprometidas. Si es absolutamente necesario, pueden redefinirse así:

# rm -f /etc/ssh/ssh_host_*
# ssh-keygen -A

ya que -A sólo genera las claves de servidor que no encuentra.

4.5.4.1.1.2. Claves en el cliente

Como se ha adelantado, los clientes almacenan los fingerprints de las claves públicas de los servidores a los que se han conectado previamente dentro del fichero ~/.ssh/known_hosts. Ahora bien:

pepe@cliente$ ssh-keygen -l -f ~/.ssh/known_hosts
256 SHA256:vOef4Mo/0obxdDeS9iNIZ5+kQpMB+krMf9XTedRMUbE |1|4WnmUKMOBGnrOtOHytjLzB8cKFE=|q7chrsGIIRUBS2S1GlpzA0vDbjo= (ECDSA)
256 SHA256:vOef4Mo/0obxdDeS9iNIZ5+kQpMB+krMf9XTedRMUbE |1|l4/bYn6a2ImKN27oCuwD3wb9M8o=|b5i6kcIRct1K1U9EBVH4PgfoJJU= (ECDSA)

si comprobamos los fingerprints almacenados no seremos capaces de saber a qué servidor corresponde tal fingerprint. Esto se hace así por privacidad, esto es, por evitar que otros usuarios sean capaces de conocer a qué servidores nos conectamos[3]. El comportamiento puede modificarse cambiando el valor de la directiva HashKnownHosts en la configuración del cliente. Por tanto, si añadimos como directiva global a ~/.ssh/config:

HashKnownHosts no

se almacenarán las direcciones en claro:

pepe@cliente$ rm -f ~/.ssh/known_hosts
pepe@cliente$ ssh usuario@servidor

[...]

pepe@cliente$ ssh-keygen -l -f ~/.ssh/known_hosts
256 SHA256:vOef4Mo/0obxdDeS9iNIZ5+kQpMB+krMf9XTedRMUbE servidor,192.168.1.11 (ECDSA)

En cualquier caso, aunque estén ofuscados los nombres, puede buscarse si hay ya alguna entrada para un servidor:

$ ssh-keygen -F servidor

A partir de ahora, cada vez que se conecte a servidor, se confirmará que el firgenprint de la clave proporcionada por este coincide con la almacenada. Si no es así, ocurrirá esto:

pepe@cliente$ ssh usuario@servidor
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:IWvZBm4stPCufdUlUdUtKGkk7P/nNhDsf1R5XDUANtM.
Please contact your system administrator.
Add correct host key in /home/josem/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/josem/.ssh/known_hosts:1
  remove with:
  ssh-keygen -f "/home/josem/.ssh/known_hosts" -R "servidor"
ECDSA host key for servidor has changed and you have requested strict checking.
Host key verification failed.

Que no coincidan las claves puede suponer una suplantación de identidad… o que las claves cambiaron en el servidor por alguna razón. Si la razón es esta segunda, la solución está incluida en el mensaje de advertenca, y es borrar el fingerprint asociado al servidor:

pepe@cliente$ ssh-keygen -R servidor
# Host servidor found: line 1
/home/josem/.ssh/known_hosts updated.
Original contents retained as /home/josem/.ssh/known_hosts.old

Nota

Putty también almacena el fingerprint del servidor, pero a diferencia de éste, no rechaza la conexión cuando detecta un cambio en la clave, sino que advierte del peligro de seguridad y permite aceptar (o no) la nueva clave.

4.5.4.1.2. Identificación del cliente

Obviamente, nos referimos a su identificación mediante clave y no mediante contraseña. Por supuesto, la identificación exige primero la creación de las claves y que el servidor acepte este tipo de identificación:

$ /usr/sbin/sshd -T | grep -i ^Pubkey
pubkeyauthentication yes

4.5.4.1.2.1. Cliente openssh

En este caso, la generación es sencilla. La orden:

$ ssh-keygen -t ecdsa -C "Comentario alusivo a la clave"

generará una clave de tipo ECDSA y, como fichero, se escogerá el predeterminado para este tipo de clave (~/.ssh/id_ecdsa y ~/.ssh/id_ecdsa.pub, para la clave pública). Si no se altera la configuración, en el momento en que intentemos conectar a cualquier servidor se intentará usar esta clave para la autenticación. Tras generar la pareja de claves se nos pide una clave de paso, que no es más que una contraseña con la que cifrar la clave privada. Fijarla obliga a escribir tal contraseña antes de usarla y nos asegura ante un hurto de las claves.

Es obvio, que no basta con generar la clave en el cliente: en el servidor debe alojarse la clave pública para que, cuando se produzca la comunicación, pueda asegurarse que quien se conecta desde el cliente es el propietario de la clave privada correspondiente. Para ello, puede hacerse:

$ ssh-copy-id usuario@servidor

que subirá la clave[4] al fichero del servidor que almacena las claves públicas (~./ssh/authorized_keys)[5]. A partir de ahora, al intentar ingresar en el servidor, se usará en primer término la identificación mediante el certificado y se nos pedirá la clave de paso (ya que hay que usar la clave privada) o nada, si no se introdujo contraseña al generar las claves.

Nota

No obstante, lo anterior, es posible usar claves almacenadas en otros ficheros. Por ejemplo:

$ ssh-keygen -t ecdsa -f .ssh/id_servidor -C "Clave para 'servidor'"
$ ssh-copy-id -i .ssh/id_servidor usuario@servidor
$ ssh -i .ssh/id_servidor usuario@servidor

e incluso indicar cuál es el nombre de la clave en la configuración:

Host svm
   Hostname       servidor
   User           usuario
   IdentityFile   ~/.ssh/id_%h

de manera que cuando conectemos a servidor siempre usemos ~/.ssh/id_servidor[6].

4.5.4.1.2.2. Cliente putty

Debemos efectuar las mismas acciones que en el caso anterior. El equivalente a ssh-keygen en la suite de putty es puttygen. Al generar el par de claves (Generate) el programa quedará esperando que movamos aletariamente el ratón por encima de la superficie vacía a fin de lograr mayor aletoriedad:

Captura de puttygen

Al acabar la generación, se podrá escribir un comentario y la clave de paso o contraseña de la propia clave. Podemos entonces guardar la clave privada (Save private key), pero la clave pública no es de poca ayuda, puesto que no tiene el mismo formato que las claves que genera OpenSSH. Sin embargo, la clave pública, tal y como la exige OpenSSH, se muestra en la propia pantalla con lo que se puede copiar y pegar en un fichero:

Captura de puttygen

Dado que ahora no disponemos de ssh-id-copy, hay que subir manualmente la clave pública al servidor para incluirla en en ~/.ssh/authorized_keys. Quizás lo más sencillo es abrir una sesión de putty y copiar contenido de la clave pública directamente sobre el fichero anterior, en vez de en un fichero cualquiera del cliente windows.

4.5.4.2. Certificados

Autenticar con certificados digitales en vez de con simples claves presenta algunas ventajas[7]:

  • Un cambio de claves en el servidor, si la identificación de este ante el cliente es con meras claves, provoca un aviso de suplantación, por cuanto el cliente había almacenado ya su anterior clave. Es tan frecuente que de forma legítima se presente el aviso que se corre el riesgo de que el cliente no le dé ninguna importancia de seguridad. Un certificado de servidor lo evita.

  • En la autenticación de clientes, un mismo cliente tendrá que subir a todos los servidores la clave pública con la que pretende identificarse.

  • Los certificados pueden expedirse con un periodo de tiempo limitado.

  • Los certificados pueden especificar qué extras se le permiten o vetan al propietario (p.e. podríamos estar interesados en que el cliente pudiera acceder al servidor, pero que en ningún caso pudiera usarlo para tunelizar[8]).

Para crear certificados podemos partir de las claves públicas que hemos visto en el epígrafe anterior. Estos certificados SSH no son certificados X.509, como los usados en SSL, sino propios de SSH, y se generan utilizando nuestro ya conocido ssh-keygen.

La idea es crear una CA que firme las claves públicas de clientes y servidores con objeto de crear los certificados:

../../_images/CA-SSH.png

Tal como se señala en el esquema se pueden tener dos parejas de claves: CA_host para firmar certificados de servidor y CA_user para firmar certificados de cliente:

  • Cualquier servidor remitirá su clave pública a la CA para obtener el certificado correspondiente (resultado de firmar la clave con CA_host) y, además, necesitará una copia de la clave pública CA_user, si quiere poder autenticar clientes mediante certificado.

  • Cualquier cliente remitirá su clave pública a la CA para obtener el certificado correspondiente (resultado de firmar la clave con CA_user) y, además, necesitará una copia de la clave pública CA_host, si quiere poder identificar clientes mediante certificado.

Nota

Por supuesto, las dos parejas de claves pueden ser la misma.

A partir de ahora trabajaremos sobre tres máquinas:

  • La que hace de CA que es aquella que contiene las claves de CA y que se encarga de firmar los certificados de las demás

  • Una máquina que hace el papel de servidor SSH.

  • Una máquina que hace el papel de cliente SSH.

Para indicar en qué máquina estamos actuando al ejecutar una orden, utilizaremos el prompt:

root@ca:~#
root@servidor:~#
pepe@cliente:~$

4.5.4.2.1. Identificación del servidor

Partimos de tener ya las claves del servidor y nuestra intención es que los clientes sean capaces de identificar al servidor mediante certificado. Debemos antes de nada generar las claves para firmar certificados de servidor:

root@ca:~# ssh-keygen -t ecdsa -f /etc/ssh/ca_host -C "Clave de CA para servidores"

Nota

Usamos claves de tipo ecdsa para evitar problemas con versiones de OpenSSH por encima de la 8.1. Para más información, consulte esta entrada de iBug.

Con esta pareja de claves operativas, debemos pasar las claves públicas del servidor a la máquina ca para que puedan ser firmadas (esto es, generado el certificado):

root@servidor:~$ scp /etc/ssh/ssh_host_*key.pub ca:/tmp

y una vez en ella, firmarlas para crear el certificado:

root@ca:~# ssh-keygen -h -s /etc/ssh/ca_host -I s_hostID -n example.net,www.example.net -z1 /tmp/ssh_host_*key.pub
root@ca:~# scp /tmp/ssh_host_*-cert.pub servidor:/etc/ssh

Advertencia

Se ha supuesto que la clave de la CA es ECDSA como se recomendo poco más arriba. Si la clave, no obstante, es RSA, aun podremos firmar, pero deberemos asegurarmos de que el algoritmo de Hash no es SHA1 (ssh-rsa) añadiendo a la orden expresamente que se usa SHA2 con -t rsa-sha2-512. Sólo así evitaremos problemas con versiones a partir de la 8.2. Este misma advertencia es aplicable a la firma de certificados para clientes.

La orden genera certificados de servidor (gracias a -h), firmados (-s) con ca_host, con un determinado identificador (-I), un número de serie (-z) que debería ser único, y que son válidos para una máquina llamada example.net o www.example.net. Podríamos haber definido una validez determinada con -V, pero por ser estos certificados de servidor los haremos eternos.

Nota

Los comodines no funcionan para definir nombres de servidor válidos. Por tanto, algo como -n "*.example,example.net" no valdrá para que el certificado sea aplicable a la máquina www.example.net.

Una vez que los certificados se remiten al servidor y se almacenan en /etc/ssh debemos modificar la configuración del servidor para que los use:

root@servidor:~# printf "HostCertificate %s\n" /etc/ssh/ssh_host_*-cert.pub >> /etc/ssh/sshd_config
root@servidor:~# invoke-rc.d ssh reload

Y con esto, hemos completado la configuración en él. Ahora debemos lograr que los clientes confien en cualquier certificado firmado por nuestra CA. Para ello debemos copiar la clave pública de la CA en el cliente:

root@ca:~# scp /etc/ssh/CA_host.pub cliente:/tmp

con objeto de añadirla a ~/.ssh/known_hosts (o /etc/ssh/ssh_known_hosts si se quiere que afecte a todos los usuarios):

pepe@cliente:~# echo "@cert-authority *.example.net,example.net,*.example.com,example.com $(cat /tmp/CA_host.pub)" >> /etc/ssh/ssh_known_hosts

Obsérvese que es necesario indicar @cert-authority para expresar que la clave es una clave de CA que tiene validez para todas las máquinas cuyo nombre se especifica a continuación (pueden añadirse también direcciones IP). Hecho esto, se aceptará la conexión con el servidor, aunque nunca antes la hubiéramos hecho, y no registrará la clave pública del servidor en el archivo ~/.ssh/known_hosts.

4.5.4.2.2. Identificación del cliente

Para que el cliente pueda autenticarse en el servidor, también pueden utilizarse certificados. Generemos primero unas claves de CA para firmar certificados de cliente:

root@ca:~# ssh-keygen -t ecdsa -f /etc/ssh/ca_user -C "Clave de CA para clientes"

Nota

Podríamos reaprovechar la pareja de claves anteriores, pero por pulcritud usaremos dos claves distintas.

Debemos pasar la clave al servidor para que este acepte clientes que tengan su certificado firmado con ella. Esto se logra añadiendo una línea a la configuración:

root@servidor:~# scp ca:/etc/ssh/ca_user.pub /etc/ssh
root@servidor:~# echo "TrustedUserCAKeys /etc/ssh/ca_user.pub" >> /etc/ssh/sshd_config
root@servidor:~# invoke-rc.d ssh reload

Concesión

Y ahora, un usuario que desee autenticarse en tal servidor, deberá generar un par de claves para sí y pasarla a la CA para que se las firme:

pepe@cliente:~$ ssh-keygen -C "Clave de pepe"
pepe@cliente:~# scp ~/.ssh/id_rsa.pub ca:/tmp

La CA firmará esas claves:

root@ca:~# ssh-keygen -s /etc/ssh/ca_user -I u_pepeID -n pepe,root -z1 -V +32w /tmp/id_rsa.pub

sin indicar la opción -h, porque esta es una clave de cliente, indicando con -n que la clave es válida para el usuario del servidor «pepe»[9] y el administrador del mismo, y que el certificado tiene una validez de 32 semanas a partir del momento en el que se firma:

root@ca:~# ssh-keygen -Lf /tmp/id_rsa.pub
id_rsa-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com user certificate
        Public key: RSA-CERT SHA256:eFEoGIJgDNFgiQycGvKXWc1FbJQOQljc90gjzRgI4uA
        Signing CA: ECDSA SHA256:ibktBc6yzycepNgHWYpWWo4V7l0QmKn+q73nf8/9vXM
        Key ID: "u_pepeID"
        Serial: 1
        Valid: from 2021-04-08T08:43:00 to 2021-11-18T08:44:34
        Principals:
                pepe
                root
        Critical Options: (none)
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc

Obsérvese que el certificado, además de limitar los usuarios con los que puede autenticarse el propietario, también permite definir de qué extras puede hacer uso (sección Extensions). Los que apareen listados son los habilitados por defecto. Sin embargo, podemos modificarlos mediante la opción -O. Por ejemplo, -O no-X11-forwarding -O mo-port-forwarding impediría al usuario identificado con el certificado mostrar en el escritorio local la ejecución aplicaciones gráficas en el servidor y hacer túneles.

Por último, el usuario en el cliente deberá obtener el certificado y guardarlo dentro de ~/.ssh:

pepe@cliente:~# scp ca:/tmp/id_rsa-cert.pub ~/.ssh

Nota

Obsérvese que con la configuración actual del servidor, un usuario podrá acceder al servidor tanto mediante una clave pública convertida en certificado como por una clave pública que no ha acreditado la CA, si la sube con ssh-copy-id. Esto puede hacer inútil la intención del administrador de añadir ciertas limitaciones al certificado (p.e. temporales) en la medida en que, una vez obtenido el certificado, el usuario puede utilizar ssh-copy-id para subir la clave al archivo authorized_keys de su perfil remoto. Para evitarlo, podemos deshabilitar la lectura de estos archivos personales añadiendo a sshd_config:

AuthorizedKeysFile      /dev/null

Putty desde agosto de 2022 soporta certificados SSH tanto para acreditación del servidor como del usuario cliente. A diferencia de las claves, el certificado no tiene formato propio y, de hecho, no puede generarse con Puttygen:

../../_images/putty-cert.png

La captura representa la identificación del cliente con clave/certificado: la clave privada tiene que tener el formato propio de Putty, mientras que el certificado es aquel que se obtiene directamente de ssh-keygen.

Revocación

Puede darse el caso de que necesitemos revocar certificados antes de que expiren. OpenSSH prevee su revocación a través de archivos KRL que listan aquellos certificados que se ha decidido revocar. Lo primero es indicar en /etc/ssh/sshd_config qué lista consultará el servidor:

RevokedKeys     /etc/ssh/revoked_keys

y tras ello, generar el archivo (en principio, vacío) y recargar el servidor:

# ssh-keygen -kf /etc/ssh/revoked_keys
# invoke-rc.d ssh reload

A partir de este momento, todo está listo para revocar certificados cuando sea preciso. Si el administrador conserva el certificado o la clave pública, puede hacerlo del siguiente modo:

# ssh-keygen -kuf /etc/ssh/revoked_keys -z1 /path/id_rsa.pub

donde debe notarse la presencia de la opción -u, porque permite conservar la lista y añadir un nuevo ítem. Si prescindimos de ella, el contenido anterior del archivo, se perdera. Además, -z permite definir la versión de la lista mediante un entero (1 en el ejemplo, porque es la primera revisión). Hemos hecho la revocación, por otro lado, utilizando la clave pública, pero habría sido igual de efectivo utilizar el certificado (id_rsa-cert.pub).

Ahora bien, la revocación también puede llevarse a cabo usando el identificador del certificado (que se introdujo con -I al crearlo) o su número de serie (introducido en su momento con -z). Para esto, sin embargo, se requiere facilitar la clave privada de la CA:

# ssh-keygen -kuf /etc/ssh/revoked_keys -z2 -s /etc/ssh/ca_user <(echo "id: u_pepeID")
# ssh-keygen -kuf /etc/ssh/revoked_keys -z3 -s /etc/ssh/ca_user <(echo "serial: 5")

Nota

ssh-keygen sólo admite archivos como argumento, así que, en realidad, «id: u_pepeID» o «serial: 5» deberían encontrarse en un archivo. Hemos usado process substitution para evitarlo.

Además, para revocar varios certificados a la vez, pueden incluirse varios archivos en la misma línea de órdenes como argumento o, en el caso de que revoquemos con identificador o número de serie, hacer un mismo archivo con varias líneas en cada una de los cuales indiquemos un certificado distinto:

# cat > /tmp/revocaciones.txt
id: u_pepeID
serial: 5

# ssh-keygen -kuf /etc/ssh/revoked_keys -z2 /tmp/revocaciones.txt

Finalmente, podemos consultar cuáles son los certificados revocado contenidos en el KRL mediante la orden:

# ssh-keygen -Qlf /etc/ssh/revoked_keys

4.5.4.3. OpenSSH y OpenSSL

Dado que ambas aplicaciones usan cifrado asimétrico y algoritmos comunes, es posible hacer conversiones entre las claves generadas con ellas. En principio:

  • Pueden hacerse conversiones para claves RSA y ECDSA. Las claves EdDSA no tienen soporte en OpenSSL.

  • El formato para las claves públicas es distinto e incompatible, pero ssh-keygen es capaz de hacer conversiones entre ambos formatos. Para obtener la clave pública en formato reconocible por OpenSSL:

    # ssh-keygen -e -f miclave.pub -m pkcs8 > miclave.pem
    

    Y para el proceso inverso:

    # ssh-keygen -i -f miclave.pem -m pkcs8 > miclave.pub
    
  • El formato para las claves privadas era el mismo hasta no hace demasiado, pero las últimas versiones de OpenSSH utilizan por defecto un formato incompatible. En cualquier caso, el formato de OpenSSL sigue soportado por OpenSSH:. Así, si se tiene una clave privada en el formato de OpenSSH:

    $ cp miclave miclave.key
    $ ssh-keygen -p -f miclave.key -m pem
    

    Y si se tiene una clave generada con OpenSSL:

    $ cp miclave.key miclave
    $ ssh-keygen -p -f miclave
    

    Nota

    En estos casos ssh-keygen genera el nuevo formato sobrescribiendo el archivo, por lo que se hace necesaria la copia previa.

  • Los formatos de certificado digital son absolutamente incompatibles y no hay conversión entre ellos, pero sí podemos tener sendos certificados generados con el mismo par de claves.

Ver también

Puede echar una lectura a este artículo sobre formatos de claves en ambas aplicaciones.

4.5.4.3.1. Partiendo de OpenSSH

Si tenemos un par de claves, las habremos generado así (para que sean ECDSA habrá que añadir -t ecdsa):

$ ssh-keygen -f miclave

lo cual creará los archivos de clave miclave y miclave.pub, ambas en formato incomprensible para OpenSSL. Para convertir podremos hacer:

$ cp miclave miclave.key
$ ssh-keygen -p -f miclave.key -m pem

Y la clave pública la podremoe obtener a partir de la clave privada usando OpenSSL, La orden exacta dependerá de si la clave es RSA o ECDSA. Podemos también usar ssh-keygen para obtener la clave pública[10], que no presenta diferencias sea una u otra la clave:

$ ssh-keygen -e -f miclave.pub -m pkcs8

4.5.4.3.2. Partiendo de OpenSSL

Podemos haber generado unas claves RSA:

$ openssl genrsa -aes128 -out miclave.key 4096
$ openssl rsa -in miclave.key -pubout -out miclave.pem

o bien unas claves ECDSA[11]:

$ openssl ecparam -name prime256v1 -genkey -noout -out miclave.key
$ openssl ec -in miclave.key -pubout -out miclave.pem

Sea como sea, el proceso de obtención de claves válidas para OpenSSH es el mismo:

$ ln -s miclave.key miclave
$ ssh-keygen -y -f miclave > miclave.pub
$ sed -ri '$s:$: Comentario para la clave' miclave.pub

donde no hemos cambiado de formato la clave privada, porque OpenSSH soporta el formato de OpenSSL y hemos obtenido la clave pública a partir de la privada (otra opción habría sido convertir desde la clave pública en el formato de OpenSSL miclave.pem).

Notas al pie