セキュリティ●●●○○

公開鍵暗号

Public-Key Cryptography ・ こうかいかぎあんごう

公開してよい鍵と秘密の鍵の対を使う暗号。事前の鍵共有なしに秘密の通信と署名を可能にした。

✦ 30秒で試す — 航海会ったこともない相手と、盗み聞きされながら秘密を決める盗聴者は、写した公開鍵でメモを元に戻せる?予想してみる

概要

公開鍵暗号は、数学的に対になった2つの鍵を使う暗号の仕組みです。片方の公開鍵は世界中に配ってよく、もう片方の秘密鍵は本人だけが厳重に保管します。公開鍵で暗号化したデータは、対になる秘密鍵でしか復号できません。だから「私の公開鍵で暗号化して送ってください」と言うだけで、会ったことのない相手とも秘密のやり取りを始められます。

同じ鍵ペアは逆向きにも使えます。秘密鍵で作った「署名」は、公開鍵を持つ誰もが検証できるので、「この文書は確かに本人が出したもので、途中で書き換えられていない」ことを証明できます。さらに、ディフィー・ヘルマン鍵共有のように、暗号化も署名もせずに、互いの公開値を交換するだけで同じ共通鍵を導く使い方もあります。厳密にはこれは暗号化ではなく「鍵共有」ですが、同じ発想から生まれた仲間として、まとめて公開鍵暗号と呼ばれます。

現代のインターネットはこの仕組みなしには成り立ちません。HTTPS の接続開始、SSH の鍵認証、ソフトウェアや OS アップデートの署名、パスキーによるログインと、「会ったことのない相手を信頼する」場面のほぼすべてで公開鍵暗号が土台になっています。

なぜ生まれたか

従来の暗号化、つまり共通鍵暗号には「鍵配送問題」という根本的な行き詰まりがありました。安全に通信するには鍵を共有しておく必要がありますが、その鍵を安全に渡すには、すでに安全な通信路が必要です。軍や銀行なら、信頼できる人が鍵を運ぶことで解決できました。しかし不特定多数がネットワークでつながる世界では、通信したい相手の数だけ事前の鍵共有が必要になります。世界中の EC サイトと買い物客が事前に鍵を郵送し合うのは、明らかに不可能です。

この行き詰まりを破ったのが、1976年にディフィーとヘルマンが発表した「暗号化と復号を別の鍵にすれば、暗号化用の鍵は公開してしまえる」という考え方でした。翌1977年には、それを実際の暗号として実現した RSA が発表されます。土台にあるのは、一方向には簡単だが逆向きは極端に難しい計算です。2つの大きな素数を掛け合わせるのは一瞬ですが、積から元の素数を割り出す(素因数分解する)のは、桁が大きければ現実的な時間では終わりません。この非対称性が、公開鍵から秘密鍵を割り出せない根拠になり、「事前の秘密の共有なしに、安全な通信を始める」ことが初めて可能になりました。

詳細

鍵ペアの2つの使い方

公開鍵暗号の使い方は、鍵を使う向きで2つに分かれます。秘密を送るときは、受け手の公開鍵で閉じて、受け手の秘密鍵で開けます。「誰でも閉じられるが、開けられるのは持ち主だけ」という南京錠の関係です。署名するときは向きが逆で、書き手の秘密鍵で作り、書き手の公開鍵で確かめます。「作れるのは持ち主だけだが、確かめるのは誰でもできる」という印鑑の関係です。

暗号化: 誰でも閉じられ、開けられるのは持ち主だけ送る人誰でもよい暗号文Bob秘密鍵の持ち主Bob の公開鍵で暗号化するBob の秘密鍵で復号する署名: 作れるのは持ち主だけ、確かめるのは誰でもBob秘密鍵の持ち主文書+署名中身は読める受け取る人誰でもよいBob の秘密鍵で署名を作るBob の公開鍵で署名を検証する金の枠と文字 = 秘密鍵が関わるところ。秘密鍵はどちらの使い方でも持ち主の手元から出ない
同じ鍵ペアでも、暗号化と署名では鍵を使う向きが逆になる

秘密を送る — 暗号化としての使い方

いちばん基本の使い方は、秘密を届けることです。受信者が鍵ペアを作り、公開鍵を配っておきます。送信者はその公開鍵で暗号化して送り、受信者は手元の秘密鍵で復号します。

受信者送信者受信者送信者鍵ペアを生成する公開鍵でメッセージを暗号化手元の秘密鍵で復号する公開鍵を渡す・盗聴されても問題ない暗号文を送る

ポイントは、秘密の情報(秘密鍵)が一度もネットワークを流れないことです。経路のすべてが盗聴されていても、公開鍵と暗号文から平文を割り出すことはできません。ただし、ここにはひとつ落とし穴があります。送信者が受け取った公開鍵が、本当に受信者のものだという保証がないのです。

下の部品では、公開鍵を「開いた南京錠」、秘密鍵を「その南京錠の鍵」として、南京錠を配るところから自分の手で運びます。盗聴者の手元に南京錠と閉じた箱がたまっても開かないこと、経路の途中に中間者がいると南京錠がすり替えられてしまうこと、CA の印がそれをどう防ぐかを、切り替えて確かめてください。

⚡ 体験: 南京錠を配って、秘密を届ける
経路の上
インターネット(丸見えの経路)Alice送る人Bob受け取る人盗聴者経路を盗み見る秘密のメモBob の秘密鍵Bob の南京錠
あなたが運んだ順に描かれるシーケンス図
AliceBobまだ何も運んでいません

Alice は Bob に秘密のメモを送りたいのですが、2人は鍵を共有していません。まず Bob の開いた南京錠(公開鍵)をつかんで、Alice へ運んでください。途中の経路は丸見えです。

本人を証明する — 電子署名としての使い方

署名では、秘密鍵で作った値を、対になる公開鍵で誰でも検証できます。秘密鍵を持っているのは本人だけなので、「この署名を作れたのは本人だけで、署名した後に内容は変わっていない」ことが保証されます。実際には長いデータ全体ではなく、ハッシュ化した短い値(ダイジェスト)に署名します。

検証者署名者検証者署名者文書のハッシュ値を計算する秘密鍵とハッシュ値から署名を作る受け取った文書のハッシュ値を自分で計算する公開鍵・ハッシュ値・署名を検証の式に入れる式が成り立てば本人の署名で未改ざん文書と署名を送る

「署名は秘密鍵で暗号化すること、検証は公開鍵で復号してハッシュ値を取り出すこと」という説明を見かけますが、これは RSA だけに当てはまる見方です。いま主流の ECDSA や Ed25519 では署名から何かを取り出すことはなく、公開鍵・ハッシュ値・署名が決められた式を満たすかどうかを確かめます。一般には「署名の生成」と「検証(成り立つか否か)」の2つの操作だと考えるのが正確です。

署名は至るところで使われています。JWT の署名検証、Git のコミットやタグへの署名、OS やアプリのアップデートが正規の配布元から来たことの確認、パスキーによるログイン(サイトごとの秘密鍵で、サーバが送ってきた値に署名する)などです。

鍵を共有する — ディフィー・ヘルマンと TLS

公開鍵暗号の計算は、共通鍵暗号に比べて桁違いに重いという弱点があります。そこで実際のシステムでは、公開鍵暗号は「共通鍵を安全に取り決める」ことと「相手を確かめる」ことだけに使い、大量のデータは速い共通鍵暗号(AES など)で暗号化します。TLS がその代表です。

かつての TLS には、クライアントが作った共通鍵の素をサーバの RSA 公開鍵で暗号化して送る方式がありました。しかしこの方式では、後からサーバの秘密鍵が漏れると、録音しておいた過去の通信までさかのぼって解読されてしまいます。そのため TLS 1.3 では廃止され、楕円曲線ディフィー・ヘルマン(ECDHE)による鍵共有だけが使われます。双方が接続ごとに使い捨ての鍵ペアを作り、公開値だけを交換すると、それぞれ「自分の秘密」と「相手の公開値」から同じ共通鍵を計算できます。経路上の盗聴者は2つの公開値しか見ていないので、共通鍵を計算できません。サーバの長期の秘密鍵は、ここでは暗号化ではなく「この公開値を送ったのは確かに自分だ」という署名にだけ使われます。

サーバクライアントサーバクライアント使い捨ての鍵ペアを作る使い捨ての鍵ペアを作る自分の秘密と相手の公開値から同じ共通鍵を計算する証明書の公開鍵で署名を検証する通信が終わったら使い捨ての鍵は捨てるClientHello・一時公開値 AServerHello・一時公開値 B証明書と、ここまでの記録へのサーバの署名共通鍵で暗号化したデータ

使い捨ての鍵は通信が終われば捨てられるので、後でサーバの秘密鍵が漏れても、過去の通信は解読できません。この性質を前方秘匿性(Forward Secrecy)と呼びます。

残る問題 — その公開鍵は本物か

公開鍵暗号は鍵配送問題を解きましたが、新しい問題を生みました。受け取った公開鍵が本当に意図した相手のものかを、どう確かめるかです。攻撃者が経路の途中で公開鍵をすり替えれば、双方になりすまして通信を丸ごと読めてしまいます(中間者攻撃)。上の部品で見たとおり、暗号そのものは一度も破られていないのに、中身が漏れます。

この問題への答えのひとつが PKI(公開鍵基盤)です。信頼できる第三者の CA(認証局)が「この公開鍵は確かにこのドメインのものです」と署名した証明書を発行し、ブラウザや OS は、あらかじめ信頼すると決めた CA の署名を検証することで公開鍵の正しさを確かめます。HTTPS のサーバ証明書がこれで、CA は申請者がその DNS のドメインを本当に管理しているかを確かめてから発行します。一方 SSH は CA を介さず、初めて接続したときに相手の公開鍵を記録し、以後それが変わったら警告する方式(TOFU: Trust On First Use)を採っています。初回だけは人が指紋を確かめる必要がありますが、仕組みは簡単です。信頼をどこから始めるかにも設計の幅があるのです。

代表的なアルゴリズムと実務の注意点

代表的な方式は、素因数分解の難しさに基づく RSA と、より短い鍵で同等の強さを出せる楕円曲線暗号(署名の ECDSA・Ed25519、鍵共有の ECDH・X25519 など)です。新しく作るシステムでは楕円曲線系が主流で、RSA を使うなら鍵長は2048ビット以上にします。

実務でいちばん大切なのは秘密鍵の管理です。秘密鍵が漏れれば、なりすましも復号も思いのままです。リポジトリへの誤コミットは典型的な事故なので、秘密鍵はシークレット管理の仕組みで扱い、クラウドでは KMS や HSM(秘密鍵を外に出さずに署名や復号だけを行う専用機器)に閉じ込めて、アプリケーションには「署名してもらう権限」だけを与えるのが定石です。署名の検証側では、受け取った公開鍵や証明書を無条件に信じない、署名方式をデータ側の指定に任せない(JWT の alg の取り違えが典型)、といった点に注意します。

将来の脅威としては量子計算機があります。十分な規模の量子計算機が実現すると、RSA も楕円曲線暗号も効率よく解かれてしまいます。「いま暗号文を録音しておき、将来解読する」攻撃に備えて、NIST は2024年に耐量子計算機暗号(鍵共有の ML-KEM、署名の ML-DSA など)を標準化し、TLS では従来の方式と組み合わせたハイブリッドの鍵共有が使われ始めています。

試問

公開鍵暗号では、数学的に対になった鍵を2つ使います。公開鍵は誰に配ってもよく、秘密鍵は本人だけが持ちます。暗号化は受け手の公開鍵で閉じて秘密鍵で開け、署名は本人が秘密鍵で作って誰もが公開鍵で確かめます。下の8つを、盗聴者やネット上の誰かに見られても安全が崩れないものと、漏れたら安全が崩れるものに分けます。

✦ 命題挑戦中

8つのものを「公開してよい」と「本人だけが持つ」に仕分けよ

公開してよい誰に見られても安全は崩れない
本人だけが持つ漏れたら安全が崩れる

項目を選んでから、入れる箱を選びます