pikesaku’s blog

個人的な勉強メモです。記載内容について一切の責任は持ちません。

RSAについて(作成中)

ポイント

名前の由来は開発者3人の名前の頭文字

公開鍵暗号の一種

公開鍵暗号 - Wikipedia

暗号化と復号に別個の鍵(手順)を用い、暗号化の鍵を公開できるようにした暗号方式

他にDiffie-Hellman key exchange(DH)があり
公開鍵暗号は、共通鍵暗号の共有鍵の交換で利用される

認証機能あり(デジタル署名で利用)

DHとの違い!DHには認証機能なし!
※openssl ciphersコマンドの結果で、au=DHの暗号化スイートがあるが、これもRSAを利用してる。
static-DHによるSSL/TLS - Qiita

電子署名として使えないDHの鍵ではCSRが作れないため、ダミーのRSA鍵を作り、それを元にCSRを作る。

確認コード

# -*- coding:utf-8 -*-
from sympy import prime
import random
import math
import time

T = int(time.time())

def pr_et(m):
  global T
  print(m + ":" + str(int(time.time()) - T))
  T = int(time.time())


def def_E_D(p1, p2):
  t1 = (p1 - 1)
  t2 = (p2 - 1)
  # t1とt2の最小公倍数
  L = (t1 * t2) // math.gcd(t1, t2)
  pr_et("fin_gen_L " + str(L))

  # 1 < E < L
  # gcd(E,L) = 1
  E = random.choice([ i for i in range(2,L) if math.gcd(i, L) == 1 ])
  pr_et("fin_gen_E " + str(E))

  # 1 < D < L
  # (E×D) mod L = 1
  D = random.choice([ i for i in range(2,L) if (E * i) % L == 1 ])
  pr_et("fin_gen_D " + str(D))
  return E, D


if __name__ == '__main__':
  # 暗号文 = 平文^E mod N
  # 平文 = 暗号文^D mod N
  # E、Nの組み合わせが公開鍵
  # D、Nの組み合わせが秘密鍵
  # Nは2つの大きな素数を掛けたもの
  t =  int(time.time())

  # N、E、D算出用素数。101と1101の指定は小さい値にならないようにする為。
  p1 = prime(random.randint(101,1101))
  p2 = prime(random.randint(101,1101))
  while p1 == p2:
    p2 = prime(random.randint(101, 1101))
  pr_et("fin_gen_p12 " + str(p1) + " " + str(p2))

  N = p1 * p2
  pr_et("fin_gen_N " + str(N))
  E, D = def_E_D(p1, p2)

  # 平文"あ"を数字化。ユニコードのコードポイント利用。
  CP = ord("あ")
  pr_et("fin_gen_CP " + str(CP))

  # 暗号化
  ENC = (CP ** E) % N
  pr_et("fin_gen_ENC " + str(ENC))

  # 復号化
  DEC = (ENC ** D) % N
  pr_et("fin_gen_DEC " + str(DEC))

  if CP == DEC:
    print('Success!')
  else:
    print('Failure!')

確認コードのポイント

必ずSuccessになる。
処理自体は、そんなに複雑ではない。
攻撃者は公開鍵(E,N)と暗号化データ(ENC)は取得可能
Ephemeralデータは使わない!=PFS対応でない

素朴な疑問

①E,N,ENCを使って総当たり計算したら、どのくらい時間かかるのだろう?
②暗号化可能な点は上記で理解できる。ただデジタル署名(復号できる=認証OK)は、どうやって実装してるのだろう?

素朴な疑問①について

確認コードの実行結果

fin_gen_p12 8297 4099:0
fin_gen_N 34009403:0
fin_gen_L 16998504:0
fin_gen_E 12379243:4
fin_gen_D 12788611:2
fin_gen_CP 12354:0
fin_gen_ENC 24181895:99
fin_gen_DEC 12354:285
Success!

そもそも、こんな計算できるの?とも思ったが、できてる。。。

平文 = 暗号文^D mod N
24181895 ** 12788611 % 34009403

E=2379243
N=34009403
ENC=24181895
上記からDECを総当たりで平文出そうとしたら、どれくらい時間かかるの?
う~ん、迷走中。

結局、DECは% Nで求められるので、1 < DEC < N(34009403)になる。
Nは公開鍵に含まれる情報。Nが小さいと、復号化をNパターンでTRYしてみて、結果が自然か?を機械学習で判定できれば、復号化できるのでは?
Nは大きくするのが必須だろう。
メールデータは、最初がReceived: ~とかで始まる前提を活用し、総当たりすれば、Nを少なくできるのでは?
メール本文がhogeだけとかのメールをSMTPSで送ってみて、そのパケットをキャプチャし、復号化をためして見ようかな。。。