ポスト量子のSSHとTLS
鍵共有は解決済みで既定になり、署名はまだ。実際のインフラでSSHとTLSを点検し直すための実務ガイド。
- ポスト量子
- SSH
- TLS
- セキュリティ
ポスト量子暗号は十年ほど学会の話題であり続け、そのあと誰にも告知されないまま、あなたのノートPCの既定値になった。OpenSSH 10とここ二年以内のブラウザを使っているなら、通信の大半はすでに量子的な攻撃者に対して守られている。残っている作業は範囲が狭く、地味で、しかし非常に具体的だ。取り残された接続を見つけ出すこと、それだけである。この記事は、それを実際のインフラでどう進めるかを扱う。何を確認し、何を変え、あとでどう検証するか。そして、いまはあえて手を付けないほうがいい部分はどこか。

この話を扱いやすくするのは、ひとつの切り分けだ。暗号は二つの方向から接続を守っている。セッションを暗号化する秘密を決める鍵共有と、相手が誰かを証明する署名である。量子計算機は両方を破る。しかし今日の時点で急を要するのは片方だけで、この二つを混同することこそ、多くのポスト量子プロジェクトが表計算の中で止まってしまう理由だ。以下の内容はすべてこの区別から導かれる。
2026年、ポスト量子暗号が実際に到達している地点
鍵共有はもう終わっている。計画中でも試験導入中でもなく、リリース済み・既定化済み・稼働中である。OpenSSHは2022年4月のバージョン9.0以降ポスト量子鍵共有を提供しており、2025年4月のOpenSSH 10.0以降はハイブリッドのmlkem768x25519-sha256が既定アルゴリズムになった。その前日にリリースされたOpenSSL 3.5.0は、既定のTLSサポートグループ一覧をハイブリッドのポスト量子グループを含み優先する形に変更し、X25519MLKEM768を既定のkeyshareとして提示するようになった。この一年でどちらかのパッケージを更新した人は、何もしないままこの機能を有効にしている。[ssh100][ossl35]
| 層 | 2026年の状況 | 自分にとっての意味 |
|---|---|---|
| SSHの鍵共有 | OpenSSH 10.0(2025年4月)以降は既定、9.0(2022年)以降利用可能 | パッケージを更新し、ネゴシエートされたアルゴリズムを確認するだけ。 |
| TLSの鍵共有 | OpenSSL 3.5.0(2025年4月)でハイブリッドグループが既定で優先 | リンクされているOpenSSLのバージョンを確認し、終端ごとに一行設定する。 |
| 共通鍵暗号 | AES-256とChaCha20は十分と見なされている | 対応不要。Groverのアルゴリズムは実効鍵長を半分にするだけである。 |
| ハッシュ | SHA-256以上は十分と見なされている | 対応不要。SHA-1の退役は量子計算機より前からの課題である。 |
| 署名とPKI | 標準化済み(ML-DSA、SLH-DSA)だが公開Webには展開不能 | 移行しない。可能になったとき素早く動けるよう発行を自動化しておく。 |
計測側も同じ絵を描いている。Cloudflareは2023年からポスト量子鍵共有の普及率を公開しており、その曲線は二年ほどで丸め誤差程度から人間由来のWebトラフィックの過半へと上がった。この記事を含め、どの記事も鵜呑みにせず実測値を見に行ってほしい。重要なのは正確な百分率ではなく曲線の形であり、それが「遅れているのはもはやインターネット全体ではなく、有限で列挙可能な集合だ」と教えてくれる。[cfpq][cfradar]
署名はまったく逆である。NISTは2024年にML-DSAとSLH-DSAを標準化し、実装も存在するが、そのどれも公開Webには展開できない。証明書は、検証側がすでに署名元のルートを信頼していて初めて意味を持つのに、ブラウザのトラストストアにポスト量子のルートは一つも入っていないからだ。これは工夫で迂回できる一時的なパッケージングの問題ではなく、エコシステムの順序の問題であり、解決には年単位の時間がかかる。
先に収集し後で復号する攻撃と、それが対象にしないもの
鍵共有が急務で署名がそうでない理由は、一つの非対称性に帰着する。OpenSSHはそれを、多くのベンダー資料より明快に書いている。[pq]
SSH接続のプライバシーは、その全体が暗号学的な鍵共有に依存している。攻撃者が鍵共有を破れれば、セッション全体を復号して閲覧できる。攻撃をリアルタイムで実行する必要はない。いま暗号化されたSSHセッションを収集しておき、量子計算機を使えるようになってから後で復号すればよい。[pq]
これが先に収集し、後で復号する攻撃であり、遡及的に効いてくる。今日、古典的な鍵交換のまま回線上で取得されたセッションは恒久的な負債になる。暗号学的に意味のある量子計算機が現れるまでアーカイブに眠り、そのとき開かれる。2032年に何をしても、2026年に記録されたセッションは救えない。署名にはこれに相当するものがない。事後に署名を偽造できたところで、すでに終わった会話に遡って誰かになりすませるわけではないからだ。ここから、きれいな優先順位の規則が得られる。
- 長寿命の機密データが長寿命の経路を通る場合。 WAN越しのデータベースレプリケーション、バックアップ転送、拠点間VPNトンネル、認証情報を貼り付けるSSHセッション。ここから直す。中身の価値は十年以上残る。
- 信頼できない経路を通る通信。 自社ネットワークを出るものすべて、そして真剣な脅威モデルではクラウド事業者のバックボーンを通るものすべて。位置を押さえた相手にとって取得は安く、保管はさらに安い。
- 誰もログインしないマシン間の経路。 警告を見る人間がいないため、監査が取りこぼすのはまさにここである。サービスメッシュ、メッセージキュー、レプリケーション経路、監視エージェント。
- 短命で価値が低く内部で完結する通信。 同一ノード上の二つのPod間のヘルスチェックに移行チケットを切る必要はない。ただしそれを文書に残し、例外が見落としではなく判断であるようにしておく。
暗号学的に意味のある量子計算機がいつ登場するかの見積もりは五年から二十年まで幅があり、多くの観測者は2030年代半ばを見込んでいる。この数字について意見を持つ必要はない。必要なのは、今日送っているデータがその時点でもなお機微かどうかを知ることであり、大半のインフラにとって正直な答えは「そうだ」である。[pq]
SSHを直す
SSHは最も取りやすい成果であり、出発点として正しい。難しい部分はOpenSSHがすでに片付けているからだ。プラグインも、導入すべきプロバイダも、実験的ブランチも要らない。あるのはバージョン番号と設定行だけで、どちらもプロジェクトが公開している。[ssh100][pq][ssh105][sshrel]
| OpenSSHのバージョン | ポスト量子鍵共有 | やること |
|---|---|---|
| 10.0以降(2025年4月以降) | 既定でmlkem768x25519-sha256 | 作業は不要だが確認は必要。ローカルのKexAlgorithms上書きで無効化されうる。 |
| 9.9 | mlkem768x25519-sha256は存在するがまだ優先されない | KexAlgorithmsの先頭に置くか、バージョンを上げる。ここでは両方の名前が使える。 |
| 9.0 – 9.8 | 既定でsntrup761x25519-sha512 | 今日の時点で耐量子性はあるが、名前はsntrup761x25519-sha512@openssh.comのみ。短い名前とML-KEMはどちらも9.9からである。 |
| 8.5 – 8.9 | sntrup761x25519-sha512@openssh.comはあるが決して優先されない | 厄介なのがこの範囲。8.9では既定リストに入っているものの古典的な曲線より下にあるため、提示はされても選ばれない。明示的に先頭へ置くこと。 |
| 8.5より前 | なし | 本当の露出点はここ。更新するか、受容したリスクを日付付きで文書化する。 |
この表には落とし穴が二つある。一つ目は名前だ。短い形のsntrup761x25519-sha512は9.9以降にしか存在しないため、それ以前では@openssh.com付きの形を書く必要があり、sshdは知らない名前を渡されると起動を拒否する。二つ目はより厄介である。既定リストに入っていることと、そこから選ばれることは同じではない。OpenSSH 8.9では、ポスト量子アルゴリズムは既定のKexAlgorithmsに確かに含まれているが六番目、curve25519-sha256より下に位置する。その結果、新しいクライアントはそのサーバーに対して古典的な鍵交換をネゴシエートし、一方でサーバーは嘘偽りなく「ポスト量子に対応している」と報告する。本稿が繰り返しネゴシエート結果を読めと言うのは、まさにこのためである。[ssh85][ssh99][ntru]
ステップ1:実際に何をネゴシエートしているか調べる
何かを変える前に、まず測る。多くの人がつまずく区別は対応しているとネゴシエートしたの違いだ。サーバーがML-KEMに対応していても、古いクライアントが要求し、サーバーの優先度リストがそれを許していれば、古典的な鍵交換で成立してしまう。その接続が実際に守られていたかを教えてくれるのは、ネゴシエートされたアルゴリズムだけである。
# 1. Your client. Anything older than 8.5 has no post-quantum key agreement
# at all; 8.5 through 9.8 have it only under the @openssh.com vendor name.
ssh -V
# OpenSSH_10.5p1, OpenSSL 3.5.7 9 Jun 2026
# 2. The remote server's software version, straight from the protocol banner.
ssh -v server.example.com exit 2>&1 | grep 'remote software version'
# debug1: Remote protocol version 2.0, remote software version OpenSSH_10.3
# 3. Which key agreement algorithms your local build even supports.
ssh -Q kex | grep -E 'mlkem|sntrup'
# mlkem768x25519-sha256
# sntrup761x25519-sha512
# 4. Supported is not preferred. On OpenSSH 8.9, for example, the PQ algorithm
# is in the default list but sixth in it, so it is offered and never chosen:
ssh -G server.example.com | grep -i '^kexalgorithms'
# kexalgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,
# ecdh-sha2-nistp384,ecdh-sha2-nistp521,sntrup761x25519-sha512@openssh.com,...
# ^ present, but nothing will ever pick it
# 5. The only answer that matters: what did THIS connection actually agree on?
# Everything above is capability; this line is the negotiated result.
ssh -v server.example.com exit 2>&1 | sed -n 's/.*kex: algorithm: /negotiated: /p'
# negotiated: mlkem768x25519-sha256一台でこの行を読めるようになれば、全台で読める。OpenSSH 10.1は、ポスト量子でない鍵交換をネゴシエートしたときにクライアント側で警告を出すようになった。人間には非常に有用だが、実際の機器群の大半を占める自動化された経路にはまったく効かない。だから自分で走査する。[ssh101]
#!/usr/bin/env bash
# pq-ssh-sweep.sh - classify every host in hosts.txt by negotiated key agreement.
# Read-only: it opens a connection, runs `exit`, and reads the debug output.
set -uo pipefail
while read -r host; do
[ -z "$host" ] && continue
# </dev/null matters: without it ssh swallows the rest of hosts.txt from the
# loop's stdin and you silently audit only the first host.
alg=$(ssh -o BatchMode=yes -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new \
-v "$host" exit </dev/null 2>&1 | sed -n 's/.*kex: algorithm: //p' | head -1)
case "$alg" in
mlkem*) printf '%-38s PQ-ML-KEM %s\n' "$host" "$alg" ;;
sntrup*) printf '%-38s PQ-LEGACY %s\n' "$host" "$alg" ;;
"") printf '%-38s UNREACHED (auth, firewall or timeout)\n' "$host" ;;
*) printf '%-38s CLASSICAL %s\n' "$host" "$alg" ;;
esac
done < hosts.txt
# PQ-ML-KEM -> done, nothing to do.
# PQ-LEGACY -> safe today (sntrup761 is quantum-resistant) but not the NIST
# standard; schedule the upgrade to OpenSSH 9.9+ anyway.
# CLASSICAL -> this is your harvest-now-decrypt-later exposure. Fix first.ステップ2:設定を慎重に変える
調査結果が手元にあれば、変更そのものは小さい。メイン設定を編集するのではなくdrop-inファイルに置けば、grepでき、戻せて、明らかに自分の変更だと分かる。[sshdcfg][ssh99]
# /etc/ssh/sshd_config.d/50-post-quantum.conf
# Requires `Include /etc/ssh/sshd_config.d/*.conf` in the main sshd_config,
# which Debian, Ubuntu, RHEL and Fedora already ship. Check with:
# grep -r '^Include' /etc/ssh/sshd_config
# --- OpenSSH 9.9 and newer ---
# Post-quantum first, classical last. The list is ordered by preference, and
# the two hybrids are the only entries here that resist a quantum adversary.
KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,curve25519-sha256,curve25519-sha256@libssh.org
# --- OpenSSH 9.0 to 9.8: NEITHER name above exists on those builds. ---
# ML-KEM only arrived in 9.9, and until 9.9 the NTRU Prime hybrid existed
# solely under its vendor extension name. sshd refuses to start on an
# unknown algorithm name, so on those versions use exactly this line and
# nothing from the one above:
# KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256
# Confirm which names your build accepts before editing: ssh -Q kex
# Signatures are NOT the urgent problem (see the article), but this is a good
# moment to drop the algorithms that are weak for classical reasons too.
HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256
PubkeyAcceptedAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,rsa-sha2-512,rsa-sha2-256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
# --- Validate BEFORE reloading, and keep your current session open. ---
# sudo sshd -t && sudo systemctl reload ssh # or sshd, depending on the distro
# Then open a SECOND session and confirm it works before closing the first.検証の儀式を省かないこと。 reloadの前に
sshd -tを実行し、いまのセッションは閉じずに残し、二つ目のセッションで接続を確認してから最初のセッションを閉じる。KexAlgorithmsのタイプミス一つでそのホストから締め出され、コンソールにアクセスできない機器ならそれは障害対応ではなく再構築になる。
クライアント側はより厳格にできる。自分のノートPCで派手に失敗するのは許容できても、共有の踏み台ではそうはいかないからだ。現実に耐える書き方は、厳しい既定値に加えて、明示的で日付入りの例外を置くことである。[sshcfg]
# ~/.ssh/config - client side
#
# ssh_config is FIRST-OBTAINED-VALUE-WINS, not last. The specific block must
# come BEFORE `Host *`, otherwise the general block wins and the exception
# below is silently dead. This is the single most common mistake in hardened
# client configs, and it fails in the direction you will not notice.
# Exceptions first: the boxes you have not fixed yet. Make each one explicit
# and dated, so it shows up in review instead of quietly becoming permanent.
Host legacy-nas.internal jump-2019.example.com
# TODO(2026-11-30): appliance firmware pending, ticket OPS-4471
# Note this REPLACES the list rather than using `+`, which would append to
# the full compiled-in default and quietly re-enable every modp group.
KexAlgorithms curve25519-sha256,diffie-hellman-group-exchange-sha256
WarnWeakCrypto no-pq-kex
# ...and the hard default for everything else.
Host *
KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512
WarnWeakCrypto yes
# Verify the result rather than trusting the file. `ssh -G` prints the
# effective configuration for a given destination, after all matching:
# ssh -G legacy-nas.internal | grep -i '^kexalgorithms'
# ssh -G anything-else.example.com | grep -i '^kexalgorithms'頭に入れておく価値のある点が二つある。第一に、OpenSSHが実装するポスト量子アルゴリズムはすべてハイブリッドだ。mlkem768x25519-sha256はML-KEMとX25519を併走させて結合するので、将来の暗号解析でML-KEMが破られても、結果はそれ以前に使っていた古典的な鍵交換より弱くはならない。損をする筋書きが存在しない。第二に、OpenSSH 9.xから上げられない場合でも、NTRU Primeのハイブリッドは9.0以降利用でき耐量子性がある。ただし名前に注意が必要で、9.9より前ではsntrup761x25519-sha512@openssh.comという形のみが存在し、短い形は拒否される。NISTの標準ではないが、収集型の攻撃を今日止められる。要点はそこにある。[pq]
TLSを直す
TLSも構図は同じで、握るレバーが違うだけだ。プリミティブはWebサーバーではなくOpenSSLの側にある。OpenSSL 3.5以降なら、パッチもoqs-providerもフォークしたnginxも不要である。まずライブラリを確認すること。意外な落とし穴のほとんどはここにあり、ディストリビューションが最新のnginxを、ML-KEMをまったく扱えないOpenSSLにリンクして配布していることは十分にありうる。[ossl35][tlsdraft][mlkemkex]
# 1. ML-KEM needs OpenSSL 3.5.0 or newer. No 3.x before 3.5 can do it at all,
# however recent the rest of the stack looks.
openssl version
# OpenSSL 3.5.7 9 Jun 2026
# 2. Confirm the provider actually exposes the primitives.
openssl list -kem-algorithms | grep -i mlkem
openssl list -signature-algorithms | grep -iE 'ML-DSA|SLH-DSA'
# 3. What does a live endpoint negotiate when the client offers the hybrid?
openssl s_client -connect www.example.com:443 -servername www.example.com \
-groups X25519MLKEM768 -tls1_3 </dev/null 2>/dev/null \
| grep -E 'Negotiated TLS1.3 group|Protocol :|Cipher :'
# Negotiated TLS1.3 group: X25519MLKEM768
# 4. Control test: the same endpoint must still serve a classical-only client,
# otherwise you have not hardened it, you have broken it.
openssl s_client -connect www.example.com:443 -servername www.example.com \
-groups X25519 -tls1_3 </dev/null 2>/dev/null \
| grep 'Negotiated TLS1.3 group'
# Negotiated TLS1.3 group: X25519手順4の対照テストに注目してほしい。ハイブリッドグループを有効にしても古典的なクライアントは壊れないはずで、壊れたのならそれは堅牢化ではなくリストの設定ミスである。順序は重要だが排他性は重要ではない。ハイブリッドを先頭に置き、古典的な曲線は後ろに残す。[osslgroups]
# Pick the ONE stanza that matches your terminator - this is four different
# config syntaxes in one block, not a file you can paste as-is.
### nginx (built against OpenSSL 3.5+; no patches, no oqs-provider needed)
# ssl_ecdh_curve feeds the TLS supported-groups list. Hybrid first, then the
# classical curves that keep older clients working.
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ecdh_curve X25519MLKEM768:X25519:secp256r1;
ssl_prefer_server_ciphers off;
### HAProxy 3.x
ssl-default-bind-curves X25519MLKEM768:X25519:secp256r1
### Apache httpd (mod_ssl passes the list straight to OpenSSL)
SSLOpenSSLConfCmd Groups X25519MLKEM768:X25519:P-256
### OpenSSL system-wide default, for everything that reads openssl.cnf
# [openssl_init] -> ssl_conf -> system_default
Groups = X25519MLKEM768:X25519:secp256r1設定はサーバーごとに一行で、いずれの場合も同じOpenSSLのサポートグループ一覧に流し込まれる。[nginxssl][haproxy][osslconf]
| コンポーネント | 前提条件 | よくある落とし穴 |
|---|---|---|
| nginx | OpenSSL 3.5.0+にリンク、ssl_ecdh_curve | 最新のnginxがOpenSSL 3.0でビルドされている場合がある。nginxのバージョンではなくnginx -Vを見る。 |
| HAProxy | OpenSSL 3.5.0+、ssl-default-bind-curves | bind単位の上書きが既定行を黙って上回る。 |
| Apache httpd | OpenSSL 3.5.0+、SSLOpenSSLConfCmd Groups | ディレクティブはvhost単位。記述のないvhostはビルド時の既定値を継承する。 |
| CDN/マネージドロードバランサー | 事業者側の設定で、多くはすでに有効 | その背後のオリジンまでの区間は自分の責任で、たいていそこが古典的なまま残る。 |
| アプリケーションランタイム(Go、Java、Node) | システムのOpenSSLではなくランタイム独自のTLSスタック | システムライブラリが効くと思い込むこと。効かない場合が多い。 |
アーキテクチャ上で外してはいけない点が一つある。これはTLSを終端する場所にだけ効くということだ。CDNやロードバランサーが代わりに終端しているなら、ハイブリッドグループが必要なのはそのホップであり、オリジン側の設定は別問題である。そして両者をつなぐ区間もまた別問題で、内部区間として忘れられるのはまさにそこだ。Kubernetesで終端しているならこれはゲートウェイの話になり、ingress-nginxからの移行はどのみちそれらのオブジェクトを書き直す機会なので、ついでに済ませるのに自然なタイミングと言える。[rfc8446]
監査に耐える棚卸しを作る
ここまではすべてホスト単位の話だ。監査担当者が、そして将来の自分が求めるのはカバレッジである。「このエンドポイントは直ったか」ではなく「全部で何台あり、直っていないのはどれか」だ。ネットワークスキャンではなく、もともと信頼している真実のソースから一覧を作ること。そうして初めて「載っていない」ことに意味が出る。
#!/usr/bin/env bash
# pq-inventory.sh - a starting point, not a CBOM. One line per listener, with
# the negotiated group, so the output diffs cleanly between runs.
set -uo pipefail
printf '%-34s %-9s %-22s %s\n' HOST PORT GROUP NOTE
while IFS=: read -r host port; do
out=$(openssl s_client -connect "$host:$port" -servername "$host" \
-groups X25519MLKEM768:X25519 -tls1_3 </dev/null 2>/dev/null)
grp=$(printf '%s' "$out" | sed -n 's/^Negotiated TLS1.3 group: //p')
sig=$(printf '%s' "$out" | sed -n 's/^Peer signature type: //p')
case "$grp" in
*MLKEM*) note="pq-ok" ;;
"") note="no-tls1.3-or-unreachable" ;;
*) note="classical-only" ;;
esac
printf '%-34s %-9s %-22s %s (sig %s)\n' "$host" "$port" "${grp:--}" "$note" "${sig:--}"
done < endpoints.txt
# endpoints.txt is one host:port per line. Feed it from whatever you already
# trust as the source of truth - the load balancer config, Consul, the CMDB -
# rather than from a network scan, so that absence is meaningful.こうしたものを一度回してみる前に、暗号資産インベントリ製品を買いたくなる衝動は抑えたほうがいい。ツールは実際に良くなっているが、最初の一巡は手作業の価値がある。自分の資産の形が見えるからで、それはどのベンダーも与えてくれないものだ。作業順序は次のとおり。
- 外部のTLS終端。 すべての公開ホスト名。一覧は最も短く露出は最も大きく、たいていはエッジの一箇所の変更で片付く。
- SSH、全域。 まず踏み台、次にそこから到達できるすべて。アプライアンス、ネットワーク機器、忘れられた仮想マシンというロングテールが浮かび上がるのはここだ。
- 内部のサービス間TLS。 サービスメッシュ、データベース接続、メッセージブローカー。一覧は長く列挙も難しいが、メッシュ自身の既定値がすでに解決している可能性もある場所である。
- VPNと拠点間トンネル。 長寿命で価値が高く、独自の更新サイクルを持つベンダーのファームウェア上で動いていることが多い。技術というより調達の問題なので、ベンダーとの会話は早めに始める。
- 組み込みのすべて。 各種デバイス、エージェント、プリンタ、カメラ、産業用コントローラ。文書化し、リスクを明示的に受容し、その受容に日付を付ける。
出力は差分を取れる形に保ち、定期的に再実行する。数字が悪い方向に動いたら、それは再作成されたイメージやロールバックされたパッケージが黙って作業を打ち消した最初の兆候である。そしてこの種の失敗は、移行そのものの失敗よりはるかに頻繁に起きる。
署名と証明書:いま待つべき理由
ここからは、有用な助言が「やらないこと」になる領域だ。NISTは2024年にポスト量子署名方式としてML-DSAとSLH-DSAを標準化し、いずれもOpenSSL 3.5に実装されている。鍵は今日でも生成できる。しかし証明書チェーンに入れるべきではない。[fips204][fips205][fips203]
理由は、OpenSSHが鍵共有を優先した説明の中で述べているものと同じだ。「いま保存して後で偽造する」攻撃は存在しない。署名は検証されるその瞬間に偽造不能でありさえすればよい。署名側の緊急性は今日の通信を守ることではなく、暗号学的に意味のある量子計算機が現れる前に古典的な署名鍵を退役させることにある。これは年単位で測る期限であって、取得されたパケットの数で測るものではない。[pq]
実務上の障害はいずれもエコシステムの形をしており、あなたが解決できるものは一つもない。
- ブラウザはポスト量子のルートを一つも信頼していない。 証明書チェーンの価値は、検証側がすでに信頼しているルートで決まる。そしてトラストストアは相応の理由があって年単位のペースでしか動かない。
- サイズの問題は実在する。 ML-DSAの署名と公開鍵はECDSAのそれよりかなり大きい。チェーン全体を運ぶハンドシェイクでは、これは抽象的なバイト数ではなく、損失のある回線での追加のラウンドトリップとして現れる。
- OpenSSHにあるのは実験的なポスト量子署名方式だけである。 プロジェクトは10.1で実験的なXMSSサポートを削除し、その後10.4(2026年7月)でML-DSA-44とEd25519を組み合わせた複合方式
mldsa44-ed25519を追加した。これは明確に実験的な位置づけで、既定では有効になっていない。HostKeyAlgorithmsとPubkeyAcceptedAlgorithmsに自分で追加し、ssh-keygen -t mldsa44-ed25519で鍵を生成する必要がある。知っておく価値はあるが、本番のホスト鍵に据える段階ではない。[ssh104][mldsased][ssh101] - 途中のすべてが同意しなければならない。 証明書検証には自分のサーバー、クライアント、検査するミドルボックス、そして2019年に誰かが入れたピン留めまでが関わる。署名は閉じる方向に失敗し、しかも全員に対して同時に失敗する。
では2026年に署名について何をすべきか。二つ、どちらも安上がりだ。古典的な理由ですでに弱いアルゴリズムを退役させること。DSAはOpenSSH 10.0で完全に削除されたし、SHA-1署名は何年も前に消えているべきだった。そして証明書の発行を自動化し有効期間を短くすること。そうしておけば、ポスト量子証明書が発行可能になったときに、入れ替えはプロジェクトではなく設定変更で済む。暗号アジリティは買ってくる製品ではなく、すでに素早くローテーションできるという性質のことであり、まったく別の理由からも望ましいものだ。退屈なアーキテクチャの背後にある勘所がここでも効く。風変わりな選択肢が安全な選択肢であることはない。[ssh103]
規制のカレンダーを正確に述べる
期限は技術記事が気づかないうちに誤りへ転ぶ場所なので、慎重な言い方をしておく。「RSAは2030年に非推奨」の根拠として誰もが引くNIST IR 8547は、2024年11月に公開された初期公開ドラフトである。意見募集期間は2025年1月に締め切られ、寄せられた意見も公開されている。NISTが想定する進め方を示すものであり、計画の入力としては正しい。しかしこれを最終的で拘束力のある標準として引用するのは不正確で、レビューの場には必ずそれを知っている人がいる。[ir8547]
| 文書 | 状態 | 実際に書かれている内容 |
|---|---|---|
| NIST IR 8547 | 初期公開ドラフト、2024年11月 | RSA、ECDSA、ECDH、有限体DHを2030年以降は非推奨、2035年以降は不可とする方針を示す。最終標準ではなくドラフト。 |
| FIPS 203 / 204 / 205 | 確定、2024年8月 | ML-KEM、ML-DSA、SLH-DSA。他のすべての文書が参照しているのはこれらのアルゴリズムである。 |
| EUの協調ロードマップ | 加盟国が採択、2025年6月 | 2026年末までに移行開始とパイロット、2030年までに高リスクと重要インフラ、2035年までに実務上可能な範囲で完了。 |
| 所管する規制当局 | 分野により異なる | たいていは上記のいずれかから派生している。要約ではなく派生元の文書を読むこと。 |
この区別は実務上効いてくる。ドラフトは下限がどちらへ動くかを教えてくれるので、計画には十分だ。しかし設計文書に「NISTの要求事項」と書くには足りない。ドラフトとして正しく引用しておけば、その計画は最初の本格的なレビューを乗り切れる。[ir8547]
欧州は別の仕組みで並行して進んでいる。加盟国はNIS協力グループを通じて協調実施ロードマップを採択した。2026年末までに移行を開始しパイロットを走らせること、2030年までに高リスクのユースケースと重要インフラを完了すること、2035年までに実務上可能な範囲で完了すること、という構成である。規則ではなく調整のための文書だが、各国のロードマップはこれを基準に書かれている。EU域内で運用しているなら、これは所管する規制当局が読んでいる文書だということになる。[euroadmap]
日本国内で運用する場合に補足すると、実務で参照されるのは国内のガイドラインや暗号技術評価の枠組みであり、いずれ扱う対象のアルゴリズムはNISTの標準に収斂するとしても、期日や強制力の建て付けは同じではない。監査向けに文書化するなら、国際的な要約から推測せず、その時点で有効な国内の一次文書を直接確認したほうがよい。そしてどのカレンダーにおいても実際の制約はベンダーのファームウェアである。機器が五年の更新サイクルに乗っているなら、今年の調達はすでにポスト量子の意思決定になっている。調達の稟議に誰もそう書かなかったとしても、である。
90日計画
全体を一枚にまとめるなら次のとおり。前提は、鍵共有は解決済みの問題を展開しているだけであり、それ以外はすべて準備だということである。
| フェーズ | 作業 | 完了の条件 |
|---|---|---|
| 第1–2週 調査 | SSHとTLSを走査し、対応一覧ではなくネゴシエートされたアルゴリズムを取る。自分の真実のソースからエンドポイント一覧を作る。 | 数字が手に入る。古典的なエンドポイントが何台で、どれかが分かる。 |
| 第3–6週 外部エッジ | すべての公開TLS終端とすべての踏み台。バイナリが実際にどのOpenSSLにリンクされているか確認する。 | 外部でハイブリッドがネゴシエートされ、古典的なクライアントも動き続けている。 |
| 第7–10週 内部 | サービス間TLS、レプリケーション、バックアップ、CDNの背後のオリジン区間。警告を見る人間がいない経路。 | 内部の件数が外部の件数と一致する。 |
| 第11–12週 残存 | 直せないアプライアンスとファームウェア。ベンダーへのチケットを起票し、リスクを文書で受容し、見直し日を設定する。 | 残るすべての例外に責任者と日付がある。 |
| 継続 署名 | 証明書発行を自動化し有効期間を短くする。ポスト量子証明書は展開しない。 | どの証明書も変更ウィンドウなしでローテーションできる。 |
多くの環境では、最初の三フェーズに九十日というのは現実的だ。変更が小さく、リスクは編集作業よりも調査の側に集中しているからである。長引くのはいつも同じ二つ、更新できないアプライアンスと、誰も存在を知らなかった経路だ。棚卸しをきちんとやれば両方とも初週に出てくる。だからこそ棚卸しを先にやる価値がある。
避ける価値のある五つの失敗
実際の移行で繰り返し現れるパターンを、失う時間の大きい順におおよそ並べる。
- ネゴシエーション結果ではなく対応可否を監査する。 「当社のサーバーはML-KEMに対応しています」は所見ではない。対応していても、古いクライアント一台のために一日中古典的なハンドシェイクを成立させることはできる。接続でネゴシエートされたアルゴリズムを読むこと。対応一覧ではない。
- 古典的なアルゴリズムを削除する。 ハイブリッドは、まさに選択を迫られないために存在する。ポスト量子グループを先頭に、X25519を後ろに置けば、可用性の事故なしに保護を得られる。
- 証明書を追いかける。 2026年にML-DSA証明書の展開を試みて費やした時間は、実際に収集されている鍵交換に費やされなかった時間である。代わりに発行を自動化すること。後で報われるのはそちらの作業だ。
- エッジで止まる。 CDNのハンドシェイクはポスト量子なのに、オリジンへの区間はそうでない。外部テストは通り、内部区間には苦情を言うユーザーがいないため、これが群を抜いて多い抜け漏れになる。
- 一度きりの作業として扱う。 再作成されたベースイメージ、ピン留めされたパッケージ、戻された設定。三月には準拠していたホストが九月には古典的な鍵交換をしている。走査はタイマーに載せ、件数が増えたら通知するようにしておく。
短くまとめると
ポスト量子鍵共有は将来のプロジェクトではない。おそらくすでに引き継いでいる既定値であり、作業のすべてはそれを取りこぼした接続を見つけることに尽きる。OpenSSH 10.xとOpenSSL 3.5+に上げ、両方でハイブリッドグループを先頭に置き、実際にネゴシエートされている内容を機器群全体で走査し、例外は日付付きで書き残す。多くのチームにとって一週間の仕事であり、この分野で今日実際に進行している唯一の攻撃を塞ぐ。
そして、そこで止める。証明書を移行しない。暗号アジリティのプラットフォームを買わない。戦略文書に「量子」と書かない。証明書発行を自動かつ短命にし、棚卸しを最新に保ち、エコシステムを待つ。ポスト量子署名が実際に展開可能になったとき、うまく対応できる組織は最も早く着手した組織ではない。変更ウィンドウを取らずに証明書を差し替えられる組織である。
よくある質問
すでにOpenSSH 10を使っている場合、何かする必要はありますか?
確認は必要で、その後はおそらく不要です。既定はmlkem768x25519-sha256ですが、ハードニングのベースラインやCIS由来のテンプレート、構成管理のモジュールが、ML-KEM以前に書かれた独自のKexAlgorithms行を持っていて、黙って除外していることがあります。実機に対してssh -v host exit 2>&1 | grep 'kex: algorithm'を実行し、ネゴシエート結果を読んでください。着信セッションについて効くのはサーバー側の設定です。
ポスト量子鍵交換を有効にすると古いクライアントが壊れませんか?
制限ではなく優先順位として設定すれば壊れません。SSHのKexAlgorithmsもTLSのサポートグループ一覧も順序付きの優先度です。ハイブリッドを先頭に置き、curve25519-sha256やX25519を後ろに残せば、新しい相手はポスト量子鍵交換になり、古い相手はフォールバックします。壊れるのは古典的なエントリを完全に削除した場合で、完全に管理下にある閉じた機器群なら妥当な判断ですが、公開されるものには適しません。
sntrup761x25519-sha512で十分ですか、ML-KEMに移るべきですか?
実際に耐量子性があり、収集して後で復号する攻撃を今日止められます。必要な性質はそこです。弱点は暗号ではなく標準化にあります。NTRU PrimeはNISTに選定されなかったため、FIPS 203を前提に書かれたコンプライアンス要件は満たせませんし、長期の実装サポートも確実とは言えません。OpenSSH 9.0〜9.8で今四半期に更新できないなら、保護はされています。それでも9.9以降への移行は計画してください。
なぜ今ポスト量子証明書を展開できないのですか?
証明書は検証側がすでに署名元のルートを信頼していて初めて役に立ちますが、ブラウザのトラストストアにポスト量子のルートは一つもないからです。OpenSSL 3.5でML-DSA鍵を生成し、それで内部CAを立てることはできます。閉じたシステムでの実験としては妥当です。しかしブラウザが触れるものについてはチェーンの検証が通りません。これは設定の問題ではなくエコシステムの順序の問題で、解決には年単位かかります。
自分のTLSエンドポイントが実際に何をネゴシエートしているか確認するには?
openssl s_client -connect host:443 -servername host -groups X25519MLKEM768 -tls1_3 </dev/null 2>/dev/null | grep 'Negotiated TLS1.3 group'です。テストそのものにOpenSSL 3.5以降のクライアントが必要で、古いクライアントで試すとグループを提示していないため偽陰性になります。あわせて-groups X25519の対照テストも必ず実行し、堅牢化したのであって壊したのではないことを確認してください。
AESやSHA-256は心配すべきですか?
いいえ。Groverのアルゴリズムは共通鍵プリミティブに対して二次の高速化を与え、実質的に鍵長を半分にします。AES-256は128ビットの安全余裕を保ち、SHA-256も十分です。AES-128はより議論がありますが実務上の懸念ではありません。Shorのアルゴリズムで根本から破られるのは公開鍵暗号——RSA、ECDH、ECDSA——であり、それが本稿の主題のすべてです。
VPNやデータベース、メッセージキューはどうすればよいですか?
規則は同じで、実行はより難しくなります。WireGuardは基本プロトコルにポスト量子鍵共有を持たず、ハイブリッドな構成には事前共有鍵の仕組みに頼ります。IPsecの対応状況はベンダーのファームウェア次第です。データベースやブローカーのTLSはシステムのOpenSSLではなくランタイム独自のTLSスタックに従うことが多いので、システム全体の設定が届いていると仮定せず個別に確認してください。これらの経路は同時に最も価値の高い標的でもあります。運ばれているのが、まさに収集型攻撃の狙う長寿命の機密データだからです。
これはコンプライアンスのための儀式ですか、実際の脅威ですか?
脅威は実在しますが時間がずれており、そのため両方向に誤って評価されがちです。今日あなたの通信が復号されているわけではありません。問うべきは、今日取得された通信が2030年代半ばにもなお機微かどうかです。診療記録、金融データ、法務資料、行政の通信、長期有効な認証情報については、答えは明らかに「そうだ」です。このリスクの特異な点は、緩和策がほとんど無料——バージョンを上げて設定を一行——であることで、そのため費用対効果の判断に特定の到来時期を信じる必要がありません。
以上はベースシステムが動かない前提だが、実際には動く。これらの既定値のうち六つを入れ替えるリリースアップグレードについてはUbuntu 24.04 から 26.04 へのサーバー移行を参照。
参考資料
以下の参考資料はすべて本稿の執筆時に実際に読んだものである。二次的な報道よりもプロジェクトのリリースノートと標準化文書を優先して引用し、ある文書が最終標準ではなくドラフトである場合はその旨を明記している。
- OpenSSH — Post-Quantum Cryptography (project page, FAQ and warning text)
- OpenSSH 9.9 release notes (19 September 2024) — ML-KEM hybrid added; sntrup761x25519-sha512 gains its IANA name
- OpenSSH 10.0 release notes (9 April 2025) — mlkem768x25519-sha256 becomes the default key agreement
- OpenSSH 10.1 release notes (6 October 2025) — warning on non-post-quantum key agreement, WarnWeakCrypto
- OpenSSH 8.5 release notes (3 March 2021) — sntrup761x25519-sha512@openssh.com replaces the older NTRU Prime hybrid, disabled by default
- OpenSSH 10.3 release notes (2 April 2026)
- OpenSSH 10.4 release notes (6 July 2026) — experimental mldsa44-ed25519 composite post-quantum signature scheme, not enabled by default
- OpenSSH 10.5 release notes (11 August 2026) — current release at the time of writing
- OpenSSH — full release notes index
- ssh_config(5) — KexAlgorithms, WarnWeakCrypto, Match
- sshd_config(5) — KexAlgorithms, HostKeyAlgorithms, Include
- IETF draft-ietf-sshm-mlkem-hybrid-kex — hybrid ML-KEM key exchange for SSH
- IETF draft-ietf-sshm-ntruprime-ssh — sntrup761x25519-sha512 for SSH (successor to the expired draft-josefsson document)
- IETF draft-miller-sshm-mldsa44-ed25519-composite-sigs — the composite signature scheme OpenSSH 10.4 implements
- OpenSSL 3.5 series release notes — PQC support and hybrid groups preferred by default (3.5.0, 8 April 2025)
- OpenSSL documentation — SSL_CTX_set1_groups_list(3), the TLS supported-groups list
- OpenSSL documentation — SSL_CONF_cmd(3), the Groups command Apache passes through
- nginx documentation — ssl_ecdh_curve in ngx_http_ssl_module
- HAProxy configuration manual — ssl-default-bind-curves
- IETF draft-ietf-tls-ecdhe-mlkem — hybrid ECDHE + ML-KEM groups for TLS 1.3
- RFC 8446 — The Transport Layer Security (TLS) Protocol Version 1.3
- NIST FIPS 203 — Module-Lattice-Based Key-Encapsulation Mechanism Standard (ML-KEM)
- NIST FIPS 204 — Module-Lattice-Based Digital Signature Standard (ML-DSA)
- NIST FIPS 205 — Stateless Hash-Based Digital Signature Standard (SLH-DSA)
- NIST IR 8547 (Initial Public Draft, 12 November 2024) — Transition to Post-Quantum Cryptography Standards
- European Commission / NIS Cooperation Group — Coordinated Implementation Roadmap for the Transition to PQC
- Cloudflare — State of the post-quantum Internet in 2025
- Cloudflare Radar — post-quantum encryption adoption (live figures)
Was this useful?