密码学实验二
一、实验目的(本次实验所涉及并要求掌握的知识点)
- 掌握RSA算法的基本原理并根据给出的RSA算法简单的实现代码源程序,以及能够使用RSA对文件进行加密。
- 掌握素性测试的基本原理,并且会使用Python进行简单的素性测试以及初步理解Solovag-Strassen检测,Lehmam检测,Rabin-Miller检测算法。
二、实验原理和技术路线
(一)RSA编码实验
- 非对称密码
对称密码算法要求通信双方通过交换密钥实现使用同一个密钥,这在密钥管理、发布和安全性方面存在很多问题,而非对称密码算法解决了这个问题。非对称密码算法是指一个加密系统的加密密钥和解密密钥是不相同,或者说不能从其中一个推导出另一个。在非对称密码算法的两个密钥中,一个是用于加密的密钥,可以公开的称为公钥;另一个是用于解密的密钥,是保密的称为私钥。非对称密码算法解决了对称密码体制中密钥管理难题,并提供对信息发送人的身份进行验证的手段,是现代密码学的最重要的发明和进展。 - RSA编码密码原理
RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。由于进行的都是大数计算,使得RSA最快的情况也比DES慢上好几倍,无论是软件还是硬件实现,速度一直是RSA的缺陷,一般来说只用于少量数据加密,RSA的速度比对应同样安全级别的对称密码算法要慢1000倍左右。
- 公钥:选择两个互异的大素数p和q,n是二者的乘积,即n=pq使Φ(n)=(p-1)(q-1),Φ(n)为欧拉函数,随机选取正整数e使其满足gcd(e,Φ(n))=1即e和Φ(n)互质,则将(n,e)作为公钥。
- 私钥:求出正数d使其满足e×d=1modΦ(n)则将(n,d)作为私钥。
- 加密算法:对于明文M由C=Memodn得到密文C。
- 解密算法:对于密文C由M=Cdmodn得到明文M如果窃密者获得了n,e和密文C为了破解密文必须计算出私钥d为此需要先分解n为p和q为了提高破解难度,达到更高的安全性,一般商业应用要求n的长度不小于1024bit,更重要的场合不小于2048bit。
加密解密算法的数学表达式为:
加密: c i = m i e m o d n ( 1 ≤ i ≤ t ) c_i=m_i^emodn(1≤i≤t) ci=miemodn(1≤i≤t)
解密: m i = c i d m o d n ( 1 ≤ i ≤ t ) m_i=c_i^dmodn(1≤i≤t) mi=cidmodn(1≤i≤t)
- RSA算法缺点
1)产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。
2)安全性,RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难度与大数分解难度等价,而且密码学界多数人士倾向于因子分解不是NP问题。
3)速度太慢,由于RSA的分组长度太大,为保证安全性,n至少也要600bits以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。
(二)素性测试编码实验
- 素数(质数):质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。(质数和合数中不包括负数)
- 素性检测:在以往判断一个数a是不是素数时,都是采用i从2到sqrt(a)能否整除a。如果能整除,则a是合数;否则是素数。但是该算法的时间复杂度为O(sqrt(a)),当a较大时,时间性能很差,特别是在网络安全和密码学上一般都需要很大的素数。而从目前来看,确定性算法判断素数的性能都不好,所以可以用MC(蒙特卡洛)概率算法来解决,其中MillerRabin算法就是其中的很经典的解决方法。下面首先介绍下相关的数学理论。
- 理论基础:Fermat小定理:若a是素数,则对所有1≤n≤a-1的整数a,有n(a-1)moda=1;该定理的逆否命题也成立,即n(a-1)moda!=1,则n为合数。但是如果a是素数,就不一定成立了,比如当n=4,a=15时,4^14mod15=1,但是4不是素数而是合数。
- Fermat素性测试:算法Fermat(n,t),其中n>2为奇数,t为测试次数。
1)对i从1到t做如下循环:
- 随机选择m,1<m<n-1;
- 计算d=gcd(m,n),如果d>1,则返回“合数”,否则反之;
- 计算r≡m^(n-1)(modn);
- 若r≠1,则返回“合数”。
2)返回“素数”。
算法主要应用了费马小定理,但m^(p-1)≡1(modp)仅是素数的必要条件。
上述算法将一个合数判断为素数的出错概率为1/2^t,但是返回合数的判定总是对的。只要增加测试次数t,就可以把出错概率降至趋近于0。
- Lehmam素性测试
1)对i从1到t做如下循环:
- 选择一个小于n的随机数a;
- 计算a^((n-1)/2)modn;
- 如果a^((n-1)/2)≠1或-1,那么返回合数。(n肯定不是素数)
2)返回素数。(n不是素数的可能性至多是50%)
算法主要运用了上面提到的第一条定理,2是素数且是n-1的素因子,在这里代替了q。
- Solovay-Strassen素性测试
1)对i从1到t做如下循环:
- 选择一个小于n的随机数a;
- 计算j≡a^((n-1)/2)modn;
- 如果j≠1或-1,则返回n不是素数;
- 计算Jacobi符号J(a,n)=(a/n);
- 如果j≠(a/n),返回n不是素数。
2)返回n是素数
算法中的步骤3同样使用了第一条定理判断出合数。而后又用素数性质加强了判断,所以这一测试准确度更高。
三、实验方法和步骤(或程序代码或操作流程)
(1)RSA编码实验
运行代码RSA.py:
在系统中打开文档进行代码的查看,在Linux系统命令行中输入vimcryptography/RSA/RSA.py,系统显示出来代码:
#!/usr/bin/env python
#-*-coding: utf-8-*-
import math
def isPrime(number):
i=2
sqrtNumber=int( math. sqrt(number))
for i in range( 2, sqrtNumber+1):
if number%i=0:
return False
i=i+1
return True
if
name_-"_main_":
print"*"*77
Flag =False
while Flag=False
p = int( raw_input( "Please input a prime(P):"))
Flag=isPrime(p)
if Flag=False
print "What you input is not a prime!"
print "The P is:", p
Flag =False
while Flag=False
q = int( raw_input( "Please input a prime(Q):"))
ifp=q
continue
Flag =isPrime(q)
if Flag=False
print "What you input is not a prime!"
print "The Q is:",q)
while Flag =False
e =int(raw_input( "Please input a number(E):"))
if (e<1 or e>t):
continue
d=0
while (((e*d)%t)!=1):
d+=1
Flag =True
print "The E is: ", e
print "The D is: ", d
print "The Public Key(E, N) is:",e, n
print "The Private Key(D, N) is:", d, n
print "*"*77
Flag =False
while Flag =False:
plainText =int(raw_input("Please input a plaintext:"))
if (plainText < n):
Flag =True
print "The plaintext is: ", plainText
print "Encrypt"+","*7
cipherText =(plainText**e)%n
print "cipherText is: ", cipherText
print "Decrypt"+","*7
plain =(cipherText**d)%n
print "The plain is: ", plain
print "*"*77
if plainText =plain:
print "RSA Test success, "
else
print "RSA Test unsuccess!")
查看完毕后,输入:q退出查看,之后对这段代码进行验证,输入以下代码查看到目录下有一个RSA.py文件。
cd/root/cryptography/RSA/ls
执行RSA.py来验证加密过程。
(2)素性测试编码实验
登录系统后,查看到目录"/root/cryptography/"下有个"zhishucs.py"文件。
查看该文件的内容:
执行zhishucs.py,判断给定的数字是否为素数。
四、实验过程原始记录(测试数据、图表截图、计算等)
(1)RSA编码实验测试数据
测试数据为:11,17,13,180 得到加密后的密文为130
测试数据为13 29 17 250 得到加密后的密文为113
(2)素性检测实验数据
- 16 检测结果为非素数
17 检测结果为素数
331 检测结果为素数
五、实验小结
- 实验中遇到的问题及解决方式
- 现象:在输入素数 P 和 Q 时,系统提示 “输入非素数”,但实际输入的数字(如 11、17)应为素数,导致程序反复要求重新输入。
- 原因:根据实验文档描述,代码中素数判断函数isPrime的逻辑可能存在漏洞,例如未正确处理边界值(如输入 1 或 2 时的判断),或循环条件错误导致漏检因子。
- 解决方式:根据提示输入素数或非素数
- 实验体会和收获
- 知识落地:通过代码运行直观理解 RSA 密钥生成与加解密流程,验证了欧拉函数、模逆元的数学关系。
- 算法局限:试除法不适用于大素数判断,认识到概率素性测试的必要性;RSA 效率受大数运算制约,需结合实际场景选择算法。
- 编程细节:调试中发现边界条件处理和模运算的重要性,提升了代码逻辑严谨性。