RSA算法原理

  1976年,两位美国计算机学家 W h i t f i e l d D i f f i e Whitfield Diffie WhitfieldDiffie M a r t i n H e l l m a n Martin Hellman MartinHellman,提出了一种崭新构思,可以在不直接传递密钥的情况下,完成解密。这被称为"Diffie-Hellman密钥交换算法"。这个算法的产生,预示着非对称加密诞生了。

  非对称加密的场景是:A给B发送信息。

  1. B要先生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
  2. A获取B的公钥,然后用它对信息加密。
  3. B得到加密后的信息,用私钥解密。

  1977年,三位数学家 R i v e s t Rivest Rivest S h a m i r Shamir Shamir A d l e m a n Adleman Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字命名,叫RSA算法。从那时直到现在,RSA算法一直是最广为使用的"非对称加密算法"。毫不夸张地说,只要有计算机网络的地方,就有RSA算法。这种算法非常可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长RSA密钥是232个十进制位,也就是768个二进制位,因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全,当然量子计算机除外。

RSA基本原理

  首先我们需要明白几个基本概念

  1. 素数:又称质数,指在一个大于1的自然数中,除了1和此整数本身外,不能被其他自然数整除的数。
  2. 互质,又称互素。若N个整数的最大公因子是1,则称这N个整数互质。
  3. 模运算即求余运算。”模“是“ m o d mod mod”的音译。和模运算紧密相关的一个概念是“同余”。数学上,当两个整数除以同一个正整数,若得相同余数,则二整数同余。
欧拉函数

  任意给定正整数n,请问在小于等于n的正整数之中,有多少个与n构成互质关系?(比如,在1到8之中,有多少个数与8构成互质关系?)计算这个值的方法就叫做欧拉函数,以 ϕ ( n ) \phi (n) ϕ(n)表示。

  比如,计算8的欧拉函数,和8互质的 1、2、3、4、5、6、7、8,所以 ϕ ( 8 ) = 4 \phi(8) = 4 ϕ(8)=4

  欧拉函数的几个特性

  1. 如果n是质数的某一个次方,即 n = p k n = p^k n=pk (p为质数,k为大于等于1的整数),则 ϕ ( n ) = ϕ ( p k ) = p k − p ( k − 1 ) \phi(n)=\phi(p^k)=p^k-p^(k-1) ϕ(n)=ϕ(pk)=pkp(k1)

    比如: ϕ ( 8 ) = ϕ ( 2 3 ) = 2 3 − 2 2 = 8 − 4 = 4 \phi(8)=\phi(2^3)=2^3-2^2=8-4=4 ϕ(8)=ϕ(23)=2322=84=4

  2. 如果n是质数,则 ϕ ( n ) = n − 1 \phi(n)=n-1 ϕ(n)=n1 。因为质数与小于它的每一个数,都构成互质关系。

    比如:计算7的欧拉函数,7是质数, ϕ ( 7 ) = 6 \phi(7) = 6 ϕ(7)=6

  3. 如果n可以分解成两个互质的整数之积,即$ n = p * k$ ,则 ϕ ( n ) = ϕ ( p ∗ k ) = ϕ ( p 1 ) ∗ ϕ ( p 2 ) \phi(n) = \phi(p * k) = \phi(p1)*\phi(p2) ϕ(n)=ϕ(pk)=ϕ(p1)ϕ(p2)

    比如: ϕ ( 56 ) = ϕ ( 8 ) ∗ ϕ ( 7 ) = 4 ∗ 6 = 24 \phi(56) = \phi(8) * \phi(7) = 4 * 6 = 24 ϕ(56)=ϕ(8)ϕ(7)=46=24

欧拉定理

  如果两个正整数m和n互质,那么m的 ϕ ( n ) \phi(n) ϕ(n)次方减去1,可以被n整除。
m Φ ( n ) m o d    n ≡ 1 m^{\Phi (n)} \mod n \equiv 1 mΦ(n)modn1

小费马定理

  欧拉定理的特殊情况,如果两个正整数m和n互质,而且n为质数!那么φ(n)结果就是n-1
m ( n − 1 ) m o d    n ≡ 1 m^{(n-1)} \mod n \equiv 1 m(n1)modn1

模反元素

  如果两个正整数e和x互质,那么一定可以找到整数d,使得$ed-1 被 x 整 除 , 或 者 说 被x整除,或者说 xed$被x除的余数是1。那么d就是e相对于x的模反元素。
e ∗ d m o d    x ≡ 1 e*d \mod x \equiv 1 edmodx1

  以上基本原理都很浅显,接下来稍微转化一下
m Φ ( n ) m o d    n ≡ 1 (1) m^{\Phi (n)} \mod n \equiv 1 \tag{1} mΦ(n)modn1(1)

m k ∗ Φ ( n ) m o d    n ≡ 1 (2) m^{k*\Phi (n)}\mod n \equiv 1 \tag{2} mkΦ(n)modn1(2)

m k ∗ Φ ( n ) + 1 m o d    n ≡ m (3) m^{k*\Phi (n)+1}\mod n \equiv m \tag{3} mkΦ(n)+1modnm(3)

e ∗ d ≡ k ∗ x + 1 (4) e*d \equiv k*x+1 \tag{4} edkx+1(4)

m e ∗ d m o d    n ≡ m (5) m^{e*d} \mod n \equiv m \tag{5} medmodnm(5)

  公式3与公式4转化为公式5,需要一个前提: e e e ϕ ( n ) \phi (n) ϕ(n)互质

  我们可以将公式5变换一下:
m e ∗ d m o d    n = = > ( m e ) d m o d    n (6) m^{e*d} \mod n ==> (m^e)^d \mod n \tag{6} medmodn==>(me)dmodn(6)

m e m o d    n ≡ c c d m o d    n ≡ m m^e \mod n \equiv c \\ c^d \mod n \equiv m memodnccdmodnm

  第一个用于加密,第二个用于解密。假设 m = 12 m=12 m=12(随便取值,只要比n小就可以), n = 15 n=15 n=15(还是随机取一个值,不一定非要互质), ϕ ( n ) = 8 \phi(n) = 8 ϕ(n)=8 e = 3 e=3 e=3( e e e必须和 ϕ ( n ) \phi(n) ϕ(n)互质),这里取 d = 19 d=19 d=19 3 d − 1 = 8 3d-1=8 3d1=8,d也可以为3,11等等,也就是 d = ( 8 k + 1 ) / 3 d = (8k + 1) / 3 d=(8k+1)/3

算法过程

  1. 随意选择两个大的质数p和q,p不等于q,计算 N = p ∗ q N=p*q N=pq
  2. 根据欧拉函数,不大于N且与N互质的整数的个数为 ( p − 1 ) ( q − 1 ) (p-1)(q-1) (p1)(q1)
  3. 选择一个整数e与 ( p − 1 ) ( q − 1 ) (p-1)(q-1) (p1)(q1)互质,并且e小于 ( p − 1 ) ( q − 1 ) (p-1)(q-1) (p1)(q1)
  4. 用以下这个公式计算d: d ∗ e m o d    ( p − 1 ) ( q − 1 ) ≡ 1 d*e \mod (p-1)(q-1) \equiv 1 demod(p1)(q1)1
  5. 将p和q的记录销毁。

  这里得到的(N, e)是公钥,(N, d)是私钥。

  下面展示RSA的实现细节

import time


def range_prime(start, end):
    l = list()
    for i in range(start, end+1):
        flag = True
        for j in range(2, int(i**0.5)+1):
            if i % j == 0:
                flag = False
                break
        if flag:
            l.append(i)
    return l


def generate_keys(p, q):
    numbers = range_prime(10, 100)
    N = p * q
    C = (p-1) * (q-1)
    e = 0
    for n in numbers:
        if n < C and C % n > 0:
            e = n
            break
    if e == 0:
        raise BaseException("e not found")
    d = 0
    for n in range(2, C):
        if(e * n) % C == 1:
            d = n
            break
    if d == 0:
        raise BaseException("d not found")
    return (N, e), (N, d)


def quick_algorithm(a, b, c):
    a = a % c
    ans = 1
    while b != 0:
        if b & 1:
            ans = (ans * a) % c
        b >>= 1
        a = (a * a) % c
    return ans


def encrypt(m, key):
    C, x = key
    # return quick_algorithm(m, x, C)
    return (m ** x) % C


def decrypt(m, key):
    return encrypt(m, key)


def ord2hex(num):
    return hex(num)


if __name__ == '__main__':
    start = int(1e3)
    end = int(1e5)
    prime_list = []
    count = 0
    while len(prime_list) < 2:
        if count > 5:
            raise RecursionError("达到最大次数")
        prime_list = range_prime(start, end)
    a = prime_list[0]
    b = prime_list[-1]
    print(a, b)
    time1 = time.time()
    print("开始产生密钥对")
    public_key, private_key = generate_keys(a, b)
    print("私钥:", private_key)
    print("公钥:", public_key)
    time2 = time.time()
    print("密钥对生成结束,耗时:{}s".format(time2-time1))
    ord_list = []
    encode_list = []
    s_input = input("请输入要加密的字符串:")
    time3 = time.time()
    print("开始加密")
    for s in s_input:
        s_ord = ord(s)
        s_encode = encrypt(s_ord, public_key)
        ord_list.append(s_ord)
        encode_list.append(s_encode)
    time4 = time.time()
    print("加密完成,耗时:{}s".format(time4-time3))
    # print(ord_list)
    print(encode_list)
    print("原数据:", [ord2hex(num) for num in ord_list])
    print("加密后的数据:", ":".join([ord2hex(num) for num in encode_list]))
    print("开始解密")
    time5 = time.time()
    decode_list = []
    for num_encode in encode_list:
        ord_decode = decrypt(num_encode, private_key)
        decode_list.append(ord_decode)
    time6 = time.time()
    print("解密完成,耗时:{}s".format(time6-time5))
    print("解密后的数据:", [ord2hex(num) for num in decode_list])
    print("转化为字符串:", [chr(num) for num in decode_list])

你可能感兴趣的:(随笔,密码学)