RSA攻击总结
RSA攻击基本原理及代码实现总结
1. n分解攻击
1. 原理
1. 基本字符含义
m:明文
c:密文
d:私钥
n:模数
phi:n的欧拉函数值
e:加密钥
yin:n分解得到的所有因数
2. 攻击原理描述
已知常规RSA算法原理可由以下五个式子表达
而非常规RSA算法原理与常规RSA算法原理仅(4)(5)式不同
(4)式改为
而(5)式改为
由上述式子可得到当n可以被分解时,很容易得到p,q,r,s,p',q',r',s'的值
可以通过(4)计算得到φ(n)
进而求e在模φ(n)条件下的模逆d
即可获取明文
那么如合通过实际可行的办法分解n
- 通过python库文件factordb进行分解(实际上依托于factordb.com的网站存储已知因数的分解)
- 通过yafu小型软件进行分解(针对p,q之间差距过大或过小的n值)
3. 适用条件
- 当n可以通过上述两种方式分解时
2.代码
1. 实现
from Crypto.Util.number import long_to_bytes
from factordb.factordb import FactorDB
from functools import reduce
from gmpy2 import invert
from re import findall
from os import popen
#用于RSA的n分解攻击
#程序会通过上述两种方式分解因式
def RSA_attack_easy(n,e=-1,c=-1,yin=[]):
with open('data.txt','wb+') as f:
f.write(f'n={n}'.encode())
if yin == []:
f = FactorDB(n)
try :
f.connect()
sign = f.get_status()
if sign == 'FF':
yin = sorted(list(set(f.get_factor_list())))
elif sign == 'CF':
yin = list(f.get_factor_list())
for i in yin:
n //= i
with open('data.txt','wb+') as f:
f.write(f'{n}\n'.encode())
result = popen(r'D:\学习相关\密码学相关\密码学工具\yafu-1.34\yafu-x64 "factor(@)" -batchfile data.txt','r')
str_yin = findall(r'P\d+ = (\d)+\n',result.read())
for x in str_yin:
yin.append(int(x))
yin = sorted(list(set(yin)))
else :
with open('data.txt','wb+') as f:
f.write(f'{n}\n'.encode())
result = popen(r'D:\学习相关\密码学相关\密码学工具\yafu-1.34\yafu-x64 "factor(@)" -batchfile data.txt','r')
str_yin = findall(r'P\d+ = (\d)+\n',result.read())
yin = [int(x) for x in str_yin]
if yin == []:
return 'n不可分解'
except:
return 'n不可分解'
yu = n//reduce(lambda x, y: x*y, yin)
phi = 1
for i in yin:
phi *= (i-1)
phi *= yu
if e != -1:
e %= phi
d = invert(e,phi)
if c!=-1:
ci = long_to_bytes(pow(c,d,n))
return(ci,c,f'd:{d}')
else :
return f'd:{d}'
else :
return(f'因数有:{yin}',f'欧拉系数:{phi}')
2. 代码说明
1. 返回说明
- 当函数仅输入参数n时,函数返回n的所有因数和phi
- 当函数仅输入参数n,e时,函数返回d
- 当函数仅输入参数n,e,c时,返回明文m的字符值和数值并返回d
- 当函数仅输入参数n,e,c,yin时,返回明文m的字符值和数值并返回d
- 无论输入参数是什么,当n不能通过上述两种方式分解时,返回‘n不可分解’
2. 输入说明
- n,e,c均为整数
- yin为整数列表
2. 共模攻击
1. 原理
1. 基本字符含义
m:明文
c:密文
d:私钥
n:模数
phi:n的欧拉函数值
e:加密钥整数集合或列表
yin:n分解得到的所有因数的集合或列表
\(e_1\):加密钥举例1
\(c_1\):用加密钥举例1加密m得到的密文
\(e_2\):加密钥举例2
\(c_2\):用加密钥举例1加密m得到的密文
2. 攻击原理描述
假设e1,e2互质,即:
即存在:
由(2)式与(4)式得:
由此可得,当求出\(s_1\)和\(s_2\)时,即可解得获得明文
如何求\(s_1\)与\(s_2\)
答案是:扩展欧几里得算法
3. 适用条件
- 当同份明文被互质的加密指数加密时
2. 代码
1. 实现
from Crypto.Util.number import long_to_bytes,bytes_to_long
from gmpy2 import invert
from egcd import egcd
#RSA共模攻击
def RSA_mo(n,e1,c1,e2,c2):
'''#RSA共模攻击'''
s,s1,s2 = egcd(e1,e2)
if s1<0:
s1,s2 = s2,s1
e1,e2 = e2,e1
c1,c2 = c2,c1
if s!=1:
return '不能进行互素的共模攻击'
c2 = invert(c2,n)
m = (pow(c1,s1,n)*pow(c2,-s2,n))%n
return m,long_to_bytes(m)
2. 代码说明
1. 输入说明
- 参数n,e1,e2,c1,c2都要输入
- e1代表\(e_1\)参数以此类推
2. 输出说明
返回m的数值与字符值
3. 低解密指数攻击(维纳攻击)
1. 原理
1. 基本字符含义
m:明文
c:密文
n:模数
d:私钥
phi:n的欧拉函数值
e:加密钥
2. 攻击原理描述
理论基础(勒让德定理):当e过大或过小时,\(\dfrac e n\)的连分数展开会逐渐趋向于\(\dfrac k d\)
原文:Let $\alpha \in \mathbb{Q} $ and \(c,d \in \mathbb{Z}\) satisfy
\[|\alpha - \dfrac{c}{d}| < \dfrac{1}{2d^2} \]Then c/d, in lowest terms, is one of the convergents in the continued fraction expansion of \(\alpha\).
由(2)两边同时除\(d \times phi\)可得:
虽然在此式子中无法得知d和k的具体值,但是由于连分数逼近原理可以得到两者之间的比值所以(p+q)是可以得到相对接近的值的
再通过构造方程
韦达定理: \(x_1 + x_2 = (p+q) , ~~ x_1 \times x_2 = n\)
求解方程即可得到p,q的值
3. 适用条件
- 当e极大或极小时
2. 代码
1. 实现
c = continued_fraction(e/n) #直接输出e/n的连分数展开的数组
alist = c.convergents() #求e/n的连分数逼近
from Crypto.Util.number import long_to_bytes
from gmpy2 import invert,isqrt
from libnum import n2s,s2n
#低解密指数攻击
#条件:d<pow(n,0.25)/3
def RSA_wiener (n,e,c):
#连分数逼近,并列出逼近过程中的分子与分母
def lian_fen(x,y):
res = []
while y:
res.append(x//y)
x,y = y,x%y
resu = []
for j in range(len(res)):
a,b = 1,0
for i in res[j::-1]:
b,a = a,a*i+b
resu.append((a,b))
if resu[0] == (0,1):
resu.remove((0,1))
return resu[:-1]
lianfen = lian_fen(e,n)
def get_pq(a,b,c):
par = isqrt((n-phi+1)**2-4*n)
x1,x2 = (-b + par) // (2 * a), (-b - par) // (2 * a)
return x1,x2
for (k,d) in lianfen:
phi = (e*d-1)//k
p,q = get_pq(1,n-phi+1,n)
if p*q == n:
p,q = abs(int(p)),abs(int(q))
d = invert(e,(p-1)*(q-1))
break
return m,long_to_bytes(pow(c,d,n))
2. 代码说明
1. 输出说明
返回m的数值与字符值
4. dp泄露攻击
1. 原理
1. 基本字符含义
m:明文
c:密文
n:模数
d:私钥
phi:n的欧拉函数值
dp:d对(p-1)取模
2. 攻击原理描述
当dp泄露时,n可分解成的素数种类大大降低,变得“可预测”
\(⇒dp \times e \equiv d \times e \mod(p-1)\)
\(⇒d \times e = k \times (p-1) +dp \times e\)
\(d \times e \equiv 1 \mod(p-1) \times(q-1)\)
\(⇒k\times(p-1) + dp \times e \equiv 1 \mod (p-1)\times(q-1)\)
\(⇒k \times (p-1) +dp \times e = k_1 \times (p-1) \times (q-1) + 1\)
\(⇒dp \times e = (k_1\times q + k_1 - k) \times (p-1) + 1\)
设:$X = (k_1\times q + k_1 - k) $
$⇒dp \times e = X \times (p-1) +1 $
\(dp < (p-1)\)
\(⇒e>X\)
\(X \in [0,e]\)
遍历[0,e]即可找出X,进而通过上述公式求得p,从而达到n分解的目的
2. 代码
1. 实现
from Crypto.Util.number import long_to_bytes
from gmpy2 import invert
from factordb.factordb import FactorDB
#dp泄露攻击
def RSA_dp_reveal(dp,e,n,c):
for X in range(2,e):
if (dp*e-1)%X==0:
p = (dp*e-1)//X + 1
if n%p == 0:
q = n // p
break
phi = (p-1)*(q-1)
d = invert(e,phi)
ci = long_to_bytes(pow(c,d,n))
return ci
2. 代码说明
1. 输出说明
返回m的数值与字符值
5. dp,dq泄露
1. 原理
1. 基本字符含义
m:明文
c:密文
n:模数
d:私钥
phi:n的欧拉函数值
dp:d对(p-1)取模
dq:d对(q-1)取模
2. 条件
dp,dq,c,p,q且dp与dq互素,且\(p<q\)
3. 攻击原理描述
n未知,首先计算\(n = p \times q\)
又已知:
又设得\(m_1,m_2\):
又可得:
因为\(gcd(p,q)=1\),\(p<q\)所以:
还要注意得一个问题是p<q,如果不成立,则一定不存在\(p^{-1}\)
由\(c^d = m_1 + kp,k \equiv (m_2-m_1)p^{-1} \mod q\)可得:
将\(m\equiv c^d \mod n\)得:
由费马小定理\(c^{p-1} \equiv 1 (\mod p)\)可得:
同理得:
最后由(5)、(8)、(9)可计算得m
2. 代码
1. 实现
from gmpy2 import invert
from libnum import n2s
def dp_dq_RSA_attack(dp,dq,p,q,c):
if p>q:
p,q = q,p
dp,dq = dq,dp
n = p*q
m1 = pow(c,dp,p)
m2 = pow(c,dq,q)
inv_p = invert(p,q)
m = ((m2-m1)*inv_p%q*p+m1)%n
return int(m),n2s(int(m))
2. 代码说明
1. 输入说明
需要输入dp,dq,p,q,c
2. 输出说明
返回m的数值与字符值
6. 低加密指数攻击
1. 原理
1. 基本字符含义
m:明文
c:密文
n:模数
2. 条件
- 当加密指数e非常小时
3. 攻击原理描述
已知:
当加密指数e非常小时,k也会非常小,通过暴力的方式,即可获得m,从而获得e
2. 代码
1. 实现
from gmpy2 import iroot
from libnum import n2s
def little_e_RSA_attack(e,n,c):
for k in range(1000000000):
if iroot(c+k*n,e)[1] == True:
return (n2s(int(iroot(c+k*n,e)[0])))
7. 低加密指数广播攻击
1. 原理
1. 基本字符含义
\(n_1,n_2,···,n_n\):不同的加密所使用的模数
\(c_1,c_2,···,c_n\):不同加密所获得的密文
2. 原理
已知:
根据中国剩余定理可求得\(m^e\)
可能题目中会存在模不互素,这时候就要用到模不互素的中国剩余定理
然后通过爆破的方式获取e
2. 代码
1. 实现
import re
from gmpy2 import gcd,invert
from libnum import n2s
def low_exponent_attack(e,text_n,text_c):
n_text = re.findall(r"(n\d)\s*=\s*(\d+)\s*\n",text_n)
c_text = re.findall(r"(c\d)\s*=\s*(\d+)\s*\n",text_c)
n_map = {a:int(b) for a,b in n_text}
c_map = {a:int(b) for a,b in c_text}
for i in n_map:
for j in n_map:
if i!=j:
p = gcd(n_map[i],n_map[j])
q = n_map[i]//p
d = invert(e,(p-1)*(q-1))
m = pow(c_map["c"+i[1:]],d,n_map[i])
return n2s(m)
2.代码说明
1. 输入说明
输入为 "n\d = \d+"正则形式的文本,由程序自动识别并录入
2. 输出说明
程序自动输出解密的明文
8. e和phi不互素
1. 原理
1. 基本字符含义
字符 | 含义 |
---|---|
phi,\(\phi(n)\) | n的欧拉函数 |
e | 加密指数 |
p,q | n的两个因数 |
2. 原理
寻找一个b使其满足如下条件
相当于变成了一个新的RSA解密
按照正常的RSA解密流程
然后尝试对\(m^b\)进行开根算法(对n肯定是开不了根的)
第一个方程可以解出b个m,第二个方程也可以解出b个m。
已知两个方程的解中肯定有为真正的解模p和模q的结果记为\(m_1,m_2\)
使用中国剩余定理解同余方程,共\(b^2\)个组合,可以获得\(B^2\)个m的值
筛选一下即可获得m的值
2. 代码
1. 实现
# sagemath
from libnum import n2s
def e_phi_not_coprime(p,q,e,c,hint:str):
n = p*q
phi = (p-1)*(q-1)
b = gcd(phi,e)
e_b = e//b
while gcd(phi,e_b)!=1:
b *= gcd(phi,e_b)
e_b //= gcd(phi,e_b)
d_b = inverse_mod(e_b,phi)
m_b = pow(c,d_b,n)
P.<m1> = PolynomialRing(Zmod(p))
P.<m2> = PolynomialRing(Zmod(q))
f1 = m1^(e//e_b) - m_b%p
f2 = m2^(e//e_b) - m_b%q
roots1 = {x[0] for x in f1.monic().roots()}
roots2 = {x[0] for x in f2.monic().roots()}
for m1 in roots1:
for m2 in roots2:
m = crt([int(m1),int(m2)],[int(p),int(q)])
if hint.encode() in n2s(int(m)):
return (n2s(int(m)))
2. 代码说明
- 输入说明:hint要求为str形式,且是最后flag一定含有的内容用于挑选
- 输出说明:直接输出合适的形式
9. p-1光滑
1. 原理
生成质数的算法不当会造成易遭受Pollard's p-1 method的分解攻击。
当p-1是可以分解为多个小质因数时,且已知其中最大的因数B
可知B和p-1满足以下等式:
根据费马定理可知
可知:
极易
2. 代码
# sagemath
from libnum import n2s
# 重写pow函数加快运算速度
def pow(m,e,n):
type = m % n
res = 1
while e > 0:
if e&1:
res = (res * type) % n
type = (type * type) % n
e >>= 1
return res
def Pollards_method(N,a=2,B):
p = gcd(pow(a,factorial(B),N)-1,N)
q = N//p
phi = (p-1)*(q-1)
d = inverse_mod(e,phi)
m = pow(c,d,N)
return n2s(int(m))
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?