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

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

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

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

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

Avatar for Sho Nakatani

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)となる。 あとは通常通りの計算で復号すればよい。