Zum Inhalt springen
ecdsa.com
← Alle Artikel

ssh-keygen 2026: Schlüsseltypen, Passphrasen und Agenten

Die Releases OpenSSH 10.0 bis 10.6 haben mehr Standardwerte geändert, als den meisten aufgefallen ist: Post-Quanten-Schlüsselaustausch, ein hybrider ML-DSA-Signaturtyp, mehr KDF-Runden, Agent-Sockets in deinem Home-Verzeichnis. Jeder Befehl unten lief mit OpenSSH 10.6p1, und die Ausgaben sind echt.

Kurz gesagt. Führe ssh-keygen -t ed25519 -C "you@host-year" aus und gib dem Schlüssel eine Passphrase; Ed25519 ist seit OpenSSH 9.5 der Standardtyp. Hast du einen FIDO2-Sicherheitsschlüssel, nimm lieber -t ed25519-sk (oder -t ecdsa-sk, wenn der Authenticator kein Ed25519 beherrscht), dann liegt der private Schlüssel nie auf dem Datenträger. Verwende RSA nur für Systeme, die nichts anderes können, und dann mit mindestens 3072 Bit: GitHub lehnt seit dem 14. Oktober 2026 kleinere neue RSA-Schlüssel ab. Lade Schlüssel mit einer Lebensdauer in den Agenten (ssh-add -t 8h), leite den Agenten nicht an Hosts weiter, die nicht unter deiner Kontrolle stehen (nimm ProxyJump), und beschränke Schlüssel mit ssh-add -h auf bestimmte Ziele. Für ganze Serverflotten ersetzt du verstreute Einträge in authorized_keys durch kurzlebige SSH-Zertifikate. Der Post-Quanten-Schutz der Sitzung ist bereits aktiv: OpenSSH 10 handelt standardmäßig mlkem768x25519-sha256 aus und warnt, wenn ein Server das nicht kann. Der neue hybride Signaturtyp ssh-mldsa44-ed25519 (OpenSSH 10.6) lohnt einen Test, den Einsatz als einziger Schlüssel aber noch nicht.

Die Befehle liefen am 20. Oktober 2026 in debian:forky-20261005-slim mit den Debian-Paketen openssh-client und openssh-server 1:10.6p1-1. Alle Schlüssel wurden für diesen Artikel erzeugt.

Welcher Schlüsseltyp

-tWas es istWann verwenden
ed25519 (Standard)Ed25519, öffentlicher Schlüssel mit 32 Byte, deterministische SignaturenFast immer
ed25519-sk, ecdsa-skFIDO2-Schlüssel: Das Secret bleibt im Authenticator, jede Signatur verlangt eine BerührungDu hast einen Sicherheitsschlüssel, und auf dem Server läuft OpenSSH 8.2 oder neuer
ecdsaECDSA auf P-256, P-384 oder P-521Eine Richtlinie verlangt NIST-Kurven
rsaRSA, seit OpenSSH 8.0 standardmäßig 3072 BitAlte Server, Appliances, manche HSMs
mldsa44-ed25519Hybride Signatur aus ML-DSA-44 + Ed25519, neu in 10.6Tests der Post-Quanten-Authentifizierung

DSA ist Geschichte: OpenSSH 10.0 (April 2025) hat es entfernt und damit „den Prozess der Abkündigung abgeschlossen, der 2015 begann“. RSA-Schlüssel sind in Ordnung; abgeschaltet wurde in OpenSSH 8.8 (September 2021) der Signaturalgorithmus ssh-rsa, der SHA-1 als Hashfunktion verwendet. Derselbe RSA-Schlüssel signiert auch mit rsa-sha2-256 oder rsa-sha2-512. Deshalb behebst du den Serverfehler zu ssh-rsa meist, indem du den Client aktualisierst, und nicht, indem du den Schlüssel ersetzt. GitHub folgt derselben Logik: Am 13. Januar 2027 entfernt GitHub die Signaturen mit ssh-rsa, nach Brownouts, also befristeten Testabschaltungen, am 4. November und 9. Dezember 2026; neue RSA-Schlüssel akzeptiert GitHub seit dem 14. Oktober 2026 nur noch ab 3072 Bit.

Größen, wie ssh-keygen 10.6 die Dateien schreibt (die Zeile in der .pub-Datei enthält den Kommentar):

RSA- und ECDSA-Schlüssel mit Standardwerten, der Hybridschlüssel und der Ed25519-Schlüssel aus dem nächsten Abschnitt
ssh-keygen -q -t rsa -N '' -f ~/rsa_default
ssh-keygen -q -t ecdsa -N '' -f ~/ecdsa_default
ssh-keygen -q -t mldsa44-ed25519 -N '' -f ~/.ssh/id_mldsa44_ed25519
for f in ~/rsa_default ~/ecdsa_default ~/.ssh/id_ed25519 ~/.ssh/id_mldsa44_ed25519; do
  ssh-keygen -l -f "$f.pub"
  printf '  public key line: %s bytes, private key file: %s bytes\n' "$(wc -c < "$f.pub")" "$(wc -c < "$f")"
done
Ausgabe (OpenSSH 10.6p1)
3072 SHA256:NGv36ZHCwauN4GGrdKSDZPnKTn6nFuLSVRS01/eSXOs alice@59151e7fff6c (RSA)
  public key line: 572 bytes, private key file: 2602 bytes
256 SHA256:4ODqYFVTGSwjx7pfis5ZtZ02PKaSd15alII7RIHPhE8 alice@59151e7fff6c (ECDSA)
  public key line: 180 bytes, private key file: 513 bytes
256 SHA256:I72RDcR38Z+glA2IhaHUj/h844afNwkK9siDEGHv24c alice@laptop-2026 (ED25519)
  public key line: 99 bytes, private key file: 464 bytes
512 SHA256:oqHqur1575V136Khl2P7Gaa6rM+2dPT51B6YfjLSxB4 alice@59151e7fff6c (MLDSA44-ED25519)
  public key line: 1868 bytes, private key file: 3982 bytes

Die Zeile des hybriden öffentlichen Schlüssels ist 19-mal so groß wie die eines Ed25519-Schlüssels. Das spielt eine Rolle für die Dateien authorized_keys, für Zertifikate und für alles, was Schlüssel in einer Datenbankspalte speichert, die auf Ed25519 ausgelegt ist. Der Vergleich Ed25519 vs. RSA behandelt das klassische Paar im Detail.

Einen Schlüssel erzeugen

Ed25519-Schlüssel mit einem Kommentar erzeugen, der nennt, wo er liegt
ssh-keygen -t ed25519 -C "alice@laptop-2026" -N 'correct horse battery staple' -f ~/.ssh/id_ed25519
Ausgabe (OpenSSH 10.6p1)
Created directory '/home/alice/.ssh'.
Generating public/private ed25519 key pair.
Your identification has been saved in /home/alice/.ssh/id_ed25519
Your public key has been saved in /home/alice/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:I72RDcR38Z+glA2IhaHUj/h844afNwkK9siDEGHv24c alice@laptop-2026
The key's randomart image is:
+--[ED25519 256]--+
|     ..o*.....   |
| o  . .=... =.   |
|. o  .. +. + o.  |
| . . . o =. . ...|
|  o   + S ..   ..|
| . . o + B       |
|  . * = * o .    |
|   o E = o.+     |
|      o oo. .    |
+----[SHA256]-----+

-N übergibt die Passphrase nur deshalb auf der Befehlszeile, weil die Testumgebung per Skript läuft; interaktiv lässt du die Option weg, dann fragt ssh-keygen nach, und die Passphrase landet nicht in der Shell-History. Der Kommentar ist freier Text, der im öffentlichen Schlüssel gespeichert wird: Name, Rechner und Jahr machen ein Audit von authorized_keys auch Jahre später möglich. Den Fingerabdruck (SHA256:…) schreiben Server ins Log, also notiere ihn, wann immer du den Schlüssel irgendwo registrierst.

Passphrase und KDF-Runden

Ohne Passphrase ist die Datei des privaten Schlüssels der Schlüssel: Ein gestohlenes Backup, ein Laptop-Image oder ein falsch konfigurierter Sync-Ordner gibt ihn preis. Mit Passphrase ist die Datei mit einem Schlüssel verschlüsselt, den bcrypt_pbkdf ableitet. Das OpenSSH-Format für private Schlüssel hält das Verschlüsselungsverfahren, die KDF und ihre Rundenzahl in einem Header fest, den jeder ohne die Passphrase lesen kann:

kdfinfo.py: Verschlüsselungsverfahren, KDF und Runden aus einem privaten OpenSSH-Schlüssel auslesen
"""Print the cipher, KDF and bcrypt rounds from the header of an OpenSSH private key file (openssh-key-v1)."""
import base64
import struct
import sys

text = open(sys.argv[1]).read()
body = "".join(line for line in text.splitlines() if not line.startswith("-----"))
blob = base64.b64decode(body)
magic = b"openssh-key-v1\0"
assert blob.startswith(magic), "not an OpenSSH private key"
pos = len(magic)


def string():
    global pos
    (length,) = struct.unpack(">I", blob[pos : pos + 4])
    value = blob[pos + 4 : pos + 4 + length]
    pos += 4 + length
    return value


cipher = string().decode()
kdf = string().decode()
options = string()
line = f"cipher={cipher} kdf={kdf}"
if kdf == "bcrypt":
    (salt_len,) = struct.unpack(">I", options[:4])
    (rounds,) = struct.unpack(">I", options[4 + salt_len : 8 + salt_len])
    line += f" salt={salt_len} bytes rounds={rounds}"
print(line)
Standard-Rundenzahl, dann der Aufwand beim Entsperren mit 32, 100 und 500 Runden
python3 kdfinfo.py ~/.ssh/id_ed25519
for r in 32 100 500; do
  ssh-keygen -q -p -a $r -P 'correct horse battery staple' -N 'correct horse battery staple' -f ~/.ssh/id_ed25519 >/dev/null
  s=$(date +%s.%N); ssh-keygen -y -P 'correct horse battery staple' -f ~/.ssh/id_ed25519 >/dev/null; e=$(date +%s.%N)
  printf 'rounds=%s unlock=%.2fs\n' $r $(echo "$e - $s" | bc)
done
Ausgabe (ein arm64-Kern in Docker auf einem Apple M4 Max)
cipher=aes256-ctr kdf=bcrypt salt=16 bytes rounds=32
rounds=32 unlock=0.16s
rounds=100 unlock=0.52s
rounds=500 unlock=2.59s

Vor OpenSSH 9.4 lag der Standard bei 16 Runden, ab 9.4 bei 24, seit 10.6 sind es 32. Der Aufwand wächst linear mit der Rundenzahl, wie die Release Notes von 10.6 anmerken („nicht wie bei bcrypt(3), wo er exponentiell wächst“), deshalb skalieren die Zahlen oben vorhersehbar: Wähle den größten Wert, dessen Verzögerung beim Entsperren du hinnimmst, denn ein Angreifer, der die Datei kopiert hat, zahlt pro Rateversuch denselben Preis. ssh-keygen -p -a 100 -f ~/.ssh/id_ed25519 verschlüsselt einen vorhandenen Schlüssel neu; lädst du ihn einmal pro Sitzung in den Agenten, zahlst du die Verzögerung nur einmal. Seit 10.6 lehnt OpenSSH Schlüssel mit mehr als einer Million Runden ab, sodass eine präparierte Schlüsseldatei einen Dienst, der sie parst, nicht blockieren kann.

Eine Passphrase schützt die gespeicherte Datei. Liegt der Schlüssel entschlüsselt im Agenten eines kompromittierten Rechners, hilft sie nicht mehr – hier kommen Hardwareschlüssel ins Spiel.

Hardwaregestützte Schlüssel: -sk

Schlüssel vom Typ ed25519-sk und ecdsa-sk (OpenSSH 8.2 und neuer) halten das Secret in einem FIDO2-Authenticator, etwa einem YubiKey oder einem Plattform-Authenticator. Die Datei ~/.ssh/id_ed25519_sk enthält dann nur ein Key Handle, das der Authenticator braucht, um den Schlüssel zu rekonstruieren; ohne das Gerät ist sie nutzlos. Jede Signatur erfordert Benutzeranwesenheit (eine Berührung), mit -O verify-required zusätzlich eine PIN. Die wichtigen Optionen, zitiert aus ssh-keygen(1):

  • -O resident speichert das Key Handle auf dem Authenticator, sodass ssh-keygen -K oder ssh-add -K es auf einem anderen Computer laden kann. Die Manpage warnt, dass dies „die Wahrscheinlichkeit erhöht, dass ein Angreifer ein gestohlenes Authenticator-Gerät nutzen kann“; kombiniere die Option deshalb mit einer PIN.
  • -O verify-required verlangt für jede Signatur eine Benutzerverifizierung (derzeit eine PIN); der Server kann sie mit der Option verify-required in authorized_keys erzwingen.
  • -O application=ssh:work trennt mehrere Resident Keys auf einem Gerät; der String muss mit ssh: beginnen.
  • -O no-touch-required verzichtet auf die Berührung, und sshd lehnt solche Signaturen ab, sofern authorized_keys sie nicht ausdrücklich erlaubt.
  • -O write-attestation=path speichert die Attestierung des Authenticators; damit kann eine Organisation bei der Registrierung nachweisen, dass der Schlüssel auf zugelassener Hardware erzeugt wurde.
Typische Registrierung eines PIN-geschützten Resident Keys (braucht einen FIDO2-Authenticator)
ssh-keygen -t ed25519-sk -O resident -O verify-required -O application=ssh:work -C "alice@yubikey-2026"

Diesen Befehl haben wir nicht ausgeführt: Der Container hat keinen Authenticator, und ein Mitschnitt ohne ihn würde nur den Fehler zeigen. Manche älteren Authenticators implementieren nur P-256; nimm für sie ecdsa-sk. Plattformschlüssel funktionieren ebenfalls, aber Schlüssel in der Sicherheitshardware eines Laptops bringen eigene Kompromisse mit sich, die der Artikel über hardwaregestützte Schlüssel behandelt.

Post-Quanten-Kryptografie: Schlüsselaustausch jetzt, Signaturen später

Die beiden Hälften von SSH haben unterschiedliche Fristen. Die Sitzungsschlüssel stammen aus dem Schlüsselaustausch; wird dieser später gebrochen, lässt sich mitgeschnittener Datenverkehr entschlüsseln (harvest now, decrypt later, also jetzt speichern, später entschlüsseln). Host- und Benutzersignaturen zählen nur im Moment des Verbindungsaufbaus: Ein künftiger Quantencomputer kann nicht nachträglich eine Anmeldung fälschen, die bereits stattgefunden hat. OpenSSH hat deshalb zuerst den Schlüsselaustausch umgestellt:

  • sntrup761x25519-sha512 ist seit OpenSSH 9.0 (2022) standardmäßig aktiv;
  • mlkem768x25519-sha256, ML-KEM-768 kombiniert mit X25519, ist seit OpenSSH 10.0 (April 2025) der Standard und inzwischen in RFC 10042 spezifiziert (Informational, 2026);
  • seit 10.1 gibt der Client eine Warnung aus, wenn die Sitzung auf einen klassischen Schlüsselaustausch zurückfällt, und seit 10.6 protokolliert der Server das.
ssh -v localhost true, Standardeinstellungen auf beiden Seiten (mit grep gefiltert)
debug1: kex: algorithm: mlkem768x25519-sha256
debug1: kex: host key algorithm: ssh-ed25519
debug1: Server host key: ssh-ed25519 SHA256:Qw4tNHnCo8UwS2qNXROrEm8RP+d+ccaVbwAzv8lLX+I
debug1: Offering public key: /home/alice/.ssh/id_ed25519 ED25519 SHA256:I72RDcR38Z+glA2IhaHUj/h844afNwkK9siDEGHv24c agent
debug1: Server accepts key: /home/alice/.ssh/id_ed25519 ED25519 SHA256:I72RDcR38Z+glA2IhaHUj/h844afNwkK9siDEGHv24c agent
Authenticated to localhost ([::1]:22) using "publickey".

Gegen einen Server, der auf KexAlgorithms curve25519-sha256,ecdh-sha2-nistp256 beschränkt ist, gab der Client mit Standardeinstellungen Folgendes aus:

Ausgabe des Clients, wenn der Server keinen Post-Quanten-Schlüsselaustausch anbietet
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html

Zwei Details, die uns aufgefallen sind: Der Client bleibt still, wenn du selbst KexAlgorithms auf ein klassisches Verfahren beschränkst (die Warnung zielt auf Server), und der Server protokolliert jede solche Sitzung, zum Beispiel connection from ::1 port 38814 is not using a post-quantum key exchange algorithm: "curve25519-sha256" [preauth]. WarnWeakCrypto no-pq-kex in einem Block Match host bringt den Client für einen Host zum Schweigen, den du nicht selbst korrigieren kannst, wie es openssh.com/pq.html vorschlägt. GitHub hat mlkem768x25519-sha256 für github.com ab dem 14. Oktober 2026 angekündigt; am 20. Oktober hat unser Client mit OpenSSH 10.6 das Verfahren mit git@github.com ausgehandelt.

Die Signaturen sind der zweite Schritt. OpenSSH 10.4 brachte eine experimentelle Composite-Signatur aus ML-DSA-44 und Ed25519; 10.6 hat sie unter dem Namen ssh-mldsa44-ed25519 aktiviert, spezifiziert im Internet-Draft draft-ietf-sshm-composite-sigs der Arbeitsgruppe SSHM. Schlüssel, die mit dem experimentellen Code aus 10.4 erzeugt wurden, müssen neu generiert werden. Im Debian-Paket 10.6 hat ssh-keygen -A den Schlüssel ssh_host_mldsa44_ed25519_key neben den Host-Schlüsseln für RSA, ECDSA und Ed25519 angelegt, und der Typ steht am Ende der Standardliste HostKeyAlgorithms, sodass Clients weiterhin Ed25519 wählen. Explizit angefordert, funktioniert er durchgängig:

ssh -v -o HostKeyAlgorithms=ssh-mldsa44-ed25519 -o IdentitiesOnly=yes -i ~/.ssh/id_mldsa44_ed25519 (gefiltert)
debug1: kex: host key algorithm: ssh-mldsa44-ed25519
debug1: Server host key: ssh-mldsa44-ed25519 SHA256:UVOUu+csMH8i8Zd/oWzokAGfzRYFetOncVzB4vYeMgQ
debug1: Server accepts key: /home/alice/.ssh/id_mldsa44_ed25519 MLDSA44-ED25519 SHA256:oqHqur1575V136Khl2P7Gaa6rM+2dPT51B6YfjLSxB4 explicit
Authenticated to localhost ([::1]:22) using "publickey".

Beide Hälften signieren dieselbe Nachricht mit Domain-Separation, und „das Fehlschlagen einer der beiden Prüfoperationen MUSS dazu führen, dass die Prüfung der Composite-Signatur fehlschlägt“; das Hybridverfahren ist heute also nicht schwächer als Ed25519. Der Preis sind die Größe (laut Draft eine Signatur von 2.484 Byte pro Authentifizierung) und die Kompatibilität: Server, Code-Hosting-Plattformen, Bastion-Hosts und Bibliotheken, die den Typ nicht kennen, akzeptieren den Schlüssel nicht. Erzeuge einen, teste ihn gegen die Hosts, die du betreibst, und lass deinen Ed25519-Schlüssel parallel registriert.

Der Agent und die Agent-Weiterleitung

ssh-agent hält entschlüsselte Schlüssel und signiert auf Anfrage; Programme erreichen ihn über den Socket in SSH_AUTH_SOCK. Seit OpenSSH 10.1 liegt dieser Socket unter ~/.ssh/agent statt unter /tmp. Füge Schlüssel mit einer Lebensdauer hinzu, damit eine vergessene Sitzung sie nicht für immer entsperrt hält:

Agenten starten und den Schlüssel für acht Stunden hinzufügen (die Testumgebung liefert die Passphrase über SSH_ASKPASS)
eval "$(ssh-agent -s)" >/dev/null
echo "SSH_AUTH_SOCK=$SSH_AUTH_SOCK"
ssh-add -t 8h ~/.ssh/id_ed25519
ssh-add -l
Ausgabe
SSH_AUTH_SOCK=/home/alice/.ssh/agent/s.eaeHp0xOjD.local.660.o5M944i4eW
Identity added: /home/alice/.ssh/id_ed25519 (alice@laptop-2026)
Lifetime set to 08:00:00
256 SHA256:I72RDcR38Z+glA2IhaHUj/h844afNwkK9siDEGHv24c alice@laptop-2026 (ED25519)

AddKeysToAgent in ~/.ssh/config erledigt dasselbe bei der ersten Verwendung und akzeptiert eine Lebensdauer (AddKeysToAgent 8h) oder confirm, das wie ssh-add -c vor jeder Signatur nachfragt.

Die Agent-Weiterleitung (ssh -A, ForwardAgent yes) macht diesen Socket auf dem entfernten Host zugänglich. ssh_config(5) benennt das Risiko klar: „Ein Angreifer kann dem Agenten kein Schlüsselmaterial entnehmen, er kann jedoch Operationen mit den Schlüsseln ausführen“. Wer auf dem entfernten Host Root-Rechte hat, kann sich in deinem Namen überall anmelden, wo deine Schlüssel funktionieren, solange du verbunden bleibst. Zwei bessere Gewohnheiten:

  • Springen statt weiterleiten. ssh -J bastion target (oder ProxyJump bastion in der Konfiguration) baut die zweite Verbindung von deinem Rechner aus durch einen weitergeleiteten TCP-Stream auf; der Bastion-Host bekommt deinen Agenten nie zu sehen.
  • Schlüssel beschränken. ssh-add -h (OpenSSH 8.9 und neuer) bindet einen Schlüssel an Ziele, die über ihre Host-Schlüssel aus known_hosts identifiziert werden, und an einzelne Hops (bastion>target), wenn du doch weiterleitest.
dest.sh (Auszug): ein Schlüssel, der nur für prod-host funktioniert
ssh-add -h prod-host ~/agent_only_key
ssh -o BatchMode=yes prod-host 'echo signed in on prod-host'
ssh -v -o BatchMode=yes build-host true 2>&1 | grep -iE 'agent|Offering|Permission denied|Authenticated|identity'
Ausgabe (gekürzt: die Zeilen, in denen nach Identitätsdateien gesucht wird, sind weggelassen)
Identity added: /home/alice/agent_only_key (alice@laptop)
signed in on prod-host
debug1: get_agent_identities: bound agent to hostkey
debug1: get_agent_identities: ssh_fetch_identitylist: agent contains no identities
debug1: Offering public key: /home/alice/.ssh/id_ed25519 ED25519 SHA256:MA2nEhBnMlCkX3pWWgPtff90dRZF9D9k8i2svCUK1II
alice@127.0.0.2: Permission denied (publickey,password).

Der Agent hat die Sitzung an den Host-Schlüssel von build-host gebunden und dann keine Identitäten dafür aufgelistet: Der Schlüssel existiert, aber nicht für dieses Ziel. Die Manpage benennt die Grenze genau: Eine Beschränkung „hindert einen Angreifer mit Zugriff auf einen entfernten SSH_AUTH_SOCK nicht daran, ihn erneut weiterzuleiten und auf einem anderen Host zu verwenden (aber nur für ein erlaubtes Ziel)“.

Zertifikate statt authorized_keys

Öffentliche Schlüssel auf jedem Server in authorized_keys zu kopieren, skaliert nicht und macht jeden Widerruf zur Suchaufgabe. Ein SSH-Zertifikat ist ein öffentlicher Schlüssel, der zusammen mit einer Identität, Principals, einer Seriennummer und einem Gültigkeitszeitraum von einem CA-Schlüssel signiert wurde. Server vertrauen der CA einmalig (TrustedUserCAKeys) und prüfen eine Sperrliste (RevokedKeys):

Benutzerschlüssel für 8 Stunden signieren, anmelden, per Seriennummer widerrufen, erneut versuchen (als root auf dem Testserver ausgeführt)
ssh-keygen -s /etc/ssh/user_ca -I "alice@example.com 2026-10-20" -n alice -V +8h -z 1042 /home/alice/.ssh/id_cert_user.pub
ssh-keygen -L -f /home/alice/.ssh/id_cert_user-cert.pub
su - alice -c 'ssh -o IdentitiesOnly=yes -o IdentityAgent=none -i ~/.ssh/id_cert_user localhost "echo logged in with certificate"'
echo "serial: 1042" > /tmp/revoke.txt
ssh-keygen -k -u -s /etc/ssh/user_ca.pub -f /etc/ssh/revoked.krl /tmp/revoke.txt
ssh-keygen -Q -f /etc/ssh/revoked.krl /home/alice/.ssh/id_cert_user-cert.pub
su - alice -c 'ssh -o IdentitiesOnly=yes -o IdentityAgent=none -o BatchMode=yes -i ~/.ssh/id_cert_user localhost true'
Ausgabe (sshd läuft mit TrustedUserCAKeys /etc/ssh/user_ca.pub und RevokedKeys /etc/ssh/revoked.krl)
Signed user key /home/alice/.ssh/id_cert_user-cert.pub: id "alice@example.com 2026-10-20" serial 1042 for alice valid from 2026-10-20T14:33:00 to 2026-10-20T22:34:33
/home/alice/.ssh/id_cert_user-cert.pub:
        Type: ssh-ed25519-cert-v01@openssh.com user certificate
        Public key: ED25519-CERT SHA256:eVstR5lK6VBztjl2AYyWcv8C6xwNahEEVSrQpe7Y/LE
        Signing CA: ED25519 SHA256:+URM6AMiGUu+gv/gxoQgpOhHP4CUN1fznXWDlVxorbY (using ssh-ed25519)
        Key ID: "alice@example.com 2026-10-20"
        Serial: 1042
        Valid: from 2026-10-20T14:33:00 to 2026-10-20T22:34:33
        Principals: 
                alice
        Critical Options: (none)
        Extensions: 
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc
logged in with certificate
Revoking from /tmp/revoke.txt
/home/alice/.ssh/id_cert_user-cert.pub (alice@ci-runner): REVOKED
alice@localhost: Permission denied (publickey).

sshd hat key ED25519-CERT SHA256:eVst… revoked by file /etc/ssh/revoked.krl protokolliert. Achte auf die Standarderweiterungen: Ein Zertifikat erlaubt Agent- und Portweiterleitung, sofern du nicht mit -O clear signierst und nur das wieder hinzufügst, was nötig ist (-O permit-pty). Halte den CA-Schlüssel offline oder in einem HSM, stelle Zertifikate für Stunden statt für Jahre aus – kurze Laufzeiten machen die meisten Widerrufe überflüssig. Host-Zertifikate (-h beim Signieren, @cert-authority in known_hosts) beseitigen auf dieselbe Weise die Rückfrage beim ersten Verbindungsaufbau (Trust on First Use).

Schlüssel rotieren

  • Benutzerschlüssel. Erzeuge den neuen Schlüssel, trage seinen öffentlichen Schlüssel überall neben dem alten ein (Server, Code-Hosting-Plattformen, CI-Secrets), verbinde dich mit -i new_key -o IdentitiesOnly=yes, um zu beweisen, dass er funktioniert, und entferne dann die alte Zeile. Ein Kommentar mit Datum zeigt dir, welche Zeile die alte ist.
  • Host-Schlüssel. UpdateHostKeys ist seit OpenSSH 8.5 standardmäßig aktiv (sofern du nicht UserKnownHostsFile überschreibst oder VerifyHostKeyDNS aktivierst): Nach der Authentifizierung meldet der Server alle seine Host-Schlüssel, und der Client speichert neue ab, sodass ein Server einen Ersatz veröffentlichen kann, bevor er den alten Schlüssel ausmustert. Clients, die sich selten verbinden, verpassen dieses Zeitfenster; Host-Zertifikate umgehen das Problem.
  • Algorithmen. Über denselben Mechanismus läuft auch eine Migration: Füge einen Ed25519-Host-Schlüssel hinzu (und später einen hybriden), lass die Clients ihn lernen und entferne dann den RSA-Schlüssel.
  • Bestandsaufnahme. ssh-keygen -l -f authorized_keys gibt pro Zeile einen Fingerabdruck aus; vergleiche die Liste mit den Logzeilen Accepted publickey … SHA256: von sshd, um Schlüssel zu finden, die niemand nutzt.

Häufige Fehler

  • Eine für alle lesbare Schlüsseldatei. ssh verweigert ihre Verwendung und gibt WARNING: UNPROTECTED PRIVATE KEY FILE! aus. Wende chmod 600 auf den Schlüssel an und 700 auf das Verzeichnis .ssh.
  • Falsche Passphrase oder konvertierter Schlüssel. incorrect passphrase supplied to decrypt private key und error in libcrypto sehen ähnlich aus; die zweite Meldung bedeutet meist, dass die Datei beschädigt ist oder in einem Format vorliegt, das der Build nicht lesen kann. Bibliotheken brauchen die Passphrase explizit, wie Go mit this private key is passphrase protected zeigt.
  • Zu viele Schlüssel im Agenten. sshd gibt nach MaxAuthTries (6) fehlgeschlagenen Versuchen auf und trennt die Verbindung mit Too many authentication failures, und jeder Schlüssel, den der Client probiert, kann einen Versuch verbrauchen (Server mit OpenSSH 10.6 erlauben sechs zusätzliche Anfragen der Art „würdest du diesen Schlüssel akzeptieren?“, PubkeyOptions max-pk-ok). Setze IdentityFile und IdentitiesOnly yes pro Host. Ist keiner der angebotenen Schlüssel registriert, bekommst du Permission denied (publickey).
  • Der Agent verweigert. agent refused operation bedeutet, dass der Server den Schlüssel akzeptiert hat, der Agent aber nicht signieren wollte: ein FIDO-Schlüssel, der nicht rechtzeitig berührt wurde, eine Bestätigung, die der Agent nicht anzeigen kann, ein gesperrtes Token oder eine Schlüsseldatei auf dem Datenträger, die nicht mehr zu dem passt, was der Agent hält.
  • Alte Gegenstellen. no matching host key type found. Their offer: ssh-rsa bedeutet, dass der Server nur mit SHA-1 signieren kann. Aktualisiere ihn; ein HostKeyAlgorithms +ssh-rsa pro Host ist eine vorübergehende Ausnahme, niemals eine globale Einstellung.
  • Einen geänderten Host-Schlüssel ignorieren. REMOTE HOST IDENTIFICATION HAS CHANGED ist entweder eine geplante Rotation, die du über einen anderen Kanal bestätigen kannst, oder genau der Angriff, für den es diese Prüfung gibt. Entferne die alte Zeile mit ssh-keygen -R host erst, wenn du weißt, welches von beiden zutrifft.

Checkliste

  1. ssh-keygen -t ed25519 (oder -t ed25519-sk mit einem Sicherheitsschlüssel), eine Passphrase, ein Kommentar mit Besitzer, Rechner und Jahr.
  2. Erhöhe die KDF-Runden bis zu der Verzögerung, die du hinnimmst (-a 100 kostet hier etwa eine halbe Sekunde).
  3. Ein Schlüssel pro Gerät; kopiere private Schlüssel nie zwischen Rechnern.
  4. Agent mit Lebensdauern; IdentitiesOnly yes pro Host; ProxyJump statt ForwardAgent; ssh-add -h, wenn sich eine Weiterleitung nicht vermeiden lässt.
  5. Serverflotten: Benutzer- und Host-Zertifikate mit kurzer Gültigkeit, CA-Schlüssel offline, eine KRL auf jedem Server.
  6. Prüfe in der Ausgabe von ssh -v, ob kex: algorithm: mlkem768x25519-sha256 erscheint; behandle die Post-Quanten-Warnung als Ticket für ein Server-Update.
  7. Teste Schlüssel vom Typ mldsa44-ed25519 gegen deine eigenen Server; lass einen klassischen Schlüssel registriert, bis jede Gegenstelle den Hybridtyp akzeptiert.

Quellen