【CTF実践編|第5話/全10話】RSA暗号を破る|鍵が小さすぎる落とし穴

⚡ CTF実践編|第5話/全10話

RSA暗号を破る|鍵が小さすぎる落とし穴

Webの安全な通信を支える公開鍵暗号RSA。その安全性は「大きな数の素因数分解は時間がかかる」という前提に支えられています。今回は、鍵の数字が小さすぎる場合に、ブラウザだけで素因数分解して秘密鍵を復元する体験をします。

🔑 RSA暗号 🔢 素因数分解 📐 公開鍵暗号 ⭐ 難易度:★★★★☆
01

💭 前回の振り返り|言語の罠から数学の罠へ

第4話のJS言語の仕組みから、今回は暗号の数学的な前提へ

🔗

これまでは「実装」、今回は「数学」の弱点

第1〜4話で見てきた弱点は、いずれも「実装の仕方」に原因がありました。今回のRSA暗号は、実装が完璧でも、暗号方式が前提としている数学的な仮定(大きな数の素因数分解は時間がかかる)が崩れてしまうと、安全性そのものが失われるという話です。

📌

この話の前提知識

前作で学んだ古典暗号の発想(総当たり攻撃)を、現代の暗号方式に応用します。

シーザー暗号やXOR暗号は「鍵の候補が少ない」ことが弱点でした。RSA暗号はまったく別の仕組みですが、今回はやはり「鍵に使われている数字が小さすぎる」ことが弱点になります。暗号方式の世代が変わっても、「探索範囲が現実的に総当たりできてしまう」という弱点のパターンは繰り返し登場します。

RSAは1977年に発表された、現在も広く使われている公開鍵暗号方式です。HTTPS通信の鍵交換や電子署名など、Webのセキュリティを支える基盤技術の1つになっています。今回はその仕組みを支える数学を実際に動かしながら理解していきます。

02

📐 RSA暗号とは何か|公開鍵と秘密鍵の関係

誰でも暗号化できるが、特定の人しか復号できない仕組み

RSAは「公開鍵暗号」という方式の1つです。暗号化に使う鍵(公開鍵)と復号に使う鍵(秘密鍵)が異なり、公開鍵は誰に見られても問題ありません。仕組みの核心は、2つの大きな素数pqを掛け合わせた数n = p × qです。公開鍵は(n, e)の組、秘密鍵はdという数値で、暗号化と復号は次のシンプルな計算だけで行われます。

公開鍵 (n, e) 誰でも見られる 暗号化: c = m^e mod n 平文 m → 暗号文 c 秘密鍵 d 持っている人だけ復号できる 復号: m = c^d mod n 暗号文 c → 平文 m 暗号文 c を送る n = p × q 2つの大きな素数の積 ⚠ pとqが分かれば d も計算できてしまう
💡

dを計算する手順

pqが分かれば、φ(n) = (p-1)(q-1)という値を計算できます。秘密鍵dは「eφ(n)を法とする逆数」、つまりe × d ≡ 1 (mod φ(n))を満たす数で、拡張ユークリッドの互除法という古くからある算法で計算できます。つまりnを素因数分解できれば、秘密鍵dも手に入るということです。

公開鍵に使うeは、多くの実装で65537という決まった値が使われます。これは2進数で表すと1のビットが2つだけというシンプルな形をしており、暗号化の計算(繰り返し二乗法)が高速になるという実務上の理由から広く採用されています。今回のラボでも、この実用的な値をそのまま使っています。

03

🔢 鍵が小さいとどうなるか

素因数分解の「時間がかかる」を支えているのは桁数

RSAの安全性は「nが大きければ素因数分解に非現実的な時間がかかる」という前提の上に成り立っています。実際に使われている鍵は2048ビット(10進数で600桁以上)が標準ですが、今回のチャレンジでは学習用にずっと小さいnを使います。

鍵の長さnの桁数(10進)素因数分解にかかる時間の目安
RSA-2048(実用標準)約617桁現在のコンピュータでは非現実的
RSA-512(過去に使われ破られた)約154桁専用環境で数時間〜数日
本チャレンジのn10桁ブラウザで一瞬

桁数が1桁増えるたびに、試し割り法で確認すべき候補の数はおおよそ10倍に増えます。鍵のビット数を2倍にしただけで、素因数分解にかかる時間は2倍どころか天文学的に増大します。この「桁数に対して指数的に難しくなる」という性質こそが、RSAという暗号方式全体の安全性を支える土台です。

⚠️

素因数分解の最も単純な方法:総当たり除算

最も単純な素因数分解の方法は、2から√nまでの数で順番に割り切れるか試すことです(試し割り法)。nが10桁程度なら、√nはわずか5桁程度で、現代のブラウザなら一瞬で総当たりが終わります。これが「鍵が小さいと簡単に破られる」という現象の最も直接的な理由です。

実際の現場でも、暗号方式そのものではなく「鍵をどう生成したか」が原因で似た問題が起きることがあります。乱数生成が不十分な環境で鍵を作ると、本来はランダムであるはずの素数が偏ったり、他の機器と同じ素数を共有してしまったりすることが報告されています。アルゴリズムが正しくても、鍵生成の品質が低ければ同じ穴に落ちる、という点は覚えておく価値があります。

04

🧪 実践チャレンジ:RSAラボで秘密鍵を復元する

nを割って、dを求めて、暗号文を1バイトずつ復号する

下のラボには、傍受した公開鍵(n, e)と、1バイトずつ暗号化されたフラグの暗号文(25個の数値)が表示されています。

🎯

チャレンジの手順

① 「nを素因数分解する」を押す → ② 表示された2つの素因数のうち小さい方を、ステージ1にFACTOR-番号の形式で入力 → ③ 「復号する」を押す(秘密鍵dが自動計算され、25個の暗号文が一括復号されます) → ④ 表示されたフラグをステージ2に入力。

公開鍵:

n = 7202220143, e = 65537

暗号文(25バイト分):

5068353288, 2021620677, 6756090224, 7043856588, 3306126710, 512255913, 3314208315, 498112345, 512255913, 5769993135, 2834058101, 2851037683, 2851037683, 498112345, 6436319174, 498112345, 6756090224, 3314208315, 5068353288, 2021620677, 5762252897, 3306126710, 6560510798, 3298267262, 1550249072

🎉 復号成功!

復元されたフラグ:

🧩 実践チャレンジ:2つのステージを繋いでフラグを掴め

ステージ1をクリアすると、ステージ2が解放されます。両方クリアした時点でスコアが確定します。

📊 ステージ進捗: 0/2|挑戦回数: 0回

1ステージ1:nを素因数分解する

ラボで見つかった2つの素因数のうち、小さい方をFACTOR-番号の形式で入力してください。

05

🛡️ なぜ現実のRSAは(今のところ)安全なのか

桁数を増やすだけで、計算量が爆発的に増える

素因数分解にかかる時間は、桁数が増えるとおおむね指数関数的に増加します。今回のチャレンジのnは10桁でしたが、実用標準のRSA-2048は617桁です。試し割り法のような単純な方法はもちろん、現在知られている最も効率的な素因数分解アルゴリズムを使っても、十分なビット数のRSA鍵を分解するには、現在のコンピュータの能力では非現実的な時間が必要になります。

⚠️

将来の脅威:量子コンピュータとショアのアルゴリズム

「ショアのアルゴリズム」という量子コンピュータ向けのアルゴリズムを使うと、素因数分解を現在のコンピュータより大幅に高速に行えることが理論的に知られています。十分な性能の量子コンピュータが実用化されればRSAの前提が崩れる可能性があるため、それに耐えられる「耐量子暗号(Post-Quantum Cryptography)」への移行が現在進められています。

次回は暗号の話を続けます。AESのようなブロック暗号で使われる「ECBモード」という動作方式が、暗号文に平文の構造を漏らしてしまう様子を、目で見て確認する体験をします。

06

📝 まとめ+FAQ+次回予告

暗号の強さは「数学的な前提」が崩れていないかで決まる

第5話では、RSA暗号の仕組みを理解し、鍵が小さい場合に素因数分解で秘密鍵を復元する体験をしました。暗号方式そのものに欠陥がなくても、使う鍵のサイズという「前提条件」を誤ると安全性が崩れることを実感できたはずです。第1〜4話の「実装ミス」「言語の罠」に続いて、今回は「暗号方式が前提とする数学的な仮定」という、また違う視点の弱点を扱いました。

✅ 今回のまとめチェック

・RSAは公開鍵(n,e)で暗号化、秘密鍵dで復号する公開鍵暗号方式
・n = p × q が分かれば φ(n) を計算でき、そこから秘密鍵dも導出できる
・nの桁数が小さいと、試し割り法のような単純な方法でも素因数分解できてしまう
・実用標準のRSA-2048は617桁、今回のチャレンジは学習用にわずか10桁
・採点ルールは前話までと同じ(ヒント-15pt、両ステージ解決でスコア確定)

Q. 実際のWebサイトの通信もこの方法で簡単に破られますか?

いいえ。実用標準のRSA-2048は617桁にも及ぶ巨大な数を使っており、現在知られているどの方法を使っても、現実的な時間で素因数分解することはできません。今回のチャレンジは学習用にあえて極端に小さい鍵を使っています。

Q. なぜ1バイトずつ暗号化したのですか?まとめて暗号化しないのですか?

RSAで暗号化できる平文の大きさは、nより小さい数に限られます。今回のnは10桁程度しかないため、フラグ全体を一度に暗号化すると数が大きすぎて扱えません。学習用に1バイト(0〜255)ずつ暗号化する設計にしました。実際のRSA運用でも、長いデータを直接RSAで暗号化することは少なく、共通鍵暗号の鍵だけをRSAで暗号化するハイブリッド方式が一般的です。HTTPSの通信でも、実際のデータ本体はAESのような高速な共通鍵暗号でやり取りされ、RSAはその共通鍵を安全に受け渡す部分だけに使われています。

Q. eの値はどんな数でもいいのですか?

条件があります。eφ(n)と互いに素(最大公約数が1)である必要があります。実用上は65537という値がよく使われており、今回のチャレンジでもこの値を採用しています。

Q. 試し割り法より速い素因数分解の方法はありますか?

あります。フェルマー法・ポラードのrho法・楕円曲線法・一般数体篩法(GNFS)など、桁数に応じてさまざまな高速化手法が研究されています。今回のチャレンジは試し割り法だけで十分解けるよう、あえて小さい鍵にしています。

次回・第6話

ECBモードの弱点を見抜く|暗号文に浮かぶパターン

ブロック暗号の動作モードの違いを学び、ECBモードが平文の構造をどのように漏らしてしまうかを視覚的に確認します。

📚 参考情報

  • RFC 8017 — PKCS #1: RSA Cryptography Specifications
  • NIST SP 800-57 — 鍵サイズに関する推奨事項

コメント