Saltar al contenido
ecdsa.com
Línea de comandos

OpenSSH (ssh-keygen)

OpenSSH 10, la suite SSH cuyo ssh-keygen también convierte claves y firma archivos y commits de git: Ed25519 por defecto, el intercambio de claves híbrido con ML-KEM como primera opción, sin DSA y con firmas ECDSA en la codificación mpint propia de SSH.
Licencia
SSH-OpenSSH
Versión comprobada
10.3p1 ·
Código fuente
github.com/openssh/openssh-portable
Documentación
www.openssh.com/manual.html

Compatibilidad de un vistazo

ECDSAEdDSACriptografía poscuántica

Curvas ECDSA
P-256P-384P-521
EdDSA
Ed25519
Formatos de clave pública
spki-pemopensshpkcs1
Formatos de clave privada
pkcs8-pemencrypted-pkcs8sec1-pempkcs1openssh

Además de ssh y sshd, OpenSSH incluye ssh-keygen, que genera y convierte claves y, con -Y sign, produce firmas SSHSIG para archivos y commits de git. Los datos de esta página se comprobaron con los paquetes de Alpine 3.24.2, OpenSSH 10.3p1, enlazado con el OpenSSL 3.5.8 de la imagen. Sin -t, ssh-keygen escribe una clave Ed25519. Solo hay claves ECDSA para P-256, P-384 y P-521 (-b 224 se rechaza), no hay Ed448, y DSA ya no está: ssh-keygen -t dsa responde «unknown key type dsa». Inspecciona cualquier clave con el inspector de claves SSH.

Sin archivo de configuración, el cliente ofrece primero el intercambio de claves híbrido mlkem768x25519-sha256 y después sntrup761x25519-sha512: protección poscuántica para las claves de sesión. ssh -Q sig no enumera ningún algoritmo de firma poscuántico, así que la autenticación de host y de usuario sigue siendo clásica. RSA con SHA-1 (ssh-rsa) sigue implementado, pero no figura en las listas predeterminadas de claves de host y de claves públicas, así que con la configuración predeterminada el cliente nunca lo usa; si la otra parte no ofrece nada más reciente que ssh-rsa, hay que volver a habilitarlo explícitamente, por ejemplo con PubkeyAcceptedAlgorithms +ssh-rsa para las claves de usuario. Comprueba qué negocia un servidor con la auditoría de servidores SSH.

Una firma ECDSA en SSH no es ni DER ni r‖s en bruto: el blob es la cadena ecdsa-sha2-nistp256 seguida de una cadena que contiene r y s como mpints de SSH (RFC 5656). Por eso, convertir firmas entre SSH y X.509, JWS o WebAuthn implica volver a codificar los dos enteros. Los nonces son aleatorios —dos firmas de un mismo archivo fueron distintas—, s no se normaliza y una firma con s sustituido por n − s se verificó.

Las firmas SSHSIG (ssh-keygen -Y sign) calculan el hash del mensaje con SHA-512 por defecto; -O hashalg=sha256 es la única alternativa, y SHA-1 y SHA-384 se rechazan. El espacio de nombres indicado con -n forma parte de lo que se firma, y verificar una firma file como email falla con «namespace does not match». Los fallos se distinguen en stderr —«invalid format» para un blob dañado, «incorrect signature» para una firma válida sobre otros datos—, mientras que stdout dice «Could not verify signature.» en ambos casos. Comprueba una firma con el verificador de firmas SSH.

ssh-keygen -e -m PKCS8 exporta una clave pública como SPKI PEM y -i -m PKCS8 la vuelve a importar; -m PEM también da SPKI para ECDSA, pero PKCS#1 para RSA, y -m RFC4716 da el formato «SSH2 PUBLIC KEY». Las claves públicas Ed25519 no se pueden exportar con -e -m PKCS8 («unsupported key type ED25519»), aunque -p -m PKCS8 reescribe una clave privada Ed25519 como PKCS#8. Las claves privadas se guardan por defecto como OPENSSH PRIVATE KEY; -p -m PEM reescribe las claves ECDSA como SEC1 y las RSA como PKCS#1, y -m PKCS8 con una frase de contraseña escribe PKCS#8 cifrado.

Datos y las comprobaciones que los respaldan

Nada de lo que sigue está copiado de la documentación. La comprobación content/libraries/verify/openssh/run.sh ejecutó OpenSSH (ssh-keygen) 10.3p1 en la imagen de contenedor alpine:3.24.2 el 20 de octubre de 2026; la página debe coincidir con lo que imprimió, y cada dato cita esas líneas.

  • Tipo de clave predeterminado

    ed25519

    ssh-keygen sin -t escribió una clave ssh-ed25519.

    Registrado por la comprobación
    fact default-key-type = ed25519
    evidence default-key-type: ssh-keygen without -t wrote a ssh-ed25519 key
  • Curvas ECDSA

    P-256P-384P-521

    -b 256, 384 y 521; -b 224 se rechaza con «valid lengths are 256, 384 or 521 bits».

    Registrado por la comprobación
    fact ecdsa-curves = P-256, P-384, P-521
    evidence ecdsa-curves: ssh -Q key: ssh-ed25519 ssh-ed25519-cert-v01@openssh.com sk-ssh-ed25519@openssh.com sk-ssh-ed25519-cert-v01@openssh.com ecdsa-sha2-nistp256 ecdsa-sha2-nistp256-cert-v01@openssh.com ecdsa-sha2-nistp384 ecdsa-sha2-nistp384-cert-v01@openssh.com ecdsa-sha2-nistp521 ecdsa-sha2-nistp521-cert-v01@openssh.com sk-ecdsa-sha2-nistp256@openssh.com sk-ecdsa-sha2-nistp256-cert-v01@openssh.com ssh-rsa ssh-rsa-cert-v01@openssh.com
  • EdDSA

    Ed25519

    ssh -Q key enumera ssh-ed25519 y su variante FIDO; no hay ningún tipo de clave Ed448.

    Registrado por la comprobación
    fact eddsa = Ed25519
  • Claves DSA

    removed

    ssh-keygen -t dsa falla con «unknown key type dsa», y ssh-dss no aparece en ssh -Q key.

    Registrado por la comprobación
    fact dsa-keys = removed
  • Intercambio de claves predeterminado

    mlkem768x25519-sha256

    Primera entrada de kexalgorithms en ssh -F none -G.

    Registrado por la comprobación
    fact default-kex = mlkem768x25519-sha256
    evidence default-kex: ssh -F none -G: kexalgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256
  • Algoritmos poscuánticos

    ML-KEMsntrup761

    Intercambios de claves híbridos mlkem768x25519-sha256 y sntrup761x25519-sha512; ningún algoritmo de firma poscuántico en ssh -Q sig.

    Registrado por la comprobación
    fact pqc = ML-KEM, sntrup761
    evidence pqc: ssh -Q kex: diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group14-sha256 diffie-hellman-group16-sha512 diffie-hellman-group18-sha512 diffie-hellman-group-exchange-sha1 diffie-hellman-group-exchange-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 curve25519-sha256 curve25519-sha256@libssh.org sntrup761x25519-sha512 sntrup761x25519-sha512@openssh.com mlkem768x25519-sha256
    evidence pqc: ssh -Q sig: ssh-ed25519 sk-ssh-ed25519@openssh.com ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521 sk-ecdsa-sha2-nistp256@openssh.com webauthn-sk-ecdsa-sha2-nistp256@openssh.com ssh-rsa rsa-sha2-256 rsa-sha2-512
  • Firmas ssh-rsa con SHA-1

    disabled-by-default

    ssh-rsa está en ssh -Q sig, pero no en los valores predeterminados de pubkeyacceptedalgorithms ni de hostkeyalgorithms.

    Registrado por la comprobación
    fact ssh-rsa-sha1 = disabled-by-default
    evidence ssh-rsa-sha1: ssh-rsa in ssh -Q sig: yes; in the default pubkeyacceptedalgorithms or hostkeyalgorithms: no
    evidence ssh-rsa-sha1: with -o PubkeyAcceptedAlgorithms=+ssh-rsa it is in the list: yes
  • Codificación de la firma ECDSA

    ssh-mpint

    El blob de la firma SSHSIG contiene la cadena de tipo, y r y s como mpints de SSH de longitud mínima.

    Registrado por la comprobación
    fact ecdsa-signature-encoding = ssh-mpint
    evidence ecdsa-signature-encoding: ssh-keygen -Y sign: hash=sha512 type=ecdsa-sha2-nistp256 mpints=yes
  • Nonce de ECDSA

    random

    Dos firmas de un mismo archivo fueron distintas.

    Registrado por la comprobación
    fact ecdsa-nonce = random
    evidence ecdsa-nonce: two signatures of one file are different
  • Low-S al firmar

    either

    s no se normaliza: aparecieron valores high-S entre 32 firmas.

    Registrado por la comprobación
    fact ecdsa-low-s-sign = either
    evidence ecdsa-low-s-sign: signatures with s > n/2 among 32: yes
  • High-S al verificar

    accepts-high-s

    Una firma con s sustituido por n − s se verificó como «Good».

    Registrado por la comprobación
    fact ecdsa-low-s-verify = accepts-high-s
    evidence ecdsa-low-s-verify: s replaced by n - s: ok
  • Salida de la verificación en caso de fallo

    distinguishable

    stderr dice «invalid format» para r‖s en bruto y para 3 bytes, e «incorrect signature» para un mensaje incorrecto; el código de salida es 255 en ambos casos.

    Registrado por la comprobación
    fact cli-verify-output = distinguishable
  • Hash predeterminado de SSHSIG

    sha512

    El encabezado SSHSIG de una firma hecha con las opciones predeterminadas indica sha512.

    Registrado por la comprobación
    fact sshsig-default-hash = sha512
    evidence sshsig-default-hash: hash=sha512 type=ecdsa-sha2-nistp256 mpints=yes
  • Algoritmos hash de SSHSIG

    sha256sha512

    -O hashalg= aceptó sha256 y sha512, y rechazó sha1 y sha384.

    Registrado por la comprobación
    fact sshsig-hash-algorithms = sha256, sha512
    evidence sshsig-hash-algorithms: ssh-keygen -Y sign -O hashalg= accepted: sha256, sha512
  • Espacio de nombres de SSHSIG

    enforced

    Una firma hecha con -n file falló con -n email: «namespace does not match».

    Registrado por la comprobación
    fact sshsig-namespace = enforced
  • Formatos de clave pública

    spki-pemopensshpkcs1

    SPKI PEM (-e -m PKCS8, que se vuelve a importar con -i), la línea de OpenSSH y PKCS#1 para RSA (-e -m PEM).

    Registrado por la comprobación
    fact public-key-formats = spki-pem, openssh, pkcs1
    evidence public-key-formats: P-256 -e -m PKCS8: -----BEGIN PUBLIC KEY-----, -i back to the same key: yes
    evidence public-key-formats: P-256 -e -m PEM: -----BEGIN PUBLIC KEY-----; -e -m RFC4716: ---- BEGIN SSH2 PUBLIC KEY ----
    evidence public-key-formats: RSA -e -m PEM: -----BEGIN RSA PUBLIC KEY-----, -i back to the same key: yes
  • Formatos de clave privada

    pkcs8-pemencrypted-pkcs8sec1-pempkcs1openssh

    PKCS#8, PKCS#8 cifrado y SEC1 para ECDSA, y PKCS#1 para RSA, todos leídos de nuevo con ssh-keygen -y, además del formato predeterminado de OpenSSH.

    Registrado por la comprobación
    fact private-key-formats = pkcs8-pem, encrypted-pkcs8, sec1-pem, pkcs1, openssh
    evidence private-key-formats: P-256 default: -----BEGIN OPENSSH PRIVATE KEY-----; -m PKCS8: -----BEGIN PRIVATE KEY----- (read back: yes); -m PKCS8 with a passphrase: -----BEGIN ENCRYPTED PRIVATE KEY----- (read back: yes); -m PEM: -----BEGIN EC PRIVATE KEY----- (read back: yes)
    evidence private-key-formats: RSA -m PEM: -----BEGIN RSA PRIVATE KEY----- (read back: yes); Ed25519 -m PKCS8: -----BEGIN PRIVATE KEY----- (read back: yes); Ed25519 -m PEM: refused

Uso

Genera una clave Ed25519, firma un archivo en el espacio de nombres `file` y verifica la firma con un archivo allowed_signers.
# Without -t, ssh-keygen generates an Ed25519 key.
ssh-keygen -q -N "" -C alice@example.com -f id_ed25519
printf 'order #1042 approved\n' > order.txt

# -n names what the signature is for; a different namespace fails verification.
ssh-keygen -q -Y sign -f id_ed25519 -n file order.txt   # writes order.txt.sig

# Verifiers trust keys through allowed_signers: a principal, then the public key.
echo "alice@example.com $(cut -d' ' -f1,2 id_ed25519.pub)" > allowed_signers
ssh-keygen -Y verify -f allowed_signers -I alice@example.com -n file -s order.txt.sig < order.txt

El arnés de pruebas de fragmentos de código ejecuta cada ejemplo tal cual en la imagen de contenedor alpine:3.24.2, y la ejecución falla si la salida no coincide.

Configuración
apk add --no-cache -q openssh-keygen=10.3_p1-r1 >/dev/null
Comando
sh sign.sh
La salida debe coincidir (expresión regular)
Good "file" signature for alice@example\.com with ED25519 key SHA256:

Bibliotecas