第一次尝试发博客,格式可能不太清楚怎么调整,以后再尝试调整,这次先这样发
实验摘要: 实验要求:在截获的加密21条报文信息中破解其明文信息,破解其明文信息,如果可以,破解参数信息,包括p,q,d的破解。 实验目的:在通过实验学习RSA的原理,以及在其加密方法和参数不当的条件下实现对密文的破解或对参数的破解,学习对RSA的攻击的几种方法。 |
实验题目:RSA加密体制破译(RSA大礼包) 题目内容: 有人制作了一个RSA加解密软件(采用的RSA体制的参数特点描述见密码学背景部分)。已知该软件发送某个明文的所有参数和加密过程的全部数据(加密文件案例详见附件3-1)。Alice使用该软件发送了一个通关密语,且所有加密数据已经被截获,请问能否仅从加密数据恢复该通关密语及RSA体制参数?如果能请给出原文和参数,如不能请给出已恢复部分并说明剩余部分不能恢复的理由?
RSA背景:参数:两个素数p,q,模数N=pq,加密指数e和解密指数d,加密 ,解密
题目中帧的填充格式:1024bits模数N||1024bits指数e||1024bits密文c
在RSA加密系统中,存在一些不正当的使用RSA,导致密码系统不安全,对RSA安全性产生产生威胁,如低指数,共模等等。使RSA可能遭受一些攻击,包括:费马分解法,Pollard p-1分解法,低加密指数攻击,公共模数攻击,因数碰撞攻击等
|
实验内容: (1)读入报文并简要分析 读入21条Frame报文,并分离出每个报文的n,e,c信息,分别存入三个列表中 如图所示,读入了每个报文的n,e,c信息,并转换为十进制存入到三个列表中,其中m:帧序列,n:模数序列,e:指数序列,c:密文序列。 尝试输出所有报文的加密指数e和模数m
|
如上图所示,简单分析加密指数e和模数N,由于Frame0与Frame4模数相同,可能存在共模攻击。
(2)共模攻击 破译原理:在RSA加密的多条帧中,若两帧使用了相同的模数,不同且互素的指数加密相同的明文,则会受到共模攻击在题目中也就是Frame0和Frame4
共模攻击过程: ,则若 ,由扩展欧几里得算法,存在 , 则存在 ,实现了对明文的破解 以下为破解结果 破解结果:成功破解Frame0,Frame4,明文为My secre (3)Fermat分解法 破译原理:对于模数n=pq,若两素数pq的值相差不大,可以通过费马分解法直接求解p,q,进而计算出fai(n)=n-q-p+1,从而恢复出解密私钥d,de=1(mod fai(n)),从而实现了对参数的破解和明文的破解。在题目中也就是Frame10,Frame14 Fermat分解过程: 若pq相差不大,则考虑 ,若p,q的值相差不大,则后一项的p-q的值很小,对于整个大整数来说可以近似为0,此时 ,可以不断尝试,从而实现分解出p+q |
分解方法: 考虑令a的初始值为n开方的整数值,在循环中每次使a的值加1,令b的值为 ,不断循环直到 ,说明此时 为一个完全平方数,说明a此时的值为 ,b的值为 ,循环结束,此时p=a+b,q=a-b,可以恢复出fai(n)=N-p-q+1,从而计算出私钥d 以下为破解结果: Frame10: Frame14:(这个帧花费时间有点久) 成功破解Frame10,Frame14, Frame10:will get Frame14:you fro (4)因数碰撞法 破译原理:在RSA加密系统中,若参数选取不当,多条报文选取选取到了相同的p,q,那么会出现 ,则由欧几里得算法, ,再计算n/p即可得到参数q,计算出fai(n)=N-p-q+1,计算出私钥d,在题目中为Frame1,Frame18 破解结果: 经过遍历,发现Frame1与Frame18的最大公因数不为1,则获得因子p,再计算因子q,即可恢复出私钥,破译明文 |
成功破解Frame1,Frame18, Frame1 :. Imagin Frame18:m A to B
(5)pollard p-1 分解法 破解原理:若所选取的素数p或素数q不为强素数,即p-1或q-1没有大素数因子时,可能存在pollard p-1 分解法实现对n的因子分解,计算出p,q,从而算出私钥d,破解明文。使用这种方法可以破译Frame 2 , Frame 6 , Frame 19 Pollard p-1 分解法: 对于一个想求解n的分解时,可以寻找一个整数z,z与n不互质,则gcd(z,n)为n的一个因子 设x=1mod(p),则p|gcd(x-1,n),根据Fermat小定理 2 ^ (p-1) = 1 (mod p) ,可以寻找p-1的一个倍数来构造此项。 由于p-1的因子都很小,对于所有素因子 q|p-1, q<=B ,可以得到 (p-1)|B!,此时2^(B!)=1mod(p),此时 , 与n的公因数为p,实现了对n的因子分解。 破解结果
|
成功分解出Frame2,Frame6,Frame19的因子
(6)低加密指数广播攻击 在RSA加密中,如果使用的n很大,e很小的加密指数,加密同一个密文m,n不同,那么会出现 ,应用中国剩余定理, 对此乘积结果开e次方,即可破解出明文m (此处曾经不理解此方法,因为如果后式可以开e次方,前面的式子为什么不可以直接开e次方呢?两个都是开方困难问题,而且此方法为什么只有低指数才可以用?经过后来仔细思考,和曾经查看的资料,才分析明白,因为e加密指数够小,那么 ,则 的值不会减小,即 是和m^e直接相等的,所以可以直接开e次方破解出m的值) 破解结果: 成功破解了Frame 3,8,12,16,20,其中明文为t is a f (7)其它 由于已知明文长度约为150位左右,模数长度约为300位左右,曾考虑尝试从模数n的10^150,到10^180倍数,暴力分解e=3的帧结果,但是破解时间太长,基本不能完成,于是放弃了这种方法。 到这里,已经成功破解了14个帧,包括 |
破解Frame情况 共模攻击:Frame0,Frame4 Fermat分解:Frame10,Frame14 破解模数 因数碰撞:Frame1,Frame18 破解模数 pollard p-1 分解法:Frame2,Frame6,Frame19 破解模数 低指数加密广播攻击:Frame 3,Frame 8,Frame 12,Frame 16,Frame 20 剩余未破解帧Frame5 Frame7 Frame9 Frame11 Frame13 Frame15 Frame17(暂未找到合适的破解方法, 筛选掉重复Frame:已经求解出包括明文:My secre will get . Imagin m A to B That is "Logic instein. t is a f you fro
查询资料,发现e=3的Frame存在Coppersmith attack,但是具体内容和代码没看懂,使用Coppersmith attack可以破解Frame7,Frame11,Frame15 明文分别为amous sa ying of Abert E 剩余的帧可以破解随机数发生器来破解帧 根据已破解的帧和查询资料,猜测最终的明文为: My secret is a famous saying of Albert Einstein. That is "Logic will get you from A to B. Imagination will take you everywhere
实验结果:成功破解帧Frame0,1,2,3,4,6,8,10,12,14,16,18,19,20,21 成功破解模数Frame1,2,6,10,14,18,19 最终的明文为:My secret is a famous saying of Albert Einstein. That is "Logic will get you from A to B. Imagination will take you everywhere.”
|
实验总结 总结:通过本次实验,我学习了RSA加密过程中,若参数选取不当,可能存在于RSA中的一些攻击,包括共模攻击,Fermat分解,因数碰撞,Pollard p-1 分解法,低指数加密广播攻击,通过查询相关资料和自己的分析,编写了python代码,并成功破解了很多帧,恢复出了明文 在查询资料后也了解了CopperSmith attack 和破解随机数发生器等其他方法,对RSA的安全应用和RSA的破解方法有了更多的了解 通过这次实验也学习了很多RSA的破解方法,也了解了对于密码学,我们最好的方法就是调标准库进行加密,不要自己尝试去实现RSA或轻易使用他人的算法,表面上安全的算法实际中可能存在很多的攻击。 在实验中也存在着一些自己的疑问,通过计算和分析,也解决了自己的疑问。在低加密指数广播攻击中 ,应用中国剩余定理, 对此乘积结果开e次方,即可破解出明文m 此处曾经不理解此方法,因为如果后式可以开e次方,前面的式子为什么不可以直接开e次方呢?两个都是开指数的困难问题,而且此方法为什么只有低指数才可以用?经过后来仔细思考,和曾经查看的资料,才分析明白,因为e加密指数够小,那么 ,则 的值不会减小,即 是和m^e直接相等的,所以可以直接开e次方破解出m的值 可以说出现这样的疑问很大的原因是对数学原理的不理解,也存在对RSA没有实际运算,只停留在表面理解,产生了这个错误。以后应当提高动手能力,积极思考。
|
参考文献(包括参考的书籍,论文,URL等,很重要) |
(1)读入报文并简要分析
def read_frame(m,n,e,c):
filename=["Frame"+str(i) for i in range(21)]
for i in range(21):
fd = open(filename[i],"r")
m.append(fd.read())
fd.close()
for i in m:
n.append(i[0:256])
e.append(i[256:512])
c.append(i[512:768])
输出帧
def print_array(a):
for i in range(len(a)):
print("frame{}:".format(str(i)),+a[i])
def print_frame(n,e,c):
for i in range(len(n)):
print("frame{}:".format(str(i)))
print(" n=",n[i])
print(" e=",e[i])
print(" c=",c[i])
(2)共模攻击
def common_modulus(c1,c2,e1,e2,n):
print("e0与e4的最大公因数为",gmpy2.gcd(e1,e2))
a0,a1,a2 = gmpy2.gcdext(e1,e2) #a1 * e1 + a2 * e2 = 1
meg=(pow(c1,a1,n)*pow(c2,a2,n))%n
print("meg:",hex(meg))
meg_text=hex(meg)[-16:]
print("meg_text:",str(base64.b16decode(meg_text.upper()),encoding='utf-8'))
费马分解法
def Farmat_d(n,e,c):
for i in range(21):
print("frame"+str(i))
Farmat_de(n[i])
p,q=Farmat_de(n[10])
fai_n=n[10]-p-q+1
d=gmpy2.invert(e[10],fai_n)
meg=(pow(c[10],d,n[10]))
print("meg:",hex(meg))
meg_text=hex(meg)[-16:]
print("meg_text:",str(base64.b16decode(meg_text.upper()),encoding='utf-8'))
def Farmat_de(n):
f=False
a= math.isqrt(n)
c=a*a-n
b=0
count = 0
while count<10000:
if(b*b==a*a-n):
f=True
break
a=a+1
b = math.isqrt(a*a-n) # int(b2**0.5)
count += 1
if(f):
p=a+b
q=a-b
print("p=",p)
print("q=",q)
return p,q
else:
print("cannot decomposition")
因数碰撞法
def factor_collisions(n,e,c):
# for i in range(21):
# for j in range(i+1,21):
# print("第{}帧与第{}帧最大公因数为{}".format(str(i),str(j),str(gmpy2.gcd(n[i],n[j]))))
p=gmpy2.gcd(n[1],n[18])
q1=n[1]//p
q18=n[18]//p
fai_n1=n[1]-p-q1+1
fai_n18=n[18]-p-q18+1
d1=gmpy2.invert(e[1],fai_n1)
d18=gmpy2.invert(e[18],fai_n18)
meg1=(pow(c[1],d1,n[1]))
print("meg1:",hex(meg1))
meg_text1=hex(meg1)[-16:]
print("meg_text1:",str(base64.b16decode(meg_text1.upper()),encoding='utf-8'))
meg18=(pow(c[18],d18,n[18]))
print("meg18:",hex(meg18))
meg_text18=hex(meg18)[-16:]
print("meg_text18:",str(base64.b16decode(meg_text18.upper()),encoding='utf-8'))
Pollard p-1 分解法
def pollard_p_1(n,e,c):
max=300000
a=2
result_t=[]
for j in range(21):
for i in range(1,max):
a=pow(a,i,n[j])
if(gmpy2.gcd(a-1,n[j])!=1):
#print("p={}".format(gmpy2.gcd(a-1,n[j])))
break
if(i==max-1):
print("frame{} cannot break".format(j))
else:
print("frame{} p={}".format(j,gmpy2.gcd(a-1,n[j])))
result_t.append(gmpy2.gcd(a-1,n[j]))
p,q,fai_n,d,n_t,e_t,c_t,meg,meg_text=[],[],[],[],[],[],[],[],[]
n_t.append(n[2])
e_t.append(e[2])
c_t.append(c[2])
n_t.append(n[6])
e_t.append(e[6])
c_t.append(c[6])
n_t.append(n[19])
e_t.append(e[19])
c_t.append(c[19])
for i in range(3):
p.append(result_t[i])
q.append(n_t[i]//p[i])
fai_n.append(n_t[i]-p[i]-q[i]+1)
d.append(gmpy2.invert(e_t[i],fai_n[i]))
meg.append(pow(c_t[i],d[i],n_t[i]))
meg_text.append(hex(meg[i])[-16:])
print("Frame 2 :",end="")
print(str(base64.b16decode(meg_text[0].upper()),encoding='utf-8'))
print("Frame 6 :",end="")
print(str(base64.b16decode(meg_text[1].upper()),encoding='utf-8'))
print("Frame 19 :",end="")
print(str(base64.b16decode(meg_text[2].upper()),encoding='utf-8'))
低加密指数广播攻击
def is_coprime(m):
k=len(m)
flag=False
for i in range(k):
for j in range(i+1,k):
#print("i={},j={},k={}".format(i,j,k))
if(gmpy2.gcd(m[i],m[j])==1):
#print("m{}与m{}互素".format(i,j))
flag=True
else:
flag=False
break
if(flag==False):
break
if(flag):
print("m之间两两互素,可以直接使用中国剩余定理")
else:
print("m之间不是两两互素,不能直接使用中国剩余定理")
return flag
def Chinese_remain(a,m):
M,inv_M,x=[],[],[]
len_m=len(m)
result=0
#m_all=numpy.prod(m)
m_all=1
for i in range(len_m):
m_all=m_all*m[i]
for i in range(len_m):
M.append(m_all//m[i])
for i in range(len_m):
#print("i=",i)
#print(type(M[i]))
#print(gmpy2.invert(M[i],m[i]))
# print(f)
inv_M.append(gmpy2.invert(M[i],m[i]))
for i in range(len_m):
x.append((a[i]*M[i]*inv_M[i])%m_all)
#print(x)
for i in range(len_m):
result=(result+x[i])%m_all
return result
def low_e_attack(n,e,c):
#Chinese_remain
#print(e)
j=0
x=0
n_t,e_t,c_t=[],[],[]
for i in range(21):
if(e[i]==5):
e_t.append(e[i])
n_t.append(n[i])
c_t.append(c[i])
if(is_coprime(n_t)):
x=Chinese_remain(c_t,n_t)
print("同余方程的解为x={}".format(x))
m=gmpy2.iroot(x,5)
#print("m={}".format(m[0]))
m=hex(m[0])[-16:]
print("Frame 3:",end="")
print(str(base64.b16decode(m.upper()),encoding='utf-8'))
print("Frame 8:",end="")
print(str(base64.b16decode(m.upper()),encoding='utf-8'))
print("Frame 12:",end="")
print(str(base64.b16decode(m.upper()),encoding='utf-8'))
print("Frame 16:",end="")
print(str(base64.b16decode(m.upper()),encoding='utf-8'))
print("Frame 20:",end="")
print(str(base64.b16decode(m.upper()),encoding='utf-8'))