1. 算法原理
a) RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在美国麻省理工学院开发的。RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
b) RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
c) 为了产生RSA公私钥对,需要进行以下几个步骤:
Ø 选取两个大素数,p和q(目前两个数的长度都接近512bit是安全的),并计算他们的乘积得n=pq。
Ø 根据欧拉函数,不大于n 且与n 互质的整数个数为。
Ø 随机选择整数作为公钥,要求满足,即互素。
Ø 用欧几里德扩展算法计算私钥d,以满足,即。则e和n是公钥,d是私钥。
d) 加密过程
使用加密算法,计算出密文;
e) 解密过程
Ø 接收方收到密文C,并把密文C 按长度为L 分组得;加密时首先将明文比特串分组,使得每个分组对应的十进制小于n,即分组长度小于,然后对每个明文分组作加密运算,具体过程分为如下几步:
Ø 获得接收方公钥;
Ø 把消息M分组为长度为 的消息分组;
Ø 将密文C发送给接收方。
Ø 使用私钥d和解密算法,计算;
Ø 得到明文消息。
2.算法参数
参数主要包括:p、q、e、d、n。p和q为大素数,为公钥,d 为私钥,n 为p 和q 的乘积。e 和n 应公开,两个素数 p 和q 不再需要,可销毁,但绝不能泄露。另外,为了防止低指数攻击,e 不能选取太小的数。
3.python代码
```python
```python
```python
```python
import time
import random
from random import randint
# 构造字典
dict = {'a': '31', 'b': '32', 'c': '33', 'd': '34', 'e': '35', 'f': '36', 'g': '37',
'h': '38', 'i': '39', 'j': '10', 'k': '11', 'l': '12', 'm': '13', 'n': '14',
'o': '15', 'p': '16', 'q': '17', 'r': '18', 's': '19', 't': '20', 'u': '21',
'v': '22', 'w': '23', 'x': '24', 'y': '25', 'z': '26', '1': '41', '2': '42',
'3': '43', '4': '44', '5': '45', '6': '46', '7': '47', '8': '48', '9': '49',
'0': '40', ' ': '50', ',': '51', '.': '52', '/': '53', ';': '54', '\'':'55',
'[': '56', ']': '57', ':': '58', '"': '59','\'': '60', '<': '61', '>': '62',
'?': '63','\\': '64', '|': '65', '!': '66', '@': '67', '#': '68', '$': '69',
'%': '70', '^': '71', '&': '72', '*': '73', '(': '74', ')': '75', '-': '76',
'=': '77', '_': '78', '+': '79'}#这里可以自己添加不同的字符加入字典
# 字符与数字之间的映射转换
def transferToNum(str):
m = ""
for d in str:
m += dict[d]
return m
def transferTostr(num):
n = ""
for i in range(0, len(num), 2):
n += {value: key for key, value in dict.items()}[num[i] + num[i + 1]]
return n
'''
扩展欧几里的算法
计算 ax + by = 1中的x与y的整数解(a与b互质)
'''
def ext_gcd(a, b):
if b == 0:
x1 = 1
y1 = 0
x = x1
y = y1
r = a
return r, x, y
else:
r, x1, y1 = ext_gcd(b, a % b)
x = y1
y = x1 - a // b * y1
return r, x, y
'''
超大整数超大次幂然后对超大的整数取模
(base ^ exponent) mod n
'''
def exp_mode(base, exponent, n):
bin_array = bin(exponent)[2:][::-1]
r = len(bin_array)
base_array = []
pre_base = base
base_array.append(pre_base)
for _ in range(r - 1):
next_base = (pre_base * pre_base) % n
base_array.append(next_base)
pre_base = next_base
a_w_b = __multi(base_array, bin_array, n)
return a_w_b % n
def __multi(array, bin_array, n):
result = 1
for index in range(len(array)):
a = array[index]
if not int(bin_array[index]):
continue
result *= a
result = result % n # 加快连乘的速度
return result
# 生成公钥私钥,p、q为两个超大质数
def gen_key(p, q):
n = p * q
fy = (p - 1) * (q - 1) # 计算与n互质的整数个数 欧拉函数
e = 65537 # 选取e 65537
a = e
b = fy
x = ext_gcd(a, b)[1]
if x < 0:
d = x + fy
else:
d = x
print("公钥:" + "(" + str(n) + "," + str(e) + ")\n私钥:" + "(" + str(n) + "," + str(d) + ")")
return (n, e), (n, d)
def proBin(w): # w表示希望产生位数,生成目标位数的伪素数
list = []
list.append('1') # 最高位定为1
for _ in range(w - 2):
c = random.choice(['0', '1'])
list.append(c)
list.append('1') # 最低位定为1
res = int(''.join(list), 2)
return res
# 幂模运算
def X_n_mod_P(base, exponent, n):
bin_array = bin(exponent)[2:][::-1]
r = len(bin_array)
base_array = []
pre_base = base
base_array.append(pre_base)
for _ in range(r - 1):
next_base = (pre_base * pre_base) % n
base_array.append(next_base)
pre_base = next_base
a_w_b = __multi(base_array, bin_array, n)
return a_w_b % n
def __multi(array, bin_array, n):
result = 1
for index in range(len(array)):
a = array[index]
if not int(bin_array[index]):
continue
result *= a
result = result % n # 加快连乘的速度
return result
def MillerRabin(a, p): # 素性测试
if X_n_mod_P(a, p - 1, p) == 1:
u = (p - 1) >> 1
while (u & 1) == 0:
t = X_n_mod_P(a, u, p)
if t == 1:
u = u >> 1
else:
if t == p - 1:
return True
else:
return False
else:
t = X_n_mod_P(a, u, p)
if t == 1 or t == p - 1:
return True
else:
return False
else:
return False
def testMillerRabin(p, k): # k为测试次数,p为待测奇数
while k > 0:
a = randint(2, p - 1)
if not MillerRabin(a, p):
return False
k = k - 1
return True
def makeprime(w): # 产生w位素数
while 1:
d = proBin(w)
for i in range(50): # 伪素数附近50个奇数都没有真素数的话,重新再产生一个伪素数
u = testMillerRabin(d + 2 * (i), 5)
if u:
b = d + 2 * (i)
break
else:
continue
if u:
return b
else:
continue
# 加密 m是被加密的信息 加密成为c
def encrypt(m, pubkey):
n = pubkey[0]
e = pubkey[1]
c = exp_mode(m, e, n)
return c
# 解密 c是密文,解密为明文m
def decrypt(c, selfkey):
n = selfkey[0]
d = selfkey[1]
m = exp_mode(c, d, n)
return m
if __name__ == "__main__":
print("1.生成>64位的质数p和q(以528位为例):")#可以通过更改makeprime()的参数生成不同位数的p,q
p = makeprime(528)
print("p:", p)
q = makeprime(528)
print("q:", q)
print("2.生成公钥私钥")
pubkey, selfkey = gen_key(p, q)
print("3.输入明文(小写英文与数字的组合及英文字符)")
plaintext = str(input())
m = int(transferToNum(plaintext))
print("4.用公钥加密信息")
c = encrypt(m, pubkey)
print("密文:", c)
print("5.用私钥解密")
d = decrypt(c, selfkey)
print("明文:", transferTostr(str(d)))
演示: