ハイブリッド暗号方式とは?仕組みとPython実装・PQC移行を解説
ハイブリッド暗号方式は、本文そのものを共通鍵暗号で暗号化し、その共通鍵だけを公開鍵暗号で包んで相手に届ける方式です。HTTPSやSSH、S/MIMEといった日常的な通信はすべてこの構成で動いています。ただし2023年のTLSハイブリッド鍵共有の実装投入と2024年のFIPS 203確定を境に、この言葉は耐量子計算機暗号を従来方式と併用する「PQCハイブリッド」を指す場面が増え、実装現場で対象がずれるようになりました。本記事では従来型の仕組みを実行検証済みのPythonコードと実測サイズで示したうえで、2つの語義の関係と、2030年・2035年という移行期限までに何を決めておくべきかを整理します。
まとめ
ハイブリッド暗号方式の要点は、公開鍵暗号が扱えるデータ長と処理速度の制約を、共通鍵暗号との役割分担で回避している点にあります。RSA-3072のOAEPで直接暗号化できるのは318バイトまでですが、AES-256の鍵は32バイトなので鍵だけなら包めます。この一点が構成のすべてを決めています。
2026年時点で最も大きな変化は、TLSの鍵交換の既定がX25519MLKEM768のような従来楕円曲線と耐量子KEMの併用へ移ったことです。サーバーの設定を変えていなくても、ライブラリの更新だけでハイブリッド鍵交換が候補に入っています。加えてNISTは、有限体DH・ECDH・RSAによる鍵確立のうち112ビット強度のものを2030年より後は非推奨、2035年より後は使用不可とする方針を草案で示しました。Pythonのcryptographyも48.0.0から標準ホイールでML-KEMを扱えるようになり、手元で検証する障壁は下がっています。以降でそれぞれの根拠と実装を見ていきます。
ハイブリッド暗号方式の基本構成と処理手順
ハイブリッド暗号方式では、共通鍵暗号と公開鍵暗号がそれぞれ別の仕事を担当します。共通鍵暗号は本文の暗号化、公開鍵暗号は「その共通鍵を安全に運ぶこと」だけを担います。共通鍵暗号と公開鍵暗号そのものの比較は公開鍵暗号方式と共通鍵暗号方式の違いで詳しく扱っているため、ここでは両者を組み合わせたときの流れに絞ります。
共通鍵で本文・公開鍵で鍵を運ぶ4ステップ
送信側は、まずその通信だけで使い捨てる共通鍵(セッション鍵)を乱数から生成します。次にその共通鍵で本文を暗号化し、続いて受信者の公開鍵で共通鍵自体を暗号化します。最後に、暗号化した本文と暗号化した共通鍵をひとまとめにして送ります。受信側は自分の秘密鍵で共通鍵を取り出し、その共通鍵で本文を復号します。
この構成で本質的なのは、公開鍵暗号が扱うデータが常に「鍵1本ぶん」に固定される点です。本文が1バイトでも1ギガバイトでも、公開鍵暗号の処理コストは変わりません。暗号技術の分野では、鍵を運ぶ部分をKEM(鍵カプセル化メカニズム)、本文を暗号化する部分をDEM(データカプセル化メカニズム)と呼び、両者を組み合わせた設計をKEM/DEM構成と呼びます。ハイブリッド暗号方式は、このKEM/DEM構成の最も一般的な実装形態にあたります。
ITパスポートと情報処理安全確保支援士での出題パターン
国家試験では、この役割分担そのものが問われます。ITパスポート試験の令和5年度 問86は、メッセージの暗号化に使う鍵と、その鍵の暗号化に使う鍵の組合せを図から答えさせる形式でした。正解は「メッセージの暗号化=共通鍵、共通鍵の暗号化=公開鍵」です。
この逆、つまり本文を公開鍵で暗号化して共通鍵で鍵を包む、という選択肢が毎回誤答として用意されます。判断の軸は単純で、公開鍵暗号は長いデータを扱えないため本文側には置けない、と覚えておけば取り違えません。
公開鍵暗号単独では実用にならない性能上の理由
「最初から公開鍵暗号だけで本文を暗号化すればよいのでは」という疑問は、実際にサイズを測ると解けます。次の値は、cryptography 49.0.0(OpenSSL 3.6.3)で実際に生成して確認したものです。
| 対象 | 方式 | 実測サイズ |
|---|---|---|
| AES-256の共通鍵 | 共通鍵暗号 | 32バイト |
| 共通鍵をRSA-3072 OAEPで暗号化 | 公開鍵暗号 | 384バイト |
| 18バイトの本文をAES-256-GCMで暗号化 | 共通鍵暗号 | 34バイト(認証タグ16バイト含む) |
| RSA-3072 OAEP-SHA256で暗号化できる平文の上限 | 公開鍵暗号 | 318バイト |
RSA-3072にOAEPとSHA-256を組み合わせた場合、平文として入れられるのは318バイトまでです。数メガバイトのファイルは物理的に入りません。分割する手もありますが、同じ環境で測ると RSA-3072の復号は毎秒211回(1回あたり4.74ミリ秒)なのに対し、AES-256-GCMは毎秒1,156メガバイトを処理します。RSAで1回復号する時間があれば、AESは約5メガバイトを暗号化し終えている計算です。一方でAES-GCMは本文18バイトに対して出力34バイト、増加分は認証タグの16バイトだけです。この非対称性が、鍵だけを公開鍵で包むという設計を必然にしています。RSAとECDSAで鍵長あたりの強度がどう違うかはECDSAとRSAの鍵長・安全性・速度の比較にまとめています。
TLS 1.3ハンドシェイクにおけるハイブリッド構成
実際のHTTPS通信では、共通鍵をそのまま公開鍵で暗号化して送る形は使われていません。TLS 1.3では鍵交換にディフィー・ヘルマン鍵共有を用い、クライアントとサーバーが互いの公開値だけを交換して同じ共有秘密を計算します。共通鍵は通信路を流れず、両者が独立に導出します。
ただし役割分担の構図は変わりません。公開鍵暗号の技術は共有秘密の確立と証明書による相手の認証に使われ、確立後の実データはAES-GCMやChaCha20-Poly1305という共通鍵暗号が処理します。ハイブリッド暗号方式を「共通鍵を公開鍵で包む方式」とだけ覚えていると、TLSの実装を読んだときに対応が取れなくなります。鍵を直接包む形はS/MIMEやPGPのファイル暗号化に、鍵共有を経る形はTLSやSSHの仕組みと公開鍵認証に、それぞれ対応すると整理すると混乱しません。手元のOpenSSHで ssh -Q kex と ssh -Q cipher を実行すると、鍵共有に curve25519-sha256、本文の暗号化に [email protected] が並んでいることを確認できます。VPNで同じ構成がどう組まれているかはIPsecのAH・ESP・IKEの仕組みで扱っています。
PythonによるRSA-OAEPとAES-GCMの実装
鍵を直接包む古典的なハイブリッド暗号方式は、標準的なライブラリで数十行に収まります。以下はcryptography 49.0.0で実行して復号まで確認したコードです。
import os
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
# 受信者の鍵ペア(本番では事前に生成し秘密鍵は鍵管理基盤に置く)
private_key = rsa.generate_private_key(public_exponent=65537, key_size=3072)
public_key = private_key.public_key()
# 1. セッション鍵を生成し、本文を共通鍵暗号で暗号化する
session_key = AESGCM.generate_key(bit_length=256)
nonce = os.urandom(12)
ciphertext = AESGCM(session_key).encrypt(nonce, b"secret payload!!!!", None)
# 2. セッション鍵だけを公開鍵暗号で包む
oaep = padding.OAEP(
mgf=padding.MGF1(hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None,
)
wrapped_key = public_key.encrypt(session_key, oaep)
# 3. 受信側は秘密鍵でセッション鍵を取り出し、本文を復号する
recovered_key = private_key.decrypt(wrapped_key, oaep)
plaintext = AESGCM(recovered_key).decrypt(nonce, ciphertext, None)
実装で落としやすいのがnonceの扱いです。AES-GCMは同じ鍵で同じnonceを二度使うと、2つの平文のXORが露出したうえに認証鍵まで復元され、改ざんの検知が効かなくなります。セッション鍵を使い回す設計にした時点でこの危険が生じます。上のコードのようにセッション鍵を毎回生成すれば、この事故は構造的に起きません。パディングもOAEPを指定してください。PKCS#1 v1.5はパディングオラクル攻撃の対象として長く知られており、新規実装で選ぶ理由がありません。
PQCハイブリッド鍵交換という第二の語義
2024年以降、「ハイブリッド暗号」が従来型とは別の対象を指す場面が増えました。従来の楕円曲線鍵共有と耐量子KEMを同時に走らせ、両方の共有秘密を結合して1つの鍵にする方式です。NIST IR 8547の草案は3.2節でこれをPQC-Classical Hybrid Protocolsとして扱い、構成要素のうち少なくとも一方が安全であれば全体の安全性が保たれる設計だと説明しています。つまり耐量子アルゴリズムに未知の欠陥が見つかっても、従来方式が残るため即座には破綻しません。
この2つの語義は排他ではありません。PQCハイブリッドが置き換えるのは鍵交換の部分だけで、本文をAES-GCMで暗号化するというKEM/DEM構成そのものは変わらないためです。
X25519MLKEM768のコードポイントと採用状況
TLSでの具体的な組合せはIETFのdraft-ietf-tls-ecdhe-mlkemが定義しています。2026年5月26日改版の第5版時点でRFC番号は付与されておらず、RFC Editorの発行待ちの状態です。定義されている名前付きグループは次の3つです。
| 名前付きグループ | コードポイント | 組合せ |
|---|---|---|
| SecP256r1MLKEM768 | 0x11EB(4587) | secp256r1 + ML-KEM-768 |
| X25519MLKEM768 | 0x11EC(4588) | X25519 + ML-KEM-768 |
| SecP384r1MLKEM1024 | 0x11ED(4589) | secp384r1 + ML-KEM-1024 |
ドラフト段階にもかかわらず実装は先行しています。OpenSSLは3.5.0(2025年4月8日リリース)でML-KEM・ML-DSA・SLH-DSAに対応し、TLSの既定keyshareをX25519MLKEM768とX25519の2つに変更しました。サーバー側で特別な設定をしていなくても、OpenSSL 3.5系へ更新した時点でハイブリッド鍵交換が候補に入っている、ということです。導入判断にあたってはOpenSSL 3.5 LTSと4.0の選び方もあわせて確認してください。
組み合わされるML-KEMの側は、NISTがFIPS 203「Module-Lattice-Based Key-Encapsulation Mechanism Standard」として2024年8月13日に確定させた標準です。ML-KEM-512、ML-KEM-768、ML-KEM-1024の3パラメータセットが定義され、安全性はモジュール格子上の誤差付き学習問題の計算困難性に基づきます。KEMの実装上の推奨事項は、2025年9月18日に最終版が出たSP 800-227が扱っています。
ML-KEM-768の実測サイズとHPKEでの実装
Pythonのcryptographyは47.0.0(2026年4月24日)でML-KEMとHPKEのモジュールを追加しましたが、この時点ではAWS-LCまたはBoringSSLでビルドした環境が必要で、公式ホイールの利用者は使えませんでした。48.0.0(2026年5月4日)でOpenSSL 3.5.0以降に対応し、標準のホイールでも耐量子アルゴリズムが動くようになっています。ML-KEM単体を試すならこの48.0.0が下限で、後述するHPKEでのハイブリッド構成は本記事の検証環境である49.0.0で確認しています。
from cryptography.hazmat.primitives.asymmetric.mlkem import MLKEM768PrivateKey
private_key = MLKEM768PrivateKey.generate()
public_key = private_key.public_key()
# 送信側: 共有秘密とKEM暗号文を同時に得る
shared_secret, kem_ciphertext = public_key.encapsulate()
# 受信側: KEM暗号文から同じ共有秘密を復元する
assert private_key.decapsulate(kem_ciphertext) == shared_secret
実行して測った値は、公開鍵が1,184バイト、秘密鍵のシードが64バイト、共有秘密が32バイト、KEM暗号文が1,088バイトでした。RSA-3072で包んだ鍵が384バイトだったことと比べると、KEM暗号文だけで3倍近く増えます。ハンドシェイクのパケットサイズが増える点は、MTUが小さい経路や組込み機器で実測が要る箇所です。
従来方式との併用まで含めて試すなら、RFC 9180のHPKEを使うと数行で書けます。同ライブラリはKEMとしてMLKEM768_X25519を選択でき、これはTLSのX25519MLKEM768と同じ組合せです。
from cryptography.hazmat.primitives import hpke
from cryptography.hazmat.primitives.asymmetric import x25519
from cryptography.hazmat.primitives.asymmetric.mlkem import MLKEM768PrivateKey
# ML-KEM-768 と X25519 を束ねたハイブリッド鍵
private_key = hpke.MLKEM768X25519PrivateKey(
MLKEM768PrivateKey.generate(),
x25519.X25519PrivateKey.generate(),
)
suite = hpke.Suite(
hpke.KEM.MLKEM768_X25519,
hpke.KDF.HKDF_SHA256,
hpke.AEAD.AES_256_GCM,
)
blob = suite.encrypt(b"hybrid pqc", private_key.public_key(), b"context-info")
assert suite.decrypt(blob, private_key, b"context-info") == b"hybrid pqc"
このKEMのencapsulated keyは1,120バイトで、ML-KEM-768の1,088バイトにX25519の32バイトを足した値と一致します。KEM・KDF・AEADの3要素を明示的に指定する形になっている点に注目してください。ハイブリッド暗号方式の構成要素が、そのままAPIの引数として現れています。
2030年・2035年の移行期限と日本の調達要件
NIST IR 8547草案が示す2030年・2035年の年次
移行をいつまでに終えるかについては、NISTが具体的な年を示しています。NIST IR 8547の初期公開草案(2024年11月12日公開)のTable 4では、鍵確立に使う有限体DH・楕円曲線DH・RSAについて、112ビット相当の安全性強度のものを2030年より後は非推奨(deprecated)、2035年より後は使用不可(disallowed)とする方針が示されました。128ビット以上の強度でも2035年より後は使用不可です。デジタル署名側のECDSA・RSAにも同じ年次が設定されています。
ここは断定を避けるべき箇所です。IR 8547は初期公開草案の段階にあり、意見募集は2025年1月10日に締め切られたものの、本記事の執筆時点で最終版は公開されていません。年次が変わる可能性は残るため、社内の移行計画に落とす際はNISTの公開状況を直接確認してください。なお米国の国家安全保障覚書NSM-10は、連邦システムの耐量子暗号移行の主目標を2035年と定めています。
CRYPTREC暗号リストと統一基準令和7年度版の参照関係
日本国内では、政府機関向けの調達で参照されるのはCRYPTREC暗号リストです。最新版はCRYPTREC LS-0001-2022R2で、2026年3月30日に更新されています。「政府機関等のサイバーセキュリティ対策のための統一基準(令和7年度版)」が2025年6月27日に決定され、情報システムで使う暗号アルゴリズムと鍵長はこのリストに基づいて定めることが求められています。公共案件を扱う場合、NISTの年次だけでなくCRYPTREC側の掲載状況を確認する必要があります。
長期秘匿データから着手する移行順序
実務上の優先順位ははっきりしています。まず着手すべきは、長期間秘匿が必要なデータを流している経路です。暗号化された通信を今のうちに保存しておき、量子計算機が実用化された将来に復号するという攻撃手法が想定されているためです。逆に、セッション単位で完結し数分後には価値を失うデータの経路は後回しで構いません。量子計算機の実用化がどの段階にあるかは量子コンピュータの仕組みと実用化の現在地で整理しています。
鍵管理で破綻する条件と回避策
ハイブリッド暗号方式そのものが破られる事例より、鍵の扱いを誤って安全性を失う事例のほうが圧倒的に多いのが実情です。設計段階で確認すべき条件を挙げます。
- 秘密鍵をアプリケーションのリポジトリや設定ファイルに平文で置いている
- セッション鍵を使い回し、AES-GCMで同じnonceを再利用している
- 公開鍵の正当性を証明書で検証せず、受け取った鍵をそのまま使っている
- 鍵の更新手順が用意されておらず、漏洩時に無効化できない
3番目は特に見落とされます。ハイブリッド暗号方式は「正しい相手の公開鍵を持っている」ことを前提に成立するため、公開鍵をすり替えられれば暗号化していても中身は読まれます。これを防ぐのが認証局の署名による証明書検証であり、暗号化と認証は別の仕組みで担保されている、という理解が要ります。
秘密鍵の保管は、自前でファイルを暗号化するよりAWS KMSのようなキーポリシーを持つ鍵管理サービスに預けるほうが確実です。鍵そのものを取り出さずに暗号化・復号を実行でき、アクセス記録も残ります。なお、パスワードの保管に暗号化を使うのは設計の誤りで、そこはハッシュ化の領域です。両者の使い分けはハッシュ化と暗号化の違いで解説しています。
よくある質問
ハイブリッド暗号方式と公開鍵暗号方式は何が違いますか?
公開鍵暗号方式は単独の暗号方式の名前で、ハイブリッド暗号方式は共通鍵暗号方式と公開鍵暗号方式を組み合わせた構成の名前です。ハイブリッド暗号方式の内部では公開鍵暗号が共通鍵を運ぶ役割で使われており、両者は対立する選択肢ではありません。
ハイブリッド暗号方式はどこで使われていますか?
HTTPS(TLS)、SSH、S/MIMEやPGPによるメール暗号化、IPsecによるVPNなど、インターネット上の暗号化通信の大半がこの構成です。ただしTLSやSSHは共通鍵を直接暗号化して送るのではなく、鍵共有によって双方が同じ鍵を導出する形を取ります。
暗号鍵はどのように管理すべきですか?
セッション鍵は通信ごとに生成して使い捨て、長期保持する秘密鍵はクラウドの鍵管理サービスやHSMに置いて取り出さない運用が基本です。あわせて、鍵の有効期限と漏洩時の無効化手順を運用開始前に決めておいてください。手順が無いまま運用を始めると、漏洩時に取れる手段がありません。
RSAはもう使えなくなりますか?
直ちに使えなくなるわけではありません。NIST IR 8547の草案では、112ビット相当の強度のRSAによる鍵確立は2030年より後が非推奨、2035年より後が使用不可という方針です。ただしこれは草案段階の年次であり、最終版で変わる可能性があります。現時点で新規に構築するなら、鍵交換にPQCハイブリッドを選べる構成にしておくのが安全側の判断です。
量子コンピュータが実用化されたら通信は全部読まれますか?
影響を受けるのは公開鍵暗号の部分で、AESのような共通鍵暗号は鍵長を伸ばせば対処できるとされています。そのためハイブリッド暗号方式のうち、置き換えが必要なのは鍵交換・鍵配送の側です。X25519MLKEM768のようなハイブリッド鍵交換は、従来方式と耐量子方式のどちらか一方が安全なら成立するよう設計されています。