JFLong  

实验目的

  • 加深对于递归技术的应用能力
  • 了解计算机在数值处理领域的工作
  • 掌握快速幂算法及其在大整数计算中的应用
  • 掌握欧几里得算法的两种实现方式
  • 理解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(欧几里得算法)

posted on 2025-04-24 17:30  鱼孜千  阅读(31)  评论(0)    收藏  举报