Aller au contenu
ecdsa.com
Ligne de commande

OpenSSH (ssh-keygen)

OpenSSH 10, la suite SSH dont le ssh-keygen convertit aussi des clés et signe des fichiers et des commits git : Ed25519 par défaut, échange de clés hybride ML-KEM en premier, DSA supprimé, et des signatures ECDSA dans l’encodage mpint propre à SSH.
Licence
SSH-OpenSSH
Version vérifiée
10.3p1 ·
Code source
github.com/openssh/openssh-portable
Documentation
www.openssh.com/manual.html

Compatibilité en un coup d’œil

ECDSAEdDSAPost-quantique

Courbes ECDSA
P-256P-384P-521
EdDSA
Ed25519
Formats de clé publique
spki-pemopensshpkcs1
Formats de clé privée
pkcs8-pemencrypted-pkcs8sec1-pempkcs1openssh

En plus de ssh et sshd, OpenSSH fournit ssh-keygen, qui génère et convertit des clés et, avec -Y sign, produit des signatures SSHSIG pour des fichiers et des commits git. Les faits présentés ici ont été vérifiés sur les paquets Alpine 3.24.2, OpenSSH 10.3p1, lié à l’OpenSSL 3.5.8 de l’image. Sans -t, ssh-keygen écrit une clé Ed25519. Les clés ECDSA n’existent que pour P-256, P-384 et P-521 (-b 224 est refusé), il n’y a pas d’Ed448, et DSA a disparu : ssh-keygen -t dsa répond « unknown key type dsa ». Inspectez n’importe quelle clé avec l’inspecteur de clés SSH.

Sans fichier de configuration, le client propose d’abord l’échange de clés hybride mlkem768x25519-sha256, puis sntrup761x25519-sha512, ce qui assure une protection post-quantique des clés de session. ssh -Q sig ne liste aucun algorithme de signature post-quantique : l’authentification de l’hôte et de l’utilisateur reste donc classique. RSA avec SHA-1 (ssh-rsa) est toujours implémenté, mais absent des listes par défaut des clés d’hôte et des clés publiques, si bien qu’avec les paramètres par défaut le client ne l’utilise jamais ; face à un pair qui ne propose rien de plus récent que ssh-rsa, il faut le réactiver explicitement, par exemple avec PubkeyAcceptedAlgorithms +ssh-rsa pour les clés utilisateur. Vérifiez ce qu’un serveur négocie avec l’audit de serveur SSH.

Une signature ECDSA dans SSH n’est ni du DER ni du r‖s brut : le blob est la chaîne ecdsa-sha2-nistp256 suivie d’une chaîne contenant r et s sous forme de mpint SSH (RFC 5656). Convertir des signatures depuis ou vers X.509, JWS ou WebAuthn implique donc de changer l’encodage des deux entiers. Les nonces sont aléatoires (deux signatures d’un même fichier différaient), s n’est pas normalisé, et une signature dont s avait été remplacé par n − s a passé la vérification.

Les signatures SSHSIG (ssh-keygen -Y sign) hachent le message avec SHA-512 par défaut ; -O hashalg=sha256 est la seule autre option, et SHA-1 et SHA-384 sont refusés. L’espace de noms indiqué avec -n fait partie de ce qui est signé, et vérifier une signature file en tant que email échoue avec « namespace does not match ». Les échecs se distinguent sur stderr (« invalid format » pour un blob endommagé, « incorrect signature » pour une signature valide portant sur d’autres données), tandis que stdout affiche « Could not verify signature. » dans les deux cas. Contrôlez une signature avec le vérificateur de signatures SSH.

ssh-keygen -e -m PKCS8 exporte une clé publique en SPKI PEM et -i -m PKCS8 la réimporte ; -m PEM donne aussi du SPKI pour ECDSA, mais du PKCS#1 pour RSA, et -m RFC4716 donne le format « SSH2 PUBLIC KEY ». Les clés publiques Ed25519 ne peuvent pas être exportées avec -e -m PKCS8 (« unsupported key type ED25519 »), alors que -p -m PKCS8 réécrit une clé privée Ed25519 en PKCS#8. Les clés privées sont stockées par défaut en OPENSSH PRIVATE KEY ; -p -m PEM réécrit les clés ECDSA en SEC1 et les clés RSA en PKCS#1, et -m PKCS8 avec une phrase de passe écrit du PKCS#8 chiffré.

Les faits et les vérifications qui les fondent

Rien de ce qui suit n’est copié d’une documentation. La vérification content/libraries/verify/openssh/run.sh a exécuté OpenSSH (ssh-keygen) 10.3p1 dans l’image de conteneur alpine:3.24.2 le 20 octobre 2026 ; la page doit correspondre à ce que la vérification a affiché, et chaque fait cite les lignes en question.

  • Type de clé par défaut

    ed25519

    ssh-keygen sans -t a écrit une clé ssh-ed25519.

    Relevé par la vérification
    fact default-key-type = ed25519
    evidence default-key-type: ssh-keygen without -t wrote a ssh-ed25519 key
  • Courbes ECDSA

    P-256P-384P-521

    -b 256, 384 et 521 ; -b 224 est refusé avec le message « valid lengths are 256, 384 or 521 bits ».

    Relevé par la vérification
    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 liste ssh-ed25519 et sa variante FIDO ; il n’existe aucun type de clé Ed448.

    Relevé par la vérification
    fact eddsa = Ed25519
  • Clés DSA

    removed

    ssh-keygen -t dsa échoue avec « unknown key type dsa », et ssh-dss ne figure pas dans ssh -Q key.

    Relevé par la vérification
    fact dsa-keys = removed
  • Échange de clés par défaut

    mlkem768x25519-sha256

    Première entrée de kexalgorithms dans ssh -F none -G.

    Relevé par la vérification
    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
  • Algorithmes post-quantiques

    ML-KEMsntrup761

    Échanges de clés hybrides mlkem768x25519-sha256 et sntrup761x25519-sha512 ; aucun algorithme de signature post-quantique dans ssh -Q sig.

    Relevé par la vérification
    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
  • Signatures ssh-rsa avec SHA-1

    disabled-by-default

    ssh-rsa figure dans ssh -Q sig, mais pas dans les valeurs par défaut de pubkeyacceptedalgorithms ni de hostkeyalgorithms.

    Relevé par la vérification
    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
  • Encodage des signatures ECDSA

    ssh-mpint

    Le blob de signature SSHSIG contient la chaîne de type ainsi que r et s sous forme de mpint SSH minimaux.

    Relevé par la vérification
    fact ecdsa-signature-encoding = ssh-mpint
    evidence ecdsa-signature-encoding: ssh-keygen -Y sign: hash=sha512 type=ecdsa-sha2-nistp256 mpints=yes
  • Nonce ECDSA

    random

    Deux signatures d’un même fichier étaient différentes.

    Relevé par la vérification
    fact ecdsa-nonce = random
    evidence ecdsa-nonce: two signatures of one file are different
  • Low-S à la signature

    either

    s n’est pas normalisé : des valeurs high-S sont apparues parmi 32 signatures.

    Relevé par la vérification
    fact ecdsa-low-s-sign = either
    evidence ecdsa-low-s-sign: signatures with s > n/2 among 32: yes
  • High-S à la vérification

    accepts-high-s

    Une signature dont s avait été remplacé par n − s a été vérifiée avec le résultat « Good ».

    Relevé par la vérification
    fact ecdsa-low-s-verify = accepts-high-s
    evidence ecdsa-low-s-verify: s replaced by n - s: ok
  • Sortie de la vérification en cas d’échec

    distinguishable

    stderr affiche « invalid format » pour du r‖s brut et pour 3 octets, et « incorrect signature » pour un mauvais message ; le code de sortie est 255 dans les deux cas.

    Relevé par la vérification
    fact cli-verify-output = distinguishable
  • Fonction de hachage par défaut de SSHSIG

    sha512

    L’en-tête SSHSIG d’une signature par défaut indique sha512.

    Relevé par la vérification
    fact sshsig-default-hash = sha512
    evidence sshsig-default-hash: hash=sha512 type=ecdsa-sha2-nistp256 mpints=yes
  • Algorithmes de hachage de SSHSIG

    sha256sha512

    -O hashalg= a accepté sha256 et sha512, et refusé sha1 et sha384.

    Relevé par la vérification
    fact sshsig-hash-algorithms = sha256, sha512
    evidence sshsig-hash-algorithms: ssh-keygen -Y sign -O hashalg= accepted: sha256, sha512
  • Espace de noms SSHSIG

    enforced

    Une signature produite avec -n file a échoué avec -n email : « namespace does not match ».

    Relevé par la vérification
    fact sshsig-namespace = enforced
  • Formats de clé publique

    spki-pemopensshpkcs1

    SPKI PEM (-e -m PKCS8, réimporté avec -i), la ligne OpenSSH, et PKCS#1 pour RSA (-e -m PEM).

    Relevé par la vérification
    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
  • Formats de clé privée

    pkcs8-pemencrypted-pkcs8sec1-pempkcs1openssh

    PKCS#8, PKCS#8 chiffré et SEC1 pour ECDSA, et PKCS#1 pour RSA, chacun relu par ssh-keygen -y, en plus du format OpenSSH par défaut.

    Relevé par la vérification
    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

Utilisation

Générer une clé Ed25519, signer un fichier dans l’espace de noms `file` et le vérifier à l’aide d’un fichier 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

Le banc de test des extraits de code exécute chaque exemple tel quel dans l’image de conteneur alpine:3.24.2, et l’exécution échoue si la sortie ne correspond pas.

Mise en place
apk add --no-cache -q openssh-keygen=10.3_p1-r1 >/dev/null
Commande
sh sign.sh
La sortie doit correspondre à cette expression régulière
Good "file" signature for alice@example\.com with ED25519 key SHA256:

Bibliothèques