实验目的
- 加深对于递归技术的应用能力
- 了解计算机在数值处理领域的工作
- 掌握快速幂算法及其在大整数计算中的应用
- 掌握欧几里得算法的两种实现方式
- 理解RSA公钥加密算法及基本数学原理
实验原理
同余定理
![]()
幂剩余
假设我们想知道3^10086的个位数,或者该数与另一个数取模的结果
分为两个方面讨论:
如何高效计算x^n
如何在不需要真实计算出大整数结果的条件下,计算出x^n(mod p)
具体实现代码:
1 def modexp(x,n,p):
2 if n == 0: return 1
3 t = (x*x) % p
4 temp = modexp(t,n//2,p)
5 if n%2 != 0: temp = (tmp*x) % p
6 return temp
最大公约数与逆元
gcd(greast common divisor)
a、b互素 ==> gcd(a,b) = 1
x关于模m的逆元y满足 xy\equiv 1(mod \ n)
同一个数可能有多个乘法逆元
的当且仅当x、m互素时,x关于模m存在逆元
>>> for i in range(40):
# 3关于7的乘法逆元
... if (3*i)%7 == 1:
... print(i)
...
5
12
19
26
33
>>>
求解gcd的多种方法,主要讨论欧几里德算法,也叫辗转相除法
RSA算法简介
RSA算法是最易于理解的公钥加密算法,它对密码学的贡献主要在于密钥成对的思想,加密密钥用于明文到密文的转换,解密密钥用于密文到明文的转换。密钥都是单向的,所以用私钥加密的信息只能用公钥解密,反之亦然。
RSA算法的安全性来自于大数分解的难度。公钥和私钥由一对大素数100-200位得到。Python中原生的长整数,可以支持RSA算法的实现。
要生成两个密钥,选择两个大素数p和q,并计算它们的乘积,n=p×q
下一步是随机选择加密密钥e,使得e与p-1和q-1的乘积互素
gcd(e,(p-1)*(q-1)) = 1
加密密钥d就是e关于模(p-1)*(q-1)的逆元
e和n一起组成公钥,d则是私钥。
加密时只需使用c=m^e(mod n),解密时只需使用 m=c^d(mod n)
d是e(mod n)的逆元,不难理解:
c^d = (m^e)^d(mod n) = m^e d(mod n) = m^1(mod n) = m(mod n)
将文本转化为数字:拼接ASCII码,采用16进制
Python3字节数组可以将字符串存储为字节序列
实验内容
简易加法密码设计
凯撒密码 rot13
输入字符串helloworld,加密得到uryybjbeyq
是在字母表内部进行的循环移位加密
def encrypt(tar):
alpha = 'abcdefghijklmnopqrstuvwxyz'
res = ''
for sub in tar:
# 使用加法表示循环右移
j = (alpha.find(sub)+13)%26
res += alpha[j]
return res
# 在13之外的情况,使用密钥解密
def decrypt(tar,k):
alpha = 'abcdefghijklmnopqrstuvwxyz'
res = ''
for sub in tar:
# 使用减法表示循环左移
j = (alpha.find(sub)+26-k)%26
res += alpha[j]
return res
快速幂算法实现
def myPow(a,b):
if b == 0:return 1
if b%2 == 0:
# b is an even number
# a^b = (a^(b/2))^2
return myPow(a,b/2)**2
else:
# b is an odd number
# a^b = a^(b-1)*a while b-1 is an even number
return myPow(a,b-1)*a
li1 = [1,2,7,9,100]
for num in li1:
res = myPow(num,20)
print(f'{num} --> {res}')
欧几里得算法实现
基础版本
def gcd(a,b):
if b == 0:return a
elif a < b:return gcd(b,a)
else:return gcd(a-b,b)
改进版本
def gcd(a,b):
while b!=0:
# 60,24
# 24,12
# 12,0
# break
a,b=b,a%b
return a
gcd(60,24)
RSA算法实现
def RSAgenKeys(p,q):
n = p * q
pqminus = (p-1) * (q-1)
实验总结
练习题:leetcode 372 超级此方superpow 难度medium
在处理大整数幂运算时,至少应该想到基于递归分治的快速幂算法
若有性能考虑,轻易不要使用简单连乘的方法求运算结果
参考资料
<<labuladong算法小抄>> 第5章 5.2 如何高效进行模幂运算
<<Python数据结构与算法分析>>第二版 第8章 8.3 复习递归
https://zhuanlan.zhihu.com/p/259706781 Euclid's algorithm(欧几里得算法)