实验

名称

RSA的编程实现

成绩评定




所用


仪器


材料



Win10

Python

Pycharm






















  1. 实验目的(1)加深对RSA算法的理解;
    (2)加深对平方乘算法和模重复平方法的理解。
  2. 实验原理RSA是在1977年由Rivest、Shamir和Adleman提出的第一个比较完善的非对称密码算法。它的安全性是建立在“大数分解和素性检测”这个数论难题的基础上,即将两个大素数相乘在计算上容易实现,而将该乘积分解为两个大素数因子的计算量相当大。虽然它的安全性还未能得到理论证明,但经过20多年的密码分析和攻击,迄今仍然被实践证明是安全的。
    RSA算法描述如下:
    1.公钥
    选择两个互异的大素数p和q(保密),n是二者的乘积,即n=pq,使

    RSA实验_RSA

    欧拉函数(保密)。随机选取正整数e,使其满足

    RSA实验_欧几里得算法_02

    ,即e和

    RSA实验_RSA_03

    互质,则将

    RSA实验_RSA_04

    作为公钥。
    2.私钥
    求出正数d,使其满足

    RSA实验_编程实现_05

    ,则将(n,d)作为私钥。
    3.加密算法
    对于明文M,由

    RSA实验_编程实现_06

    ,得到密文C。
    4.解密算法
    对于密文C,由

    RSA实验_欧几里得算法_07

    ,得到明文M。
    如果窃密者获得了n、e和密文C,为了破解密文必须计算出私钥d,为此需要先分解n。为了提高破解难度,达到更高的安全性,一般商业应用要求n的长度不小于1024位,更重要的场合不小于2048位。
  3. 实验步骤









































1.欧几里得算法实验:设 a 为自己的学号,b=210,编程实现扩展的欧几里得算法,求整数s[n]t[n],使得 s[n]a+t[n]b=(a, b)。

(1)根据以下代码,编程实现扩展的欧几里得算法,输出计算的中间结果及最终运算结果。

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

print(str(a) + '=' +str(a//b)+'×'+str(b)+'+' + str(a%b))

print(str(r) + '=' + str((a)) + '×' + str(x) + '+' + str(b)+ '×'+str(y))

print('裴蜀等式:'+str(r)+'='+str(a)+'×'+str(x)+'+'+str(b)+'×'+str(y))

(2)代码如下:

def ext_gcd(a, b):
if b == 0:
x1 = 1
y1 = 0
x = x1
y = y1
r = a
return r, x, y
else:
print(str(a) + '=' +str(a//b)+'×'+str(b)+'+' + str(a%b))
r, x1, y1 = ext_gcd(b, a % b)
x = y1
y = x1 - a // b * y1
if x!=0:
print(str(r) + '=' + str((a)) + '×' + str(x) + '+' + str(b)+ '×'+str(y))
return r, x, y
if __name__ == '__main__':
a=20101030210;
b=210;
r, x, y=ext_gcd(a, b)
print('裴蜀等式:'+str(r)+'='+str(a)+'×'+str(x)+'+'+str(b)+'×'+str(y))

RSA实验_RSA_08


2.素性检测算法实验:设a为自己的学号后两位+100编程实现Miller-Rabin素性检测算法,找出使得离a最近且比a大的三个素数

(1)Miller-Rabin素性检测算法python语言代码

import math
import random

# 使用平方乘算法,计算a**b(mod n)。
def SquareMultiplication(a, b, n):
# 将b表示为二进制形式bkbl-1...b0,既b=bn*2**n+bn-1*2**(n-1)+...+b1*2**1+b0*2**0
b_bin = bin(b)[2:][::-1]
r=1
#a**b=(((((1**2*a**bn)**2*a**bn-1)**2...a**b2)**2)*a**b1)**2*a**b0
for i in list(range(len(b_bin)))[::-1]:
r=r*r*a**int(b_bin[i])%n
return r

# 使用模重复平方算法,计算a**b(mod n)。

def ModRepeatSquare(a, b, n):
# 将b表示为二进制形式bkbk-1...b0,既b=bk*2**k+bk-1*2**(k-1)+...+b1*2**1+b0*2**0
b_bin = bin(b)[2:][::-1]
r=1
#a**b=a**b0*(a**2)**b1...(a**2**k-1)**bk-1*(a**2**k)**bk
for i in list(range(len(b_bin))):
if b_bin[i]=='1':r=a*r%n
a=a*a%n
return r



#欧几里得算法,求最大公约数
def gcd(a, b):
if b == 0:
return a
else:
r = gcd(b, a % b)
return r


# 如果返回值为TRUE表示n为素数,返回值为FALSE表示n为合数。
def MillerRabinPrimeTest(n):
a = random.randint(2, n - 2) # 随机第选取一个a∈[2,n-2]
if gcd(a, n)>1:
return False
s = 0 # s为d中的因子2的幂次数。
t = n - 1
while (t & 1) == 0: # 将d中因子2全部提取出来。
s += 1
t >>= 1

x = ModRepeatSquare(a, t, n)
for i in range(s): # 进行s次二次探测
newX = ModRepeatSquare(x, 2, n)
if newX == 1 and x != 1 and x != n - 1:
return False # 用二次探测定理的逆否命题,此时n确定为合数。
x = newX

if x != 1: # 用费马小定理的逆否命题判断,此时x=a^(n-1) (mod n),那么n确定为合数。
return False

return True # 用费马小定理的逆命题判断。能经受住考验至此的数,大概率为素数。


# 经过连续特定次数(如100次)的Miller-Rabin测试后,
# 如果返回值为TRUE表示n为素数,返回值为FALSE表示n为合数。
def isPrimeByMRS(n):
if n<=3 or (n & 1) == 0:
return False
for i in range(100):
if MillerRabinPrimeTest(n) == False:
return False
return True

if __name__ == '__main__':
random.seed()
#a为自己的学号后两位+100,如学号后两位为07
a = 110
for i in range(a, a + 10):
result = isPrimeByMRS(i)
if result == True:
print("离a最近且比a大的三个素数为:%d" %(i))

RSA实验_RSA_09


3. 模重复平方算法实验:

实现的python代码如下:

def SquareMultiplication(a, b, n):
# b表示为二进制形式bkbl-1...b0,b=bn*2**n+bn-1*2**(n-1)+...+b1*2**1+b0*2**0
b_bin = bin(b)[2:][::-1]
r=1
#a**b=(((((1**2*a**bn)**2*a**bn-1)**2...a**b2)**2)*a**b1)**2*a**b0
for i in list(range(len(b_bin)))[::-1]:
r=r*r*a**int(b_bin[i])%n
return r
# 使用模重复平方算法,计算a**bmod n)。
def ModRepeatSquare_10(a_10, b_10, n_10):
# b表示为二进制形式bkbk-1...b0,b=bk*2**k+bk-1*2**(k-1)+...+b1*2**1+b0*2**0
b_10_bin = bin(b_10)[2:][::-1]
r_10=1
#a**b=a**b0*(a**2)**b1...(a**2**k-1)**bk-1*(a**2**k)**bk
for i in list(range(len(b_10_bin))):
if b_10_bin[i]=='1':r_10=a_10*r_10%n_10
a_10=a_10*a_10%n_10
print(''+ str(i)+ ', m['+str(i) + ']=' + str(b_10 & 1) + 'r['+str(i)+']='+ str(r_10)
+ '(mod'+str(n_10)+ '),a['+str(i)+ ']='+str(a_10))
else:
print(''+ str(i) + '轮,m['+ str(i)+ ']='+ str(b_10 & 1) + 'r['+ str(i)+']='+'r['+str(
i- 1) + ']×'+ 'a['+ str(i - 1)+ ']='+ str(r_10) + '(mod'+ str(n_10) + '),a['+str(i)+']='+str(a_10))
return r_10

if __name__ == '__main__':
print("使用模重复平方法计算a**m(mod n),请输入数字a:");
a_10 = int(input());
print("请输入数字m:");
b_10 = int(input());
print("请输入数字n:");
n_10 = int(input());
result_10 = ModRepeatSquare_10(a_10, b_10, n_10)
print('结果为:'+str(a_10)+'**'+str(b_10)+'(mod '+str(n_10)+')'+'='+str(result_10))


RSA实验_算法实验_10

RSA实验_算法实验_11


RSA实验_RSA_12



4.算法实验:

开RSA源码文件夹,熟悉RSA算法流程,将公钥(e,n)中的e改为学号后5位,e=30210


RSA实验_欧几里得算法_13



五、实验思考

  1. 源程序中采用的哪种快速运算算法?拓展欧几里得算法、Miller-Rabin素性检测算法、模重复平方算法
  2. 如何确保大素数p和q是满足条件的大素数呢?费马素性检测,通过费马小定理:如果p是一个素食,且整数a不是p的倍数,那么a^p-1=1(modp)
  3. 正整数e一般建议选取多少?为什么?

一般建议取e=2^16+1=65537.

六、实验算例

设p=43,q=59,取公钥e=13+学号后两位=23,用RSA算法加密明文public。将明文代替为数字,代替方案为a-00,b-01,...,z-25(两位十进制数表示),既public=162102120903;并利用RSA算法实验

RSA实验_编程实现_14