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

Crypto超入門 / SECCON Beginners Live 2022

ushigai
September 11, 2022
1.5k

Crypto超入門 / SECCON Beginners Live 2022

ushigai

September 11, 2022
Tweet

Transcript

  1. どのような問題が出るのか 文字コード変換 2018: Veni, vidi, vici 2020: R&B AES 2020:

    Encrypter 2021: Imaginary 2022: command ElGamal 2018: Well Known 乱数 2022: unpredictable_pad 格子 2021: Field_trip そのた 2019: Party 2020: Noisy equations 2021: Logical_SEESAW 2021: GFM 2022: CoughingFox Crypto超入門 6
  2. RSA 2018: RSA is Power 2019: Go RSA 2020: RSA

    Calc 2021: simple_RSA 2021: p-8RSA 2022: PrimeParty 2022: omni-RSA どのような問題が出るのか Crypto超入門 7
  3. 前提知識 (3/4) オイラーのトーシェント関数 任意の自然数 について と互いに素な 以下の自然数の個数を とおく。 が素数の場合 e.g.

    が異なる素数 からなる合成数の場合 e.g. n n n φ(n) n φ(n) = n − 1 n = 7 ⇒ φ(n) = 6 n p, q φ(n) = (p − 1)(q − 1) n = 15 ⇒ φ(n) = 8 Crypto超入門 13
  4. RSA暗号の暗号化と復号の定義 鍵生成: 素数 と (一般に )を決定し とおき、 とおく。(ただし とする) このとき公開鍵の組を

    ,秘密鍵を とする。 p, q e e = 65537 n = pq d = e−1 mod φ(n) gcd(φ(n), e) = 1 (e, n) d 暗号化: 任意の平文 について暗号文 は となる。 m c c = me mod n 復号: 平文 は と復号できる。 m m = cd mod n Crypto超入門 15
  5. RSA暗号の具体的な計算例 暗号化 pow(32, 3, 55) -> 43 復号 pow(43, 27,

    55) -> 32 m = 32 c = me mod n c = 323 mod 55 m = cd mod n m = 4327 mod 55 Crypto超入門 17
  6. from Crypto.Util.number import * p, q = getPrime(512), getPrime(512) #

    素数生成 n = p * q # 公開鍵生成 e = 65537 message = bytes_to_long(b"Hello world!!!") cipher = pow(message, e, n) # 暗号化 c=m^e mod n phi = (p - 1)*(q - 1) d = inverse(e, phi) # 秘密鍵生成 d=e^-1 mod φ(n) message = pow(cipher, d, n) # 復号 m=c^d mod n RSAの実装 Crypto超入門 19
  7. from Crypto.Util.number import * p, q = getPrime(64), getPrime(64) #

    64bitの素数を生成 n = p*q e = 65537 message = bytes_to_long(b"Hello world!!!") cipher = pow(message, e, n) print("n =", n) print("e =", e) print("cipher =", cipher) # n = 176758646138734597782135865714590884773 # e = 65537 # cipher = 84184983095913927892595433377236235254 実際にやってみる Crypto超入門 24
  8. from Crypto.Util.number import * n = 176758646138734597782135865714590884773 e = 65537

    cipher = 84184983095913927892595433377236235254 p = 11654023597864701997 q = 15167177640786744409 phi = (p - 1)*(q - 1) d = inverse(e, phi) message = pow(cipher, d, n) message = long_to_bytes(message) print(message) 実際にやってみる Crypto超入門 25
  9. 素数を使いまわしている場合 from Crypto.Util.number import * p1, q1 = getPrime(512), getPrime(512)

    p2, q2 = getPrime(512), q1 n1 = p1*q1 n2 = p2*q2 e = 65537 dummy_message = bytes_to_long(b"dumdumdummy!!!") dummy_cipher = pow(dummy_message, e, n2) message = bytes_to_long(b"FLAG{****}") cipher = pow(message, e, n1) print("n1 =", n1) print("n2 =", n2) print("e =", e) print("cipher =", cipher) ​ ​ { n ​ = p ​ q ​ 1 1 1 n ​ = p ​ q ​ 2 2 2 ここで とすると、 ​ { n ​ = p ​ Q 1 1 n ​ = p ​ Q 2 2 ⇒ Q = GCD(n ​ , n ​ ) 1 2 Q = q ​ = 1 q ​ 2 Crypto超入門 26
  10. from Crypto.Util.number import * n1 = <<snip>> n2 = <<snip>>

    e = 65537 cipher = <<snip>> Q = q1 = GCD(n1, n2) p1 = n1 // q1 phi = (p1 - 1)*(q1 - 1) d = inverse(e, phi) message = pow(cipher, d, n1) message = long_to_bytes(message) print(message) 素数を使いまわしている場合 Crypto超入門 27
  11. 方程式を解き素因数分解できる場合 from Crypto.Util.number import * p, q = getPrime(512), getPrime(512)

    n = p*q r = p + q e = 65537 message = bytes_to_long(b"FLAG{****}") cipher = pow(message, e, n) print("n =", n) print("e =", e) print("cipher =", cipher) print("r =", r) ​ { n = p ∗ q r = p + q ⇔ ​ ​ { n = p ∗ q p = r − q ⇒ n = −q + 2 rq ⇔ q − 2 rq + n = 0 の二次方程式なので が計算 できる q q Crypto超入門 28
  12. 方程式を解き素因数分解できる場合 from Crypto.Util.number import * from gmpy2 import iroot n

    = <<snip>> e = 65537 cipher = <<snip>> r = <<snip>> a, b, c = 1, -r, n X = iroot(b*b - 4*a*c, 2)[0] q = (-b + X) // 2*a p = n // q d = inverse(e, (p - 1)*(q - 1)) message = pow(cipher, d, n) message = long_to_bytes(message) print(message) q − 2 rq + n = 0 q = ​ 2 r + ​ r − 4n 2 Crypto超入門 29
  13. おすすめ記事 RSA暗号運用でやってはいけないnのこと #ssmjp Twenty Years of Attaks on the RSA

    Cryptosystem おすすめVTuber kurenaif 【RSA入門】【初心者と一緒に学ぶ】CTFのCrypto超入門【kurenaif】 おすすめ紹介 Crypto超入門 32