Zum Inhalt springen
ecdsa.com
Befehlszeile

OpenSSH (ssh-keygen)

OpenSSH 10, die SSH-Suite, deren ssh-keygen auch Schlüssel konvertiert und Dateien sowie Git-Commits signiert: standardmäßig Ed25519, hybrider Schlüsselaustausch mit ML-KEM an erster Stelle, DSA entfernt – und ECDSA-Signaturen in der SSH-eigenen mpint-Kodierung.
Lizenz
SSH-OpenSSH
Geprüfte Version
10.3p1 ·
Quellcode
github.com/openssh/openssh-portable
Dokumentation
www.openssh.com/manual.html

Kompatibilität auf einen Blick

ECDSAEdDSAPost-Quanten-Verfahren

ECDSA-Kurven
P-256P-384P-521
EdDSA
Ed25519
Formate privater Schlüssel
pkcs8-pemencrypted-pkcs8sec1-pempkcs1openssh

Neben ssh und sshd bringt OpenSSH ssh-keygen mit, das Schlüssel erzeugt und konvertiert und mit -Y sign SSHSIG-Signaturen für Dateien und Git-Commits erstellt. Die Fakten auf dieser Seite wurden mit den Paketen aus Alpine 3.24.2 geprüft, OpenSSH 10.3p1, gelinkt gegen das OpenSSL 3.5.8 des Images. Ohne -t schreibt ssh-keygen einen Ed25519-Schlüssel. ECDSA-Schlüssel gibt es nur für P-256, P-384 und P-521 (-b 224 wird abgelehnt), Ed448 fehlt, und DSA ist entfernt: ssh-keygen -t dsa antwortet mit „unknown key type dsa“. Untersuche jeden Schlüssel mit dem SSH-Schlüsselinspektor.

Ohne Konfigurationsdatei bietet der Client zuerst den hybriden Schlüsselaustausch mlkem768x25519-sha256 an, danach sntrup761x25519-sha512 – Post-Quanten-Schutz für die Sitzungsschlüssel. ssh -Q sig listet keinen Post-Quanten-Signaturalgorithmus auf, Host- und Benutzerauthentifizierung bleiben also klassisch. RSA mit SHA-1 (ssh-rsa) ist weiterhin implementiert, fehlt aber in den Standardlisten für Host-Schlüssel und öffentliche Schlüssel, sodass der Client es mit den Standardeinstellungen nie verwendet; für eine Gegenstelle, die nichts Neueres als ssh-rsa anbietet, muss es ausdrücklich wieder aktiviert werden, für Benutzerschlüssel etwa mit PubkeyAcceptedAlgorithms +ssh-rsa. Was ein Server aushandelt, zeigt das SSH-Server-Audit.

Eine ECDSA-Signatur in SSH ist weder DER noch rohes r‖s: Der Blob besteht aus dem String ecdsa-sha2-nistp256, gefolgt von einem String, der r und s als SSH-mpints enthält (RFC 5656). Um Signaturen von oder nach X.509, JWS oder WebAuthn zu konvertieren, musst du deshalb die beiden Ganzzahlen neu kodieren. Nonces sind zufällig – zwei Signaturen derselben Datei unterschieden sich –, s wird nicht normalisiert, und eine Signatur, in der s durch n − s ersetzt war, bestand die Prüfung.

SSHSIG-Signaturen (ssh-keygen -Y sign) hashen die Nachricht standardmäßig mit SHA-512; -O hashalg=sha256 ist die einzige Alternative, SHA-1 und SHA-384 werden abgelehnt. Der mit -n angegebene Namespace ist Teil der signierten Daten, und die Prüfung einer Signatur für den Namespace file als email scheitert mit „namespace does not match“. Fehlschläge lassen sich auf stderr unterscheiden – „invalid format“ für einen beschädigten Blob, „incorrect signature“ für eine gültige Signatur über andere Daten –, während stdout in beiden Fällen „Could not verify signature.“ ausgibt. Prüfe eine Signatur mit dem SSH-Signatur-Verifizierer.

ssh-keygen -e -m PKCS8 exportiert einen öffentlichen Schlüssel als SPKI-PEM, und -i -m PKCS8 importiert ihn wieder; -m PEM liefert für ECDSA ebenfalls SPKI, für RSA aber PKCS#1, und -m RFC4716 liefert das Format „SSH2 PUBLIC KEY“. Öffentliche Ed25519-Schlüssel lassen sich mit -e -m PKCS8 nicht exportieren („unsupported key type ED25519“), obwohl -p -m PKCS8 einen privaten Ed25519-Schlüssel als PKCS#8 neu schreibt. Private Schlüssel werden standardmäßig als OPENSSH PRIVATE KEY gespeichert; -p -m PEM schreibt ECDSA-Schlüssel als SEC1 und RSA-Schlüssel als PKCS#1 neu, und -m PKCS8 mit Passphrase schreibt verschlüsseltes PKCS#8.

Fakten und die Prüfungen dahinter

Nichts im Folgenden ist aus einer Dokumentation abgeschrieben. Das Prüfskript content/libraries/verify/openssh/run.sh hat OpenSSH (ssh-keygen) 10.3p1 am 20. Oktober 2026 im Container-Image alpine:3.24.2 ausgeführt; die Seite muss mit seiner Ausgabe übereinstimmen, und jeder Fakt führt die zugehörigen Zeilen auf.

  • Standard-Schlüsseltyp

    ed25519

    ssh-keygen ohne -t schrieb einen Schlüssel vom Typ ssh-ed25519.

    Von der Prüfung aufgezeichnet
    fact default-key-type = ed25519
    evidence default-key-type: ssh-keygen without -t wrote a ssh-ed25519 key
  • ECDSA-Kurven

    P-256P-384P-521

    -b 256, 384 und 521; -b 224 wird mit „valid lengths are 256, 384 or 521 bits“ abgelehnt.

    Von der Prüfung aufgezeichnet
    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 listet ssh-ed25519 und dessen FIDO-Variante auf; einen Schlüsseltyp für Ed448 gibt es nicht.

    Von der Prüfung aufgezeichnet
    fact eddsa = Ed25519
  • DSA-Schlüssel

    removed

    ssh-keygen -t dsa scheitert mit „unknown key type dsa“, und ssh-dss fehlt in ssh -Q key.

    Von der Prüfung aufgezeichnet
    fact dsa-keys = removed
  • Standard-Schlüsselaustausch

    mlkem768x25519-sha256

    Erster Eintrag von kexalgorithms in ssh -F none -G.

    Von der Prüfung aufgezeichnet
    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
  • Post-Quanten-Algorithmen

    ML-KEMsntrup761

    Hybrider Schlüsselaustausch mit mlkem768x25519-sha256 und sntrup761x25519-sha512; kein Post-Quanten-Signaturalgorithmus in ssh -Q sig.

    Von der Prüfung aufgezeichnet
    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
  • ssh-rsa-Signaturen mit SHA-1

    disabled-by-default

    ssh-rsa steht in ssh -Q sig, aber nicht in den Standardwerten von pubkeyacceptedalgorithms oder hostkeyalgorithms.

    Von der Prüfung aufgezeichnet
    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
  • Kodierung von ECDSA-Signaturen

    ssh-mpint

    Der SSHSIG-Signaturblob enthält den Typ-String sowie r und s als minimale SSH-mpints.

    Von der Prüfung aufgezeichnet
    fact ecdsa-signature-encoding = ssh-mpint
    evidence ecdsa-signature-encoding: ssh-keygen -Y sign: hash=sha512 type=ecdsa-sha2-nistp256 mpints=yes
  • ECDSA-Nonce

    random

    Zwei Signaturen derselben Datei waren verschieden.

    Von der Prüfung aufgezeichnet
    fact ecdsa-nonce = random
    evidence ecdsa-nonce: two signatures of one file are different
  • Low-S beim Signieren

    either

    s wird nicht normalisiert: Unter 32 Signaturen traten High-S-Werte auf.

    Von der Prüfung aufgezeichnet
    fact ecdsa-low-s-sign = either
    evidence ecdsa-low-s-sign: signatures with s > n/2 among 32: yes
  • High-S bei der Prüfung

    accepts-high-s

    Eine Signatur, in der s durch n − s ersetzt war, bestand die Prüfung mit „Good“.

    Von der Prüfung aufgezeichnet
    fact ecdsa-low-s-verify = accepts-high-s
    evidence ecdsa-low-s-verify: s replaced by n - s: ok
  • Ausgabe bei fehlgeschlagener Prüfung

    distinguishable

    stderr meldet „invalid format“ für rohes r‖s und für 3 Byte, „incorrect signature“ für eine falsche Nachricht; der Exit-Status ist in beiden Fällen 255.

    Von der Prüfung aufgezeichnet
    fact cli-verify-output = distinguishable
  • Standard-Hash von SSHSIG

    sha512

    Der SSHSIG-Header einer Signatur mit Standardeinstellungen nennt sha512.

    Von der Prüfung aufgezeichnet
    fact sshsig-default-hash = sha512
    evidence sshsig-default-hash: hash=sha512 type=ecdsa-sha2-nistp256 mpints=yes
  • Hash-Algorithmen von SSHSIG

    sha256sha512

    -O hashalg= akzeptierte sha256 und sha512 und lehnte sha1 und sha384 ab.

    Von der Prüfung aufgezeichnet
    fact sshsig-hash-algorithms = sha256, sha512
    evidence sshsig-hash-algorithms: ssh-keygen -Y sign -O hashalg= accepted: sha256, sha512
  • SSHSIG-Namespace

    enforced

    Eine mit -n file erstellte Signatur scheiterte mit -n email: „namespace does not match“.

    Von der Prüfung aufgezeichnet
    fact sshsig-namespace = enforced
  • Formate öffentlicher Schlüssel

    spki-pemopensshpkcs1

    SPKI-PEM (-e -m PKCS8, mit -i wieder importiert), die OpenSSH-Zeile und PKCS#1 für RSA (-e -m PEM).

    Von der Prüfung aufgezeichnet
    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
  • Formate privater Schlüssel

    pkcs8-pemencrypted-pkcs8sec1-pempkcs1openssh

    PKCS#8, verschlüsseltes PKCS#8 und SEC1 für ECDSA sowie PKCS#1 für RSA, die ssh-keygen -y jeweils wieder einlas – zusätzlich zum Standardformat von OpenSSH.

    Von der Prüfung aufgezeichnet
    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

Verwendung

Erzeuge einen Ed25519-Schlüssel, signiere eine Datei im Namespace `file` und prüfe sie gegen eine allowed_signers-Datei.
# 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

Die Snippet-Testumgebung führt jedes Beispiel unverändert im Container-Image alpine:3.24.2 aus, und der Lauf schlägt fehl, wenn die Ausgabe nicht übereinstimmt.

Einrichtung
apk add --no-cache -q openssh-keygen=10.3_p1-r1 >/dev/null
Befehl
sh sign.sh
Ausgabe muss passen (regulärer Ausdruck)
Good "file" signature for alice@example\.com with ED25519 key SHA256:

Bibliotheken