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发送信息。
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位的密钥极其安全,当然量子计算机除外。
首先我们需要明白几个基本概念
任意给定正整数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
欧拉函数的几个特性
如果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)=pk−p(k−1)。
比如: ϕ ( 8 ) = ϕ ( 2 3 ) = 2 3 − 2 2 = 8 − 4 = 4 \phi(8)=\phi(2^3)=2^3-2^2=8-4=4 ϕ(8)=ϕ(23)=23−22=8−4=4
如果n是质数,则 ϕ ( n ) = n − 1 \phi(n)=n-1 ϕ(n)=n−1 。因为质数与小于它的每一个数,都构成互质关系。
比如:计算7的欧拉函数,7是质数, ϕ ( 7 ) = 6 \phi(7) = 6 ϕ(7)=6
如果n可以分解成两个互质的整数之积,即$ n = p * k$ ,则 ϕ ( n ) = ϕ ( p ∗ k ) = ϕ ( p 1 ) ∗ ϕ ( p 2 ) \phi(n) = \phi(p * k) = \phi(p1)*\phi(p2) ϕ(n)=ϕ(p∗k)=ϕ(p1)∗ϕ(p2),
比如: ϕ ( 56 ) = ϕ ( 8 ) ∗ ϕ ( 7 ) = 4 ∗ 6 = 24 \phi(56) = \phi(8) * \phi(7) = 4 * 6 = 24 ϕ(56)=ϕ(8)∗ϕ(7)=4∗6=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)modn≡1
欧拉定理的特殊情况,如果两个正整数m和n互质,而且n为质数!那么φ(n)结果就是n-1
m ( n − 1 ) m o d n ≡ 1 m^{(n-1)} \mod n \equiv 1 m(n−1)modn≡1
如果两个正整数e和x互质,那么一定可以找到整数d,使得$ed-1 被 x 整 除 , 或 者 说 被x整除,或者说 被x整除,或者说ed$被x除的余数是1。那么d就是e相对于x的模反元素。
e ∗ d m o d x ≡ 1 e*d \mod x \equiv 1 e∗dmodx≡1
以上基本原理都很浅显,接下来稍微转化一下
m Φ ( n ) m o d n ≡ 1 (1) m^{\Phi (n)} \mod n \equiv 1 \tag{1} mΦ(n)modn≡1(1)
m k ∗ Φ ( n ) m o d n ≡ 1 (2) m^{k*\Phi (n)}\mod n \equiv 1 \tag{2} mk∗Φ(n)modn≡1(2)
m k ∗ Φ ( n ) + 1 m o d n ≡ m (3) m^{k*\Phi (n)+1}\mod n \equiv m \tag{3} mk∗Φ(n)+1modn≡m(3)
e ∗ d ≡ k ∗ x + 1 (4) e*d \equiv k*x+1 \tag{4} e∗d≡k∗x+1(4)
m e ∗ d m o d n ≡ m (5) m^{e*d} \mod n \equiv m \tag{5} me∗dmodn≡m(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} me∗dmodn==>(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 memodn≡ccdmodn≡m
第一个用于加密,第二个用于解密。假设 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 3d−1=8,d也可以为3,11等等,也就是 d = ( 8 k + 1 ) / 3 d = (8k + 1) / 3 d=(8k+1)/3)
算法过程
这里得到的(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])