SSH
pqdoctor ssh github.compqdoctor ssh git.example.com:2222pqdoctor ssh ssh://git@example.org:7999 --json # the user name is droppedWhat it does
Section titled “What it does”pqdoctor sends its identification (SSH-2.0-pqdoctor_<version>), reads the server’s identification and its KEXINIT (the algorithms it offers), and hangs up. It never sends a KEXINIT of its own, never does a key exchange, and never logs in.
Post-quantum methods
Section titled “Post-quantum methods”| Method | |
|---|---|
mlkem768x25519-sha256 |
ML-KEM hybrid. OpenSSH 9.9 added it, 10.0 made it the default |
mlkem768nistp256-sha256 |
ML-KEM hybrid with P-256 |
mlkem1024nistp384-sha384 |
The only one that meets CNSA 2.0 |
sntrup761x25519-sha512 (+ @openssh.com) |
Streamlined NTRU Prime hybrid. OpenSSH’s default from 9.0 to 9.9 |
Kyber drafts and sntrup4591761… count as “draft only”.
Real output
Section titled “Real output”✔ ssh github.com:22 (140.82.114.4) Post-quantum: offers mlkem768x25519-sha256, sntrup761x25519-sha512, sntrup761x25519-sha512@openssh.com The server offers a hybrid post-quantum key exchange. A client that also has one (OpenSSH 9.0+) uses it. server: 1f08b963 strict kex: yes ! Not CNSA 2.0: that needs ML-KEM-1024 (mlkem1024nistp384-sha384). X25519 and P-256 hybrids are fine for everyone else.
Offered (server's order) kex 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 host key ssh-ed25519, ecdsa-sha2-nistp256, rsa-sha2-512, rsa-sha2-256, ssh-rsa ciphers chacha20-poly1305@openssh.com, aes256-gcm@openssh.com, aes128-gcm@openssh.com, aes256-ctr, aes192-ctr, aes128-ctr macs hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com, hmac-sha2-512, hmac-sha2-256Causes
Section titled “Causes”| Code | Means |
|---|---|
ssh-mlkem |
Offers an ML-KEM hybrid |
ssh-sntrup-only |
Post-quantum, but only sntrup761, not ML-KEM (the NIST standard). OpenSSH 9.9+ offers ML-KEM as well |
ssh-draft-only |
Only draft methods |
ssh-kex-config |
OpenSSH 9.0+ supports a PQ method, but the server’s KexAlgorithms leaves it out |
ssh-old-openssh |
OpenSSH older than 9.0 |
ssh-no-pq |
Not OpenSSH, and no PQ method offered |
connect-failed |
Couldn’t connect |
OpenSSH 9.0 or newer with PQ left out. pqdoctor prints a KexAlgorithms line with the PQ methods this version has (ML-KEM from 9.9, sntrup761 from 9.0), in front of the methods the server offers now:
# /etc/ssh/sshd_config (or a file in sshd_config.d/)KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,curve25519-sha256,ecdh-sha2-nistp256
# thensudo sshd -t && sudo systemctl reload ssh # 'sshd' on some systemsOlder OpenSSH. Upgrade to OpenSSH 10.0 or later. It offers mlkem768x25519-sha256 first by default, with no config change.
Not OpenSSH. Check its release notes for mlkem768x25519-sha256 or sntrup761x25519-sha512 and enable it. If it has neither, put OpenSSH 10 in front.
Verify
Section titled “Verify”With no known host keys, this stops right after the key exchange, before any key is offered:
ssh -vv -o BatchMode=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=/dev/null -o GlobalKnownHostsFile=/dev/null github.com 2>&1 | grep -E 'kex: algorithm|KEX algorithms'Cross-checked
Section titled “Cross-checked”On 2026-10-15, github.com and gitlab.com were checked with pqdoctor and with OpenSSH 10.0p2 (ssh -vv). The servers’ offered lists were the same in both, apart from marker names (ext-info-*, kex-strict-*) that pqdoctor leaves out. Both servers negotiated mlkem768x25519-sha256.
Exit status: 0 post-quantum, 1 not, 2 unreachable.
Post-quantum host keys
Section titled “Post-quantum host keys”No post-quantum host key (signature) algorithm is standard for SSH yet. pqdoctor flags names from drafts and OQS-OpenSSH that the server offers in its host key list — anything with mldsa, ml-dsa, slh-dsa, sphincs, falcon or dilithium in it — in pqHostKey, marks them “(draft)” on screen, and warns to keep a classical host key too. They don’t change the verdict, which is about the key exchange.