今回はRSA暗号について
考えてみることにしました。


解説動画はこちら


さてさて
RSAッて良く分からないので
Wikiで調べてみることにしました。

RSA暗号とは、桁数が大きい合成数の素因数分解問題が
困難であることを安全性の根拠とした公開鍵暗号の一つ
鍵生成、暗号化、復号の3つのアルゴリズムで定義される

うん・・・・・

RSA暗号は次のような方式である

鍵のペア(公開鍵と秘密鍵)を作成して公開鍵を公開する
まず、適当な正整数 E を選択する

また、大きな2つの素数の組み P,Q を生成し
それらの積(N=PQ)を求めて、組みE,N を
平文の暗号化に使用する鍵(公開鍵)とする

2つの素数P,Qは秘密に保管し
暗号文の復号に使用する鍵(秘密鍵)D の生成にも使用する

暗号化(平文 M から暗号文 C を作成する):
復号(暗号文 C から元の平文 M を得る): 
暗号化(E 乗)は公開鍵 E,N があれば容易に計算でき
復号(D 乗)も容易に計算できる

しかし、秘密鍵 D を知らずに
解読(法 N の下で E 乗根を計算)するのは
「N の素因数を知らないと難しい」と考えられている

つまり
「秘密鍵を用いずに暗号文から平文を得ることは難しい」
と信じられている

これがRSA暗号の安全性の根拠である


はい良くわかりませんです!!!


というわけで
サンプルコードを作ってみました。

# RSA暗号の例
import random
import fractions
import sympy
import warnings 
warnings.filterwarnings('ignore')

# 乱数生成
def _random():
    digit = 10
    return random.randrange(10**(digit - 1),10**digit)

# 最小公倍数
def _lcm(p , q):
    return (p * q) // fractions.gcd(p, q)

# 拡張ユークリッド
def _euclid(x,y):
    c0, c1 = x, y
    a0, a1 = 1, 0
    b0, b1 = 0, 1
    while c1 != 0:
        m = c0 % c1
        q = c0 // c1
        c0, c1 = c1, m
        a0, a1 = a1, (a0 - q * a1)
        b0, b1 = b1, (b0 - q * b1)
    return c0, a0, b0

# キー生成
def generate_key(p = 0,q = 0,e = 0,d = 0,n = 0,l = 0):
    if p == 0:
        while True:
            p = _random()
            if sympy.isprime(p):break
    _p = p
    if q == 0:
        while True:
            q = _random()
            if sympy.isprime(q) and p != q:break
    _q = q
    if n == 0:
        n = p * q
    _n = n
    if l == 0:
        l = _lcm(p - 1, q  - 1)
    _l = l
    if e == 0:
        while True:
            i = random.randint(2,l)
            if fractions.gcd(i, l) == 1:
                e = i
                break
    _e = e
    if d == 0:
        _c, a, _b = _euclid(e, l)
        d = a % l
    _d = d
    return _e,_d,_n,_p,_q,_l

# 暗号化
def encrypt(_e,_n,plaintext):
    st,ciphertext = "",[]
    for i in map((lambda x: pow(ord(x), _e,_n)),list(plaintext)):
        ciphertext.append(i)
        st += str(i)
    return st,ciphertext

# 復号化
def decrypt(_d,_n,ciphertext):
    cip , st = [] , ""
    for i in  list(ciphertext):
        tmp = chr(pow(i, _d,_n))
        cip.append(tmp)
        st += str(tmp)
    return st

使う際は平文として暗号化したい
文字列を定義しておきます。

plain_text = '文字列を入力'


早速使っていきましょう。
暗号化するところと
復号化するところのコードです。
# 初期化
ciphertext = []
_e = _d = _n = _p = _q = _l = 0

# キー生成
_e,_d,_n,_p,_q,_l = generate_key(0,0,65537)

# 暗号化
e_text , ciphertext = encrypt(_e,_n,plain_text)

# 復号化
d_text = decrypt(_d,_n,ciphertext)

print('素数 p : {0}'.format(_p))
print('素数 q : {0}'.format(_q))
print('l : {0}'.format(_l))
print('公開鍵 e : {0}'.format(_e))
print('公開鍵 n : {0}'.format(_n))
print('秘密鍵 d : {0}'.format(_d))
print()

print('暗号文(String) : {0}'.format(e_text))
print()
print('暗号文(List) : {0}'.format(ciphertext))

素数 p : 9558530557
素数 q : 5377612577
l : 12850518531506468064
公開鍵 e : 65537
公開鍵 n : 51402074140962015389
秘密鍵 d : 104902992421928993

暗号文(String) : 502447033995121916661752375033108949410513472439923007515854175237503310894941051347243992300751585434094647152221189902182494137669912247793511588278946816434351158827894681643422454674385942603378

暗号文(List) : [50244703399512191666, 17523750331089494105, 13472439923007515854, 17523750331089494105, 13472439923007515854, 34094647152221189902, 18249413766991224779, 3511588278946816434, 3511588278946816434, 22454674385942603378]

素数P,Qや
鍵N,Dは毎回変わってしまいます。

公開鍵Nと秘密鍵Dがあれば
暗号を解読することができます。

暇な方は上記の鍵と暗号文から
復号してみてくださいね。

人類を平和にする
「あいことば」を暗号にしてみましたよ

解読面倒な方は
動画見て下さいねーー


このサンプルコードでは
およそ20桁ほどの秘密鍵になりますんで
9千京回ほどブルートフォースすれば
暗号解読できるかもしれません!!!!

鼻血出せば解けるかもしれませんねえ
そんなアニメが有るとか無いとか

自分ならやらないっすねーー

今回はここまででーす
それでは。