加密方式从密钥是否相同的角度分为对称加密和非对称加密。
对称加密:“加密”和“解密”使用【相同的】密钥。
非对称加密:“加密”和“解密”使用【不相同的】密钥。
非对称加密服务端生成一对密钥(公钥和私钥),将公钥公开给访问者,要求访问者通过公钥来加密,自己通过私钥来解密。
从效率上来讲,对称加密速率快很多,但是密钥的保存和传输的安全性成了很大的风险;而非对称加密只传输公钥,没有私钥是无法解开密文的,所以安全性更高,但是开销更大。
现阶段流行的非对称加密是RSA加密,本文主要解释下RSA非对称加密,并用Python做验证。
RSA这个缩写很坑,因为对应的不是什么英文单词的意思,而是发明这种算法的三位数序家的首字母(Rivest、Shamir和 Adleman)
1随机生成2个不想等的质数(也叫素数),p和q
2计算n=p*q, n的二进制就是密钥的长度,一般是1024位,重要场合是2048位
3计算欧拉函数N=(p-1)*(q-1)
4随机选择一个整数e,条件是1<e<N,且e与N互质
5计算一个模反元素d,所谓模反元素就是使N/ed取余=1
简单可以理解为ed=N+1
6 (n,e)封装为公钥,(n,d)封装为私钥
7利用(n,e)公钥进行加密,明文内容是m,加密后密文是c
(m的e次方)除以n取余,结果为密文c
换算成公式是c=(m**e)/n取余
8利用(n,d)私钥进行解密
(c**d)/n取与,结果为解密后的明文
下面python做验证,代码如下:
import math
import random
#判断是否为质数
def isPrime(n):
if n<=1:
return False
for i in range(2,int(math.sqrt(n))+1) :
if n%i==0:
return False
return True
#质数100-200间,不需要算太大,只是为了演算
p = random.choice(range(100,200))
#p=61
while not isPrime(p) :
p = random.choice(range(100, 200))
else:
print('P: %d' % p);
q = random.choice(range(100,200))
#q=53
while not isPrime(q) or p==q:
q = random.choice(range(100, 200))
else:
print('q: %d'% q);
n=p*q
print('n: %d and bin is %s' %(n,bin(n)))
N=(p-1)*(q-1)
print('欧拉函数N=%d' %N)
#保证e也是个质数,就可以保证e与N互质
e=random.choice(range(1,N))
#e=17
while not isPrime(e) :
e = random.choice(range(1, N))
else:
print('e: %d' % e);
#计算模反元素d
d=random.choice(range(1,N))
while not ((e*d)%N==1):
d = random.choice(range(1, N))
else :
print('模反元素d: %d' % d);
print('Public key is (%d %d), private key is (%d %d)' %(n,e,n,d))
print('----开始对数据进行加密----')
m=random.choice(range(1, 100))
print('加密前明文m=%d' %m)
c=m**e%n
print('加密后密文c=%d' %c)
print('----开始对数据进行解密----')
M=c**d%n
print('解密后明文m=%d' %M)
结果如下:
P: 181
q: 179
n: 32399 and bin is 0b111111010001111
欧拉函数N=32040
e: 1153
模反元素d: 6697
Public key is (32399 1153), private key is (32399 6697)
----开始对数据进行加密----
加密前明文m=43
加密后密文c=405
----开始对数据进行解密----
解密后明文m=43
注:公钥和私钥只是在应用层面上相对的,你决定不公开的就为私钥,公开的就为公钥,在数学层面上来说
(n,e)(n,d)
是等价的,谁做私钥都可以,用私钥加密的内容用公钥也可以解的开。数字签名就是对方用自己保管的私钥加密,客户端用公钥来解密,来确保签名方的身份。