Upgrade to Pro — share decks privately, control downloads, hide ads and more …

体得しよう!RSA暗号の原理と解読

 体得しよう!RSA暗号の原理と解読

セキュリティ・ミニキャンプ in 大阪 2025 の講義資料・演習ヒント・解答

Sho Nakatani

March 20, 2025
Tweet

More Decks by Sho Nakatani

Other Decks in Programming

Transcript

  1. • 今日のゴール ◦ RSA暗号がわかるようになる!だけではない ◦ 暗号があらゆるところで使われていることを実感 ◦ 暗号化・復号を自分の手で実装した経験を得る ◦ 有名な暗号も正しく使わないと危険なことを知る

    • 受講者の皆さんの今後の姿(一例) ◦ セキュリティや開発の学習・仕事で「暗号ならわかる」と武器の一つに ◦ セキュリティコンテスト(CTF)で暗号カテゴリが得点源になる ◦ 暗号研究の道へ • ハンズオン(一緒にやる)・演習(質問しつつ自分でやる)について ◦ ハンズオンは一緒にやりましょう ◦ 演習はこの場で解けなくても大丈夫!後日自分で解いてみてください 講義の目的 2
  2. 中谷 翔 (トヨタ自動車) X, GitHub: @laysakura CTF, CryptoHack, HackTheBoxなどが趣味 Automotive

    CTF 国内決勝2位, 世界大会4位 (2024) 防衛省サイバーコンテスト 7位 (2024) OffSec Certified Professional (OSCP) (2024-) CISSP (2024-) 情報処理安全確保支援士 (合格; 2024-) Burp Suite Certified Practitioner (2023-) トヨタ 主幹/プリンシパル・リサーチャー (2021-) 東京大学大学院 情報理工学系研究科 修士卒 (2014) セキュリティ&プログラミングキャンプ (2010) 講師紹介 3
  3. • 第1部: ざっくり学ぶ!暗号・RSA暗号 (20分; 10:30 ~ 10:50) ◦ 暗号と実社会での使われ方 ◦

    共通鍵暗号・公開鍵暗号 ◦ RSA暗号概観 • 第2部: RSAの数理入門 (25分; 10:50 ~ 11:15) ◦ 暗号化・復号の数式を眺める・要素分解する ◦ [ハンズオン] 数学的要素を学ぶ (文字列↔整数 変換・剰余・モジュラ逆数・素因数分解) • 第3部: [ハンズオン] RSA暗号化・復号の実装 (30分; 11:15 ~ 11:45) • 第4部: [演習] RSAの解読 (65分; 11:45 ~ 12:50) ◦ 色々な "弱い" RSA暗号を用意しました ◦ コンテスト形式で演習しましょう • 付録: 今後の学習リソース紹介 (10分; 12:50 ~ 13:00) 講義の流れ(質問はいつでも挙手でOKです) 4
  4. 暗号と実社会での使われ方 メッセージ ・プライベート伝言 ・ネット注文 ・業務秘密 ・軍事機密 • メッセージへの攻撃 ◦ 盗聴(覗き見)

    ◦ 改ざん(書き換え) ◦ なりすまし • インターネットの仕組み上、メッセージへの 攻撃者は排除できない • メッセージを攻撃から守るために必ず暗号化 ◦ 盗聴対策 ◦ 暗号を基礎にした追加の工夫で 改ざんやなりすましへの対策にも • 利用箇所(一例) ◦ ブラウザ ◦ メッセージングアプリ ◦ SSH 攻撃者 ・盗聴 ・改ざん ・なりすまし 6 ?

  5. 共通鍵暗号 • メッセージの送信者と受信者が共通鍵を持つ ◦ 全く同じ鍵 • 共通鍵でメッセージを暗号化 & 復号 •

    共通鍵を持たない人には復号不可 • 利点: 暗号化・復号ともに高速 • 課題: 送信者と受信者の共通鍵の共有方法 ◦ "鍵共有問題" という 共通鍵 共通鍵 ?
 7
  6. 公開鍵暗号 • メッセージの受信者が公開鍵と秘密鍵 (キーペア)を生成 ◦ 公開鍵は誰に見られてもOK ◦ 秘密鍵は堅牢に保管 • 送信者は公開鍵で暗号化

    • 受信者は秘密鍵で復号 ◦ 受信者しか復号できない • 利点: 鍵共有問題を解消 • 課題: 共有鍵暗号に比べ一般に低速 ◦ 対策: 公開鍵暗号でメッセージの代わりに 共通鍵(またはその生成パラメータ)を 送るハイブリッド暗号も ▪ 例: TLS 公開鍵 配布 取得 秘密鍵 ?
 取得 8
  7. 公開鍵暗号の肝: 一方向性 • 秘密鍵から簡単に公開鍵を生成(演算)可能 • 公開鍵から秘密鍵の演算は困難 ◦ 総当りと同等程度の時間がかかる • 公開鍵暗号の肝:

    逆演算が困難な一方向関数 ◦ 素因数分解 → RSA ◦ 離散対数 → DH鍵共有, ElGamal暗号 ◦ 楕円曲線上の離散対数 → ECDH 公開鍵 秘密鍵 生成 公開鍵から秘密鍵を求める → 逆関数 逆関数計算が困難 → 一方向性 9
  8. RSA暗号の肝: 素因数分解 • 大きな素数(1と自分自身以外で割切れない整数)を 2つ生成する • 2つの素数の積を計算する •   だけが与えられたとき、その素因数の

       を見つける(素因数分解)のは困難 公開鍵 秘密鍵    が大きな素数の場合、   から   への素因数分解は困難 *2 RSAの秘密鍵は実際にはp,qそのものではない 安全と言われる(*1) 鍵長2048bitのRSAの 素数の例(309桁) *2 *1 セキュリティ強度112bit以上   NIST SP 800-57 Part1 Rev5 より p = 1661464038506986952099361779855268263814773487503791549443600158770427 0319586827671110953027645954703667361431276992974958887661489175016657 2672158872213491194579280089280509906561078869636285271075103776065582 3132547766217190926639146623688857163554673344174039259892616065771945 12953191187536339960058260679 q = 1376257090728843514204691749056904293778621379524071694185875920681016 9853844137979100017058947472788487507719198722612525190095124199145237 6255761392414044799886029228512816190759923027562523382193252254157059 9748084476671083617373238578000370044426026227265828929399502743171506 78591340699591024090624980817 10
  9. RSA暗号概観 1. メッセージの受信者が素数   を生成 2. 受信者が   を元に秘密鍵を生成 ◦ 受信者の秘密にする 3. 受信者が公開鍵     を計算し配布 4.

    送信者が  を取得 ◦ 送信者は   を知らない 5. 送信者は公開鍵を使ってメッセージを暗号化 6. 受信者は秘密鍵を使ってメッセージを復号 公開鍵 取得 秘密鍵 配布 *1 RSAの秘密鍵は実際にはp,qそのものではない *1 11
  10. RSAの数式を眺める 1. 素数   を生成 2.      を計算 3.           を計算 ファイ

    4.   と互いに素 (共通素因数なし) な   を選ぶ ◦            をよく使う 5.          を計算し、秘密鍵とする 6.    を公開鍵とする 鍵生成 公開鍵 秘密鍵 平文 暗号文 暗号化 (平文  → 暗号文  ) 復号 (暗号文  → 平文  ) 現時点で完全理解 できなくてOK 13
  11. RSAの数式を要素分解 1. 素数   を生成 2.      を計算 3.           を計算 ファイ

    4.   と互いに素 (共通素因数なし) な   を選ぶ ◦            をよく使う 5.          を計算し、秘密鍵とする 6.    を公開鍵とする 鍵生成 公開鍵 秘密鍵 平文 暗号文 暗号化 (平文  → 暗号文  ) 復号 (暗号文  → 平文  ) 小さすぎても大きすぎても弱くなる   のモジュラ逆数(法  ) 平文文字列を整数に変換、 乗、 法  での剰余を求める 暗号文を  乗、法  での剰余を 求め、文字列に変換 文字列↔整数・剰余・モジュラ逆数 を次ページから詳説 オイラーの  関数    を知らないと計算できない 14
  12. 文字列↔整数 変換 (ASCIIで解説) 1. 文字列を1文字ずつ整数にASCIIエンコード ◦ 'a' : 97 ,

    'b' : 98 , 'c' : 99 2. 各ASCIIコードを、256     を 重みとして足し合わせる ◦ 97 * 256^2 + 98 * 256^1+ 99 * 256^0 = 6382179 右から何文字目 文字列 'abc' → 整数 1. 整数を256     で割り、法256での余り を求める ◦ 0文字目: (6382179 / 256^0) % 256 = 99 ◦ 1文字目: (6382179 / 256^1) % 256 = 98 ◦ 2文字目: (6382179 / 256^2) % 256 = 97 2. 各整数をASCIIデコード → 'abc' 整数 6382179 → 文字列 右から何文字目 >>> ord('a') 97 >>> ord('b') 98 >>> ord('c') 99 >>> ord('a') * (256**2) + \ ... ord('b') * (256**1) + \ ... ord('c') * (256**0) 6382179 >>> from Crypto.Util.number import * >>> bytes_to_long(b'abc') 6382179 >>> long_to_bytes(6382179) b'abc' python インタプリタで実行しよう↓ 15
  13. 剰余 >>> 8 % 3 # 8の法3での剰余 2 >>> 64

    % 3 # 64の法3での剰余 1 >>> pow(8, 1, 3) # 8^1 % 3 2 >>> pow(8, 2, 3) # 8^2 % 3 1 python インタプリタで実行しよう↓ • 「aの法bでの剰余」=「aをbで割った余り」 ◦ モジュロ演算などとも呼ぶ • 高速に求める種々のアルゴリズムあり ◦ ユークリッドの互除法など • 本講義ではPythonの % か pow() 関数でOK 16
  14. モジュラ逆数 >>> pow(14, -1, 3) # 14^-1 (mod 3) 2

    python インタプリタで実行しよう↓ • 「aの法bでのモジュラ逆数」 =「       」 =「       を満たすような  」 • 14の法3でのモジュラ逆数 ◦ 14 * 2 = 28 = 3 * 9 + 1 により、2 • モジュラ逆数は無限個あるが、最小の正整数を使うことが多い ◦ 14の法3でのモジュラ逆数は 2 + 3k • 本講義ではPythonの pow() 関数でOK 17
  15. RSAの数式を要素分解(再掲) 1. 素数   を生成 2.      を計算 3.           を計算 ファイ

    4.   と互いに素 (共通素因数なし) な   を選ぶ ◦            をよく使う 5.          を計算し、秘密鍵とする 6.    を公開鍵とする 鍵生成 公開鍵 秘密鍵 平文 暗号文 暗号化 (平文  → 暗号文  ) 復号 (暗号文  → 平文  ) オイラーの  関数    を知らないと計算できない 小さすぎても大きすぎても弱くなる   のモジュラ逆数(法  ) 平文文字列を整数に変換、 乗、 法  での剰余を求める 暗号文を  乗、法  での剰余を 求め、文字列に変換 わからないことがなくなったはず! 18
  16. RSAの暗号化を実装 暗号化 (平文  → 暗号文  ) 前提 • 自分はメッセージ送信者だと思って良い • 平文 

    は自分の好きなメッセージ文字列を 整数変換したもの • 公開鍵    は既知 (メッセージ受信者指定) 問題: 暗号化せよ • m = 6382179 • N = 61037359 • e = 5 m = 6382179 N = 61037359 e = 5 c = pow(m, e, N) # m^e (mod N) print(f'c = {c}') python で実行しよう↓ $ python enc.py c = 53668997 20
  17. RSAの復号を実装 前提 • 自分はメッセージ受信者だと思って良い • 素数   は既知(生成済み) • 公開鍵のひとつ  は既知(選択済み)

    • 暗号文  は既知(受信済み) 問題: 復号せよ • c = 53668997 • p = 787 • q = 77557 • e = 5 c = 53668997 p = 787 q = 77557 e = 5 N = p * q phi = (p - 1) * (q - 1) d = pow(e, -1, phi) # e^-1 (mod phi) m = pow(c, d, N) # c^d (mod N) print(f"m = {m}") # 前ページの平文 # 平文をデコード from Crypto.Util.number import * m_str = long_to_bytes(m) print(f"m_str = {m_str}") python で実行しよう↓ $ python dec.py m = 6382179 m_str = b'abc' 復号 (暗号文  → 平文  ) 前ページの N = 61037359 の素因数分解 前ページの暗号化結果 21
  18. RSAの解読戦略 公開鍵 秘密鍵 平文 暗号文 • (a) 素数   を突き止める ◦

     →  →  の順に平文にたどり着く • (b)    を介さず直接  を突き止める ◦ 暗号化の式を転用することがある 秘密鍵が分かればその後全ての 暗号文を短時間で復号できる (b) は特定の平文の暗号文のみ解読 ∴ (a) は「強い」解読 本演習やCTFでは (a)(b) に優劣なし 23
  19. • Kintoneで演習問題含むPDFを送信してもらったはずなのでお手元にDL • 暗号文とその他必要な情報を与える。平文に復号せよ ◦ 平文は rsa{hankaku_eiji} の形式の文字列(数値→文字列 変換が必要) •

    復号結果と、その求め方をPythonコードまたは文章で提出せよ ◦ 当日のみ解答フォームあり • 各問題で配点は異なる。合計得点が最も高い人が優勝 ◦ 優勝者には... 特に何も... 本人が良ければ講義の最後にみんなで拍手👏 • ヒントを3回に分けてKintoneで公開 & 講師が説明 ◦ ヒント発表前後での得点差なし • Google検索やオンラインツール (LLM以外) 利用OK。カンニングなどは禁止 ◦ ChatGPTやClaude使うのは教育効果が損なわれるのでなし ◦ 講師・チューターへの質問応答: ▪ [NG] 解法に繋がる質問応答「考え方がわからないから教えて」 ▪ [OK] 各自考えた解法のサポート「こういう考えだけどここが動かない...」 RSA解読演習: ルール 24
  20. RSA解読演習: お品書き # タイトル 配点 ヒント時刻目安 作問者 1 小さいN見つけた 10

    11:55 laysakura (講師) 2 1でeの? 10 12:10 laysakura (講師) 3 でっかe 30 12:25 laysakura (講師) 4 ちっちゃe 40 12:25 laysakura (講師) 5 使い回し 50 12:25 laysakura (講師) 6 2つのe 50 12:25 hiikunZ 7 6つの素数 50 12:25 うしがぃ 慣れてる人でも時間的に全問解くのは難しい。解けそう・面白そうな問題から 取り組んでください。 初挑戦は解けなくても当たり前。一生懸命考える経験を持って帰ってください。 25
  21. #2 1でeの? (10点) 問題: 復号せよ • c = 10962199806997852621849592264890411439467769672834706813 •

    N = 9354989215068158144043140201182704736159947394157330700447282783241788585482102156255293917437554835381114716778 5844819790395407225817235426413294207470454583232796302469349068346152820921191513267542584628588614810778342591 674538229518195823357632385246395692767294668921897962854736600178473173740528805639 • e = 1 27
  22. #3 でっかe (30点) 問題: 復号せよ • c = 1515785339205680498815120832318976648885580424765758034212650602297341644777790730736584138054292389283319771911 9097634064973376032217882138963039208514221664879711928014737326358427573831824184127997433115186943671756541693

    945599008905490060073050979050273252022306488808550742574789688036675577537206647700 • N = 1323460161262448382377878455555645851979218529931227133697876363408749003913675998537448946854825772328225120718 9125252625993849782551758355647699021032745226518626512645463160428380642165710714817966803586878633287115789243 5863717093016311015942899979834193496478515665409163431674034521084813260265519877527 • e = 7792993772075807263019665575193826851606311143987083001744759783292554482199069197028614078665102291393601902409 2488843436290830317206755983043534055390943885278627283556746214168360102775696185638214747450830241140575216884 51294871264292124507585425826052506377518895500700998383416258681913315855249353737 28
  23. #4 ちっちゃe (40点) 問題: 復号せよ • c = 5330771718594563231935137401530046955438217958208649161138916935712595446531235678512856192847291650112630087121 4119774896652148147706314116488502295077989149092966501357909776225091518942549051634943577111139950003269349470

    731079127788078104797580254455400193616106658993971704377611189507947103649247229584 • N = 9900125982750383321313457773382502108359409207027265305966196792881597756518593532237892202817849486228937210085 6435200787207536366445399722133897433684496732960789310518848859502885933475471842001744544995888275871747404666 508451688056124064493381659642475078198315894882290460124015791475489317063448792013 • e = 3 29
  24. #5 使い回し (50点) 問題: 以下条件を加味し、 復号せよ。  ある暗号鍵生成ツールは、素数を使い回すことで鍵生成を高速化している。  N, N2も共通の素因数を1つ含む。cの計算にはNが使われている。 •

    c = 1027542887057244087253608365200320098964204225884550474254711010256168509181409943577429888055967050997568859979 5436196237653442231902453260757860781093653810582161049120922698445887315563551211175567343978823251613480186590 1017816758709227156687447167868718753667900825602205482929255939324490916849360498616 • N = 1277619536743854959972339969832780657096134638337935530935682669396975343256083379844175011903124112756820526418 8145182311623387150315660556014579835183665206213059029454753736360050255024077812237949729150420598723783972151 4645447858975537658193230645297528005686403003344592258885350623570778844459951568421 • N2 = 1488964899702443620878534133593807975905947365674350453385205128060491973809317992144040341292721127648839029351 4349256788248269275817927171896058393732113541210973176134649054821945176040204003351131869341934172487841264313 4353557778020489589566578038269851120161616625628821668234516232241051979579009711717 • e = 65537 30
  25. #6 2つのe (50点) 問題: 以下条件を加味し、 復号せよ。  同じ平文 m を、e を変更することで

    2 通り暗号化した。(N は変更していない)  公開鍵 (N,e1) で暗号化したものが c1, (N,e2) で暗号化したものが c2 である。 • c1 = 54103849731276644553897625696883416142142785563704650352703466794904628774315806138784110971831383339966143 18057359739026911372807224511089052509673337455187686550756409185188728505919670503148900475955778282230449 7074690869013068065413448468042440600150981015073295194258492646636683594715185368993356495323 • c2 = 62286886668680173653006564133133957869744785885218598234221009427469198985814772758363045639657237311359598 62116312497928769195837128121144580491706490444996158635118636385201317561782281563333960390932093606889973 5071581416575215930334352402146101245167989269615540348616605481867521786031107798407252972491 • N = 80218529762736927076986567666842969824220507216466338638914312954310282724379714202935637580665785463497028 82927509179699008212459475416953185328168027130627233666680209740505273169869099318039416327433714974898198 8941210972478567306838753416740087919453967409903541856213135033335306208125483526642728616757 • e1 = 65537 • e2 = 65539 31
  26. • p = 14464334816788210139 • q = 15769416010044301523 • r

    = 16419082908446791451 • s = 14138761265659705979 • t = 16419082908446791451 • u = 10542742753391853391 • N = p*q*r*s*t*u • e = 65537 • c = 27855384830324599562584907323152613811364291530943190516610809171419795591 02399773560510571346904537677487131456452 #7 6つの素数 (50点) 問題: 素数 p, q, r, s, t, uの積をNとして暗号化した。平文を復号せよ。 32
  27. 常設CTF, CryptoHack • 先程の演習みたいなのが好きだったら是非 • 常設CTF: いつでもやってるCTF ◦ 暗号以外の分野の問題もある ◦

    おすすめ: picoCTF, AlpacaHack • CryptoHack ◦ ジャンルではなくサイトそのもの ◦ 暗号専用の常設CTFの趣 ◦ CTFでは扱われづらい暗号アルゴリズム もカバー • まず picoCTF のCryptography(暗号) カテゴリから始めて、暗号大好きだったら CryptoHackやるとよさそう 34
  28. 暗号分野の書籍 • 講師が読んだことあるものの中でのオススメ ◦ この他も良い本もあるはず • 1冊目に『暗号と認証のしくみと理論が     これ1冊でしっかりわかる教科書』 ◦ 共通鍵暗号・公開鍵暗号・ハッシュ・

    署名・乱数など、「暗号」でカバーされる 分野の事項が幅広くわかりやすく解説 ◦ 数学はほぼない • 暗号分野を深める『暗号の理論と技術』 ◦ 耐量子暗号や形式手法による安全性検証 など、先進的な話題が魅力 ◦ 数学は結構ある • 数学的基礎づくり『はじめての数論 第4版』 ◦ 暗号の深い理解に整数論は欠かせない ◦ 平易な文章で群論や楕円曲線もカバー 35
  29. RSAと耐量子暗号 • 量子コンピューターが実現すると、RSA暗号は解読される ◦ Shorのアルゴリズム: 量子コンピューターで素因数分解が高速にできる → 公開鍵から秘密鍵が計算できる • 量子コンピューターに対抗できる暗号技術

    ◦ PQC: Post-Quantum Cryptography ◦ 格子暗号, 符号ベース暗号, ハッシュベース暗号など • どれもRSAよりも高度な数学が要求されますが、(もしも)数学が苦手でも 「勉強した先にこんなに実用的なものがあるのか」と考えるキッカケになると 思います 37
  30. [ヒント] #1 小さいN見つけた 問題: 復号せよ • c = 15516472635516552190199 •

    N = 17743946952907110741731 • e = 65537 ヒント1 Nが小さいとき、p, qへ素因数分解できるかも ヒント2 素因数分解できるサイトやコードを探す ヒント3 http://factordb.com/ 40
  31. [ヒント] #2 1でeの? 問題: 復号せよ • c = 10962199806997852621849592264890411439467769672834706813 •

    N = 935498921506815814404314020118270473615994739415733070044728278324178858548210215625529391743755483538111 471677858448197903954072258172354264132942074704545832327963024693490683461528209211915132675425846285886 14810778342591674538229518195823357632385246395692767294668921897962854736600178473173740528805639 • e = 1 ヒント1 Nは大きくp, qは求められなさそう ヒント2 暗号化の式を睨む ヒント3 e=1 を代入すると...? 41
  32. [ヒント] #3 でっかe 問題: 復号せよ • c = 151578533920568049881512083231897664888558042476575803421265060229734164477779073073658413805429238928331977191190976340649733760322 178821389630392085142216648797119280147373263584275738318241841279974331151869436717565416939455990089054900600730509790502732520223

    06488808550742574789688036675577537206647700 • N = 1323460161262448382377878455555645851979218529931227133697876363408749003913675998537448946854825772328225120718912525262599384978255175835564769 9021032745226518626512645463160428380642165710714817966803586878633287115789243586371709301631101594289997983419349647851566540916343167403452108 4813260265519877527 • e = 7792993772075807263019665575193826851606311143987083001744759783292554482199069197028614078665102291393601902409248884343629083031720675598304353405539094388527 862728355674621416836010277569618563821474745083024114057521688451294871264292124507585425826052506377518895500700998383416258681913315855249353737 ヒント1 eは大きすぎても脆弱 ヒント2 "rsa e 大きい 脆弱" ヒント3 有名解読手法: Wiener's Attack ヒント4 有名な解読手法はコード書かずとも オンラインソルバーがあるかも 42
  33. [ヒント] #4 ちっちゃe 問題: 復号せよ • c = 5330771718594563231935137401530046955438217958208649161138916935712595446531235678512856192847291650112630087121 4119774896652148147706314116488502295077989149092966501357909776225091518942549051634943577111139950003269349470

    731079127788078104797580254455400193616106658993971704377611189507947103649247229584 • N = 9900125982750383321313457773382502108359409207027265305966196792881597756518593532237892202817849486228937210085 6435200787207536366445399722133897433684496732960789310518848859502885933475471842001744544995888275871747404666 508451688056124064493381659642475078198315894882290460124015791475489317063448792013 • e = 3 ヒント1 eは小さすぎても脆弱 ヒント2 暗号化の式を睨む ヒント3 cのe乗根 (3乗根) が m ? ヒント4 合同式のままだと3乗根を取れないので、 整数変数を使った等式を作る。 整数変数は総当たり探索で本問は解ける。 43
  34. [ヒント] #5 使い回し 問題: 以下条件を加味し、 復号せよ。  ある暗号鍵生成ツールは、素数を使い回すことで鍵生成を高速化している。  N, N2も共通の素因数を1つ含む。cの計算にはNが使われている。 •

    c = 1027542887057244087253608365200320098964204225884550474254711010256168509181409943577429888055967050997568859979543619623765344223190245326075786078 1093653810582161049120922698445887315563551211175567343978823251613480186590101781675870922715668744716786871875366790082560220548292925593932449091 6849360498616 • N = 1277619536743854959972339969832780657096134638337935530935682669396975343256083379844175011903124112756820526418814518231162338715031566055601457983 5183665206213059029454753736360050255024077812237949729150420598723783972151464544785897553765819323064529752800568640300334459225888535062357077884 4459951568421 • N2 = 1488964899702443620878534133593807975905947365674350453385205128060491973809317992144040341292721127648839029351434925678824826927581792717189605839 3732113541210973176134649054821945176040204003351131869341934172487841264313435355777802048958956657803826985112016161662562882166823451623224105197 9579009711717 • e = 65537 ヒント1 NとN2の共通素因数をpとすると、q = N/p ヒント2 NとN2の共通素因数はどう求める? ヒント3 GCD 44
  35. [ヒント] #6 2つのe (50点) 問題: 以下条件を加味し、 復号せよ。  同じ平文 m を、e

    を変更することで 2 通り暗号化した。(N は変更していない)  公開鍵 (N,e1) で暗号化したものが c1, (N,e2) で暗号化したものが c2 である。 ヒント1 暗号化の式を睨む ヒント2 c1 と c2 から何かを求められないか…? ヒント3 ヒント4 モジュラ逆数を使うと、 45 • c1 = 54103849731276644553897625696883416142142785563704650352703466794904628774315806138784110971831383339966143180573597390269113728072245110890525096733374551876865507564091851887 285059196705031489004759557782822304497074690869013068065413448468042440600150981015073295194258492646636683594715185368993356495323 • c2 = 62286886668680173653006564133133957869744785885218598234221009427469198985814772758363045639657237311359598621163124979287691958371281211445804917064904449961586351186363852013 175617822815633339603909320936068899735071581416575215930334352402146101245167989269615540348616605481867521786031107798407252972491 • N = 80218529762736927076986567666842969824220507216466338638914312954310282724379714202935637580665785463497028829275091796990082124594754169531853281680271306272336666802097405052 731698690993180394163274337149748981988941210972478567306838753416740087919453967409903541856213135033335306208125483526642728616757 • e1 = 65537 • e2 = 65539
  36. [ヒント] #7 6つの素数 (50点) ヒント1 公開鍵Nの素因数が3つ以上のRSA暗号を Multi-Prime RSAと呼ぶらしい ヒント2 例えばN=p*q*rのMulti-Prime

    RSAの場合、 Φ=(p-1)*(q-1)*(r-1)で、N=p*q*r*sの場合 はΦ=(p-1)*(q-1)*(r-1)*(s-1)で秘密鍵を計 算すればよい ヒント3 与えられた6つの素数のうち、rとtは同じ値 である。ところで、Φの定義は「Nと互いに 素な1以上N以下の自然数の個数」である。 ヒント4 N=p*pの場合Φの定義を考えるとΦ=p*(p-1) となることを確かめてほしい。 では、N=p*q*r*s*t*uでrとtが等しい場合は どうなるか。 46
  37. [解答] #1 小さいN見つけた 問題: 復号せよ • c = 15516472635516552190199 •

    N = 17743946952907110741731 • e = 65537 c = 15516472635516552190199 N = 17743946952907110741731 e = 65537 # factordb.com などでNを素因数分解 p = 997 q = 17797338969816560423 # 秘密鍵を求める phi = (p - 1) * (q - 1) d = pow(e, -1, phi) # 復号 m = pow(c, d, N) # デコード from Crypto.Util.number import long_to_bytes m_str = long_to_bytes(m) print(m_str) 平文: rsa{V_V} 48
  38. [解答] #2 1でeの? 問題: 復号せよ • c = 10962199806997852621849592264890411439467769672834 706813

    • N = 93549892150681581440431402011827047361599473941573 30700447282783241788585482102156255293917437554835 38111471677858448197903954072258172354264132942074 70454583232796302469349068346152820921191513267542 58462858861481077834259167453822951819582335763238 52463956927672946689218979628547366001784731737405 28805639 • e = 1 from Crypto.Util.number import long_to_bytes c = 10962199806997852621849592264890411439467769672834706813 # Nは不要 e = 1 # 暗号化の式: c ≡ m^e (mod N) # e = 1 なので、c ≡ m (mod N) # c が Nよりもかなり小さく、余りではなく # c = m の可能性が高い(実際合ってる) m = c m_str = long_to_bytes(m) print(m_str) 平文: rsa{e_is_1_then_c_is_m} 49
  39. [解答] #3 でっかe 問題: 復号せよ • c = 1515785339205680498815120832318976648885580424765758034 2126506022973416447777907307365841380542923892833197719

    1190976340649733760322178821389630392085142216648797119 2801473732635842757383182418412799743311518694367175654 1693945599008905490060073050979050273252022306488808550 742574789688036675577537206647700 • N = 1323460161262448382377878455555645851979218529931227133697876 3634087490039136759985374489468548257723282251207189125252625 9938497825517583556476990210327452265186265126454631604283806 4216571071481796680358687863328711578924358637170930163110159 4289997983419349647851566540916343167403452108481326026551987 7527 • e = 7792993772075807263019665575193826851606311143987083001744759783292 5544821990691970286140786651022913936019024092488843436290830317206 7559830435340553909438852786272835567462141683601027756961856382147 4745083024114057521688451294871264292124507585425826052506377518895 500700998383416258681913315855249353737 https://www.dcode.fr/rsa-cipher Wiener's Attackできるオンラインツール 他ツールやコードでWiener's AttackしてもOK 平文: rsa{Wiener_Attack} 50
  40. [解答] #4 ちっちゃe 問題: 復号せよ • c = 5330771718594563231935137401530046955438217958208649 1611389169357125954465312356785128561928472916501126

    3008712141197748966521481477063141164885022950779891 4909296650135790977622509151894254905163494357711113 9950003269349470731079127788078104797580254455400193 616106658993971704377611189507947103649247229584 • N = 9900125982750383321313457773382502108359409207027265 3059661967928815977565185935322378922028178494862289 3721008564352007872075363664453997221338974336844967 3296078931051884885950288593347547184200174454499588 8275871747404666508451688056124064493381659642475078 198315894882290460124015791475489317063448792013 • e = 3 平文: rsa{mod_cubic_root_abcdefghijklmnopqrstuvw} from Crypto.Util.number import long_to_bytes import gmpy2 c = 5330771718594563231935137401530046955438217958208649161138916935712595446531235678512 8561928472916501126300871214119774896652148147706314116488502295077989149092966501357 9097762250915189425490516349435771111399500032693494707310791277880781047975802544554 00193616106658993971704377611189507947103649247229584 N = 9900125982750383321313457773382502108359409207027265305966196792881597756518593532237 8922028178494862289372100856435200787207536366445399722133897433684496732960789310518 8488595028859334754718420017445449958882758717474046665084516880561240644933816596424 75078198315894882290460124015791475489317063448792013 e = 3 # 暗号化の式: c = m^e (mod N) より、 # c = m^e + kN を満たす整数 k が存在。 # m = (c - kN)^(1/e) (e乗根)が整数になる k を探索。 def decrypt_iroot_e(c, n, e): for k in range(-1000, 1000): c_kn = c - k * n if c_kn < 0: continue m, exact = gmpy2.iroot(c_kn, e) if exact: # m が整数 return m m = decrypt_iroot_e(c, N, e) m_str = long_to_bytes(m) print(m_str) 51
  41. [解答] #5 使い回し 問題: 以下条件を加味し、 復号せよ。  ある暗号鍵生成ツールは、素数を使い回すことで  鍵生成を高速化している。  N, N2も共通の素因数を1つ含む。

     cの計算にはNが使われている。 • c = 102754288705724408725360836520032009896420422588455047425471101 025616850918140994357742988805596705099756885997954361962376534 422319024532607578607810936538105821610491209226984458873155635 512111755673439788232516134801865901017816758709227156687447167 868718753667900825602205482929255939324490916849360498616 • N = 127761953674385495997233996983278065709613463833793553093568266 939697534325608337984417501190312411275682052641881451823116233 871503156605560145798351836652062130590294547537363600502550240 778122379497291504205987237839721514645447858975537658193230645 297528005686403003344592258885350623570778844459951568421 • N2 = 148896489970244362087853413359380797590594736567435045338520512 806049197380931799214404034129272112764883902935143492567882482 692758179271718960583937321135412109731761346490548219451760402 040033511318693419341724878412643134353557778020489589566578038 269851120161616625628821668234516232241051979579009711717 • e = 65537 from math import gcd from Crypto.Util.number import long_to_bytes c = 1027542887057244087253608365200320098964204225884550474254711010256168509181409943577 4298880559670509975688599795436196237653442231902453260757860781093653810582161049120 9226984458873155635512111755673439788232516134801865901017816758709227156687447167868 718753667900825602205482929255939324490916849360498616 N = 1277619536743854959972339969832780657096134638337935530935682669396975343256083379844 1750119031241127568205264188145182311623387150315660556014579835183665206213059029454 7537363600502550240778122379497291504205987237839721514645447858975537658193230645297 528005686403003344592258885350623570778844459951568421 N2 = 1488964899702443620878534133593807975905947365674350453385205128060491973809317992144 0403412927211276488390293514349256788248269275817927171896058393732113541210973176134 6490548219451760402040033511318693419341724878412643134353557778020489589566578038269 851120161616625628821668234516232241051979579009711717 e = 65537 # N, N2の共通素因数: GCD (最大公約数) # これはユークリッドの互除法などで高速に求められる p = gcd(N, N2) q = N // p phi = (p - 1) * (q - 1) d = pow(e, -1, phi) m = pow(c, d, N) m_str = long_to_bytes(m) print(m_str) 平文: rsa{gcd_so_fast} 52
  42. [解答] #6 2つのe (50点) 問題: 以下条件を加味し、 復号せよ。  同じ平文 m を、e

    を変更することで 2 通り暗号化した。  (N は変更していない)  公開鍵 (N,e1) で暗号化したものが c1,  (N,e2) で暗号化したものが c2 である。 • c1 = 54103849731276644553897625696883416142142785563704650352703466794904628774315 80613878411097183138333996614318057359739026911372807224511089052509673337455 18768655075640918518872850591967050314890047595577828223044970746908690130680 65413448468042440600150981015073295194258492646636683594715185368993356495323 • c2 = 62286886668680173653006564133133957869744785885218598234221009427469198985814 77275836304563965723731135959862116312497928769195837128121144580491706490444 99615863511863638520131756178228156333396039093209360688997350715814165752159 30334352402146101245167989269615540348616605481867521786031107798407252972491 • N = 80218529762736927076986567666842969824220507216466338638914312954310282724379 71420293563758066578546349702882927509179699008212459475416953185328168027130 62723366668020974050527316986909931803941632743371497489819889412109724785673 06838753416740087919453967409903541856213135033335306208125483526642728616757 • e1 = 65537 • e2 = 65539 from Crypto.Util.number import long_to_bytes import gmpy2 c1 = 54103849731276644553897625696883416142142785563704650352703466794904628774315806138784 11097183138333996614318057359739026911372807224511089052509673337455187686550756409185 18872850591967050314890047595577828223044970746908690130680654134484680424406001509810 15073295194258492646636683594715185368993356495323 c2 = 62286886668680173653006564133133957869744785885218598234221009427469198985814772758363 04563965723731135959862116312497928769195837128121144580491706490444996158635118636385 20131756178228156333396039093209360688997350715814165752159303343524021461012451679892 69615540348616605481867521786031107798407252972491 N = 80218529762736927076986567666842969824220507216466338638914312954310282724379714202935 63758066578546349702882927509179699008212459475416953185328168027130627233666680209740 50527316986909931803941632743371497489819889412109724785673068387534167400879194539674 09903541856213135033335306208125483526642728616757 e1 = 65537 e2 = 65539 c1_inv = pow(c1, -1, N) # c1 の(mod N での)モジュラ逆数 m2 = (c2 * c1_inv) % N # c2/c1 = c2*(c1^-1) = m^2 (mod N) m, exact = gmpy2.iroot(m2, 2) # m^2 の平方根を取る assert(exact) # m^2 の平方根が存在するかチェック m_str = long_to_bytes(m) print(m_str) 平文: rsa{65537_and_65539_are_twin_primes} 53
  43. [解答] #7 6つの素数 (50点) 問題: 素数p,q,r,s,t,uの積をNとして暗号化した。 平文を復号せよ。 from Crypto.Util.number import

    * N = 916593639845747488972140759153098740345890250466970098886308987698 2301623127561014158785961307853313187221280505133 e = 65537 c = 278553848303245995625849073231526138113642915309431905166108091714 1979559102399773560510571346904537677487131456452 p = 14464334816788210139 q = 15769416010044301523 r = 16419082908446791451 s = 14138761265659705979 t = 16419082908446791451 u = 10542742753391853391 phi = (p - 1)*(q - 1)*(r - 1)*(s - 1)*t*(u - 1) d = inverse(e, phi) flag = pow(c, d, N) print(long_to_bytes(flag)) 平文: rsa{MakeSureYouUnderstandTheTheorems!!!} 54 • p = 14464334816788210139 • q = 15769416010044301523 • r = 16419082908446791451 • s = 14138761265659705979 • t = 16419082908446791451 • u = 10542742753391853391 与えられた素数を見るとrとtが等しいことが わかる。Φの定義はNと互いに素な1以上N以 下の自然数なので Φ=(p-1)*(q-1)*(r-1)*(s-1)*t*(u-1)となる。 あとは通常通りの計算で復号すればよい。