PR 本記事には広告(Amazonアソシエイト・もしもアフィリエイト・A8.net等)が含まれます。掲載情報の正確性には努めていますが、商品の詳細は必ずリンク先で最新情報をご確認ください。
CTF・セキュリティ学習

【RSA基礎編】素因数分解・小さい指数・Common Modulusの攻め方|CTF思考フレームワーク #52

かも次郎とアンペンが「RSA」を解説するマスコットイラスト
安全に生きたい編集部

こんにちは、アンペンです!

今回は公開鍵暗号の王様、RSAの基礎編です。CTFの暗号カテゴリで最も登場する暗号方式であり、現実のTLS・SSH・PGPでも長年使われてきた要のアルゴリズムです。

『素因数分解の難しさ』を安全性の根拠にしているため、nが弱いと一瞬で崩れるのがCTF的に最高に楽しいポイントです。

『あんな巨大な数学が、なぜCTFでは解けるの?』——いい質問です。種明かしをすると、CTFのRSAは“わざと弱く”作られているから。本物のRSAは2048ビットという気の遠くなる桁数ですが、CTFでは『nがやけに小さい』『eが3しかない』『同じnを使い回している』といった“実装ミス”をあえて仕込んで、練習させてくれるんです。つまり解くべきは数学そのものではなく、『どんなミスが仕込まれているか』を見抜くこと。だから初心者でも、ちゃんと楽しめます。

RSAって超巨大な数学のやつでしょ?なんでCTFで解けるの?

CTFは『わざと弱いパラメータ』になっているからね。nが小さすぎる・eが小さすぎる・同じnを使い回し…そんな実装ミスをわざと作って練習させてくれるんだ。

RSAと聞くと『超巨大な数式のかたまりで、自分には無理』と身構えてしまうかもしれません。でも安心してください。RSAの“心臓部”は、たったひとつのシンプルな事実です——『2つの数を掛け算するのは簡単。でも、掛け算の答えから元の2つに戻すのは、とてつもなく難しい』。この一方通行の性質だけで、世界中の通信を守る暗号が成り立っています。今日はその仕組みと、“弱く作られたRSA”の崩し方を見ていきましょう。

まず結論

RSAの安全性は『n=p×q の素因数分解が困難』に依存します。CTFでは(1)nが小さい/factordbに載っている (2)p,qが近い(Fermat) (3)eが小さく平文が小さい(Low Exponent) (4)同じnで異なるe(Common Modulus) (5)複数nに共通素因子(共通GCD)の5パターンが頻出。守る側は2048bit以上+OAEPパディング+nの使い回し禁止を徹底します。

この記事で分かること

  • RSAの鍵生成・暗号化・復号の流れ
  • nが弱いときの5つの定番攻撃
  • RsaCtfTool / factordb / SageMath の使い方
  • 実装時のセキュアな設定
難易度:中級向け 所要時間:13分 体験:弱いnのRSAを実際に解く おすすめ:#51の後

📖 はじめてのWebセキュリティ #52|RSA基礎編
素因数分解・小さい指数・Common Modulusの攻め方を扱います。 シリーズ一覧を見る →

⚠️ 大事なお約束
他者の暗号化されたデータ・通信を無断で復号する行為は、業務上の権限や法律に違反します。CTFや公開された練習問題のみで確認してください。

RSAの仕組みをざっくり3式で

RSAは『大きな2つの素数 p, q を選んで n = p × q とする』ところから始まります。n と e の組(公開鍵)からd(秘密鍵)を作るのに p, q が必要、というのがミソ。p, q を外に出さず n だけ公開すれば、原理上 d は他人には作れません。

ここがRSAのいちばんの肝なので、もう少しかみ砕きます。p と q という2つの素数を掛けて n を作るのは、電卓で一瞬。でも、できあがった n だけを渡されて『元の p と q は何だった?』と聞かれると、桁が大きいほど絶望的に難しい。この“掛けるのは楽、割り戻すのは地獄”という非対称さこそ、RSAの安全性そのものです。逆に言えば、n さえ素因数分解できてしまえば、秘密鍵 d は芋づる式に作れて、暗号は全部開いてしまうわけです。

  • 鍵生成:p, q を選び n=p×q、φ(n)=(p-1)(q-1)、d ≡ e^(-1) mod φ(n)
  • 暗号化:c = m^e mod n(公開鍵 e で m を上げる)
  • 復号:m = c^d mod n(秘密鍵 d で戻す)

図解:RSAの鍵と式の関係

n, e, d, p, q, φ(n) という6つの登場人物の関係さえ掴めば、後の攻撃手法はすべてこの図上で動いている話だと分かります。

登場人物が6つも出てきて頭が痛くなりますが、関係はシンプルです。公開していいのは n と e の2つだけ。p, q, φ(n), d の4つは“絶対に隠す秘密”です。そして、この秘密グループは n を素因数分解できた瞬間に、ドミノ式に全部バレてしまう。だから攻撃側の狙いはいつもひとつ——『どうにかして n を p と q に割りたい』。これから出てくる5つの攻撃も、結局はこの一点を、いろんな“弱点”から突いているだけなんです。

RSAの鍵生成・暗号化・復号の3段階フローと公開鍵・秘密鍵の関係を示した図解
図1:RSAは鍵生成→暗号化→復号の3段階。nを素因数分解できれば全部破れる
🔐 たとえるなら、特注の南京錠

公開鍵 (n, e) は『南京錠そのもの』。誰でも掛けられますが、開ける鍵は持っていません。秘密鍵 d は『この錠を開ける鍵』で、製造者(=鍵生成者)だけが持っています。錠の構造(n)は誰にでも見えますが、構造から鍵の歯形を逆算するのは『p, q を見抜く=素因数分解』に等しく、桁が大きいほど困難になります。

誰でも掛けられるが開ける鍵は1本だけという公開鍵暗号のたとえイラスト
図2:誰でも掛けられるが、開ける鍵は1本だけ。それが公開鍵暗号

ここで覚える用語:素因数分解の困難性
RSAの安全性の根拠です。2048bitのnを素因数分解するには、現実的な時間では計算不能(年単位の計算機リソース)とされています。逆に言えば、nが200bit程度なら自宅PCで分解可能500bit付近はクラウドで数日768bit以下は既に破られた実績あり。CTFでは300〜700bit程度の弱いnがよく出てきます。

CTF頻出!RSA攻略5パターン

攻め方マップ

  • ① factordb 照会:有名な弱いn(過去CTF出題)はDBに登録済み。まずfactordb.comに投げる
  • ② Fermat法:p,qが近い場合 n=a²−b²=(a+b)(a−b) で分解。RsaCtfToolが自動でやってくれる
  • ③ Low Public Exponent (e=3):m^3 < n なら mod n の影響なし。iroot(c,3)で立方根
  • ④ Common Modulus:同じ n を別のe1, e2 で使うと、ベズーの等式で gcd(e1,e2)=1 ⇒ m が復元
  • ⑤ Common Factor:2つの n1, n2 が同じ p を共有 ⇒ gcd(n1, n2) = pで一発

5パターンの判別ポイントは『与えられた情報』を見るだけ。e=3が見えたら③、複数(n,c)組があれば④か⑤、と一瞬で当たりが付きます。

面白いのは、『どの攻撃を使うか』が、問題で“与えられた情報”を眺めるだけで決まってしまう点です。eが3みたいに小さければLow Exponentを疑い、同じnに対して暗号文が2つ以上配られていればCommon Modulusを疑う。料理でいえば、冷蔵庫の中身を見てメニューを決めるようなもの。RSA問題を開いたら、まず『何が渡されているか』をリストアップする——これが解答への最短ルートになります。

factordb・Fermat・Low e・Common Modulus・Common Factorの5つのRSA攻撃パターンを横並びカードで示した図解
図3:CTFで出るRSA問題はこの5パターンでほぼ網羅できる

RsaCtfTool 1本でほぼ自動化できる

CTFのRSA問題は、RsaCtfTool(GitHub)に公開鍵PEMと暗号文を投げれば9割は自動で解けます。各種攻撃を順に試して、当たれば復号結果を吐いてくれる優れもの。

  • ./RsaCtfTool.py -n <n> -e <e> --uncipher <c>
  • ./RsaCtfTool.py --publickey pub.pem --uncipher c.bin
  • 裏で factordb, Fermat, Wiener, Pollard などを順次試す

これに加えて、複雑な攻撃にはSageMath(数式処理系)が定番。Lattice系の応用編は#53で扱います。

『ツールが自動で解くなら、原理を学ぶ意味は?』と思うかもしれません。でも、むしろ逆です。RsaCtfToolは“なぜ解けたか”までは教えてくれないので、原理を知らないと『たまたま解けた』で終わってしまう。本番で少しひねられた問題が出たとき、手が出るかどうかは原理の理解しだいです。ツールは時短の相棒として使いつつ、『今どの弱点を突いたのか』を毎回ふり返るクセをつけましょう。

CTFでやってみよう:弱いRSAを自分で解く

やってみよう / 自分の環境・CTFのみ

200bit RSAを自宅PCで素因数分解する

目的は『nが小さいと一瞬で崩れる』を体感することです。

  1. Pythonで p, q を 100bit 程度の素数として2つ生成(sympy.randprime)
  2. n = p×q, e=65537, m=”FLAG{rsa_baby}” を整数化して c = pow(m,e,n)
  3. n を factordb.com に投げる(知名度が低いn は出ない)
  4. 出なければ RsaCtfTool で分解を試す
  5. p, q が出たら d を計算し、c を復号して FLAG を取り出す
  6. 次に同じnでe1=3, e2=65537の2つの暗号文を作り、Common Modulus攻撃を試す
他者の暗号文を解く目的でこれを使わないでください。本物のRSAキーは2048bit以上で、現実的時間では破れません。検証は自作データかCTF配布データのみで。

ここまで“崩し方”を見てきましたが、裏返せば、そのまま“守り方”になります。CTFで頻出の敗北フラグ——nが小さい・eが小さい・nを使い回す——を、実装の段階で1つも作らないこと。それが守る側のチェックリストです。

守る側:RSAを安全に使うチェックリスト

実装時のセキュア設定
  • 鍵長はRSA-2048以上(将来的にはRSA-3072推奨)
  • p, q を暗号論的乱数で生成(言語標準のrandomはNG、secrets系を使う)
  • パディングは必ずOAEP(PKCS#1 v1.5は避ける)
  • 署名にはRSA-PSSを使う(古いPKCS#1 v1.5署名は避ける)
  • 同じnを複数システムで使い回さない(Common Factorの温床)
  • 新規システムではECDSA/EdDSA等の楕円曲線系を検討(鍵が短く速い)

nがちっちゃい・eがちっちゃい・nを使い回す、が全部敗北フラグなんだね。

そう。次回はRSA応用編。Wiener攻撃やCoppersmith法など、もっと数学的にエレガントな攻撃を扱うよ。

ここまでをひと言でまとめると、RSAは『nを素因数分解できれば終わり』。だから攻める側は“nの弱点”を5パターンで探し、守る側は“nを強く保つ”ことに集中する。攻守どちらも、見ているのは結局おなじ n だった——そう捉えると、ごちゃっとした攻撃名もスッキリ整理できます。

まとめ:『nが弱い5パターン』をまず疑う

今回のポイント
  • RSAは素因数分解の困難性で安全
  • 頻出5パターン:factordb / Fermat / Low e / Common Modulus / Common Factor
  • 定番ツール:RsaCtfTool / factordb / SageMath
  • 守りは2048bit+OAEP+nの使い回し禁止

今日の持ち帰りは『RSAは数学が難しいのではなく、ミスを見抜くゲーム』。本物のRSAは強固ですが、パラメータの選び方を一つ間違えるだけで一瞬で崩れます。攻める人は“渡された情報”からミスを探し、守る人は“ミスを作らない”。この視点さえあれば、次のRSA応用編もぐっと楽に読めますよ。

次回はRSA応用編、Wiener・Hastad Broadcast・Coppersmithといった、Lattice(格子)を使うエレガントな攻撃を扱います。

次に読みたい記事

参考資料

記事URLをコピーしました