ポイント
名前の由来は開発者3人の名前の頭文字
公開鍵暗号の一種
暗号化と復号に別個の鍵(手順)を用い、暗号化の鍵を公開できるようにした暗号方式
他にDiffie-Hellman key exchange(DH)があり
※公開鍵暗号は、共通鍵暗号の共有鍵の交換で利用される
認証機能あり(デジタル署名で利用)
DHとの違い!DHには認証機能なし!
※openssl ciphersコマンドの結果で、au=DHの暗号化スイートがあるが、これもRSAを利用してる。
static-DHによるSSL/TLS - Qiita
確認コード
# -*- 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で送ってみて、そのパケットをキャプチャし、復号化をためして見ようかな。。。