先理解以下维纳攻击的原理
攻击条件:e过大或过小
在e过大或过小的情况下,可使用算法从e中快速推断出d的值
模数N=pq ,其中q < p < 2p,若d<时,给定公钥(N,e),且
其中G=
那么就可以有效的得到私钥d
这里与常见得RSA加密不同得是使用了,并不是我们所熟知的
。这两个玩意相差了整数G,其实是差不多的
使用原理
维纳攻击(wiener attack)是依靠连分数进行的攻击方式,使用与非常接近某一个值时,求一个比例关系,通过改比例关系再来反推关键信息就简单多了。
这种攻击方式对于解密指数d很小时有很好的效果,一般的用法是通过如下方式:
得到
即
这种情况下且
非常大,也就是说
所以有 ==》
也就是说
与
非常接近,而
又是已知量
对于进行连分数展开,得到一串分数得分母很可能就是d
公式推导
设
其中
因为
令,
带入上式得:
解题脚本及出题脚本
出题脚本
#出题脚本
import libnum
import random
import uuid
# 生成随机素数
p = libnum.generate_prime(512)
q = libnum.generate_prime(512)
m = 'flag{'+str(uuid.uuid4())+'}'
print('m = '+m)
#"flag{20d6e2da95dcc1fa5f5432a436c4be18}"
# 字符串转数字
m = libnum.s2n(m)
n = p * q
phi_n = (p - 1) * (q - 1)
# 计算d
while True:
nbits = 1024
d = random.getrandbits(nbits // 4)
if (libnum.gcd(d, phi_n) == 1 and 36 * pow(d, 4) < n):
break
# 计算e
e = libnum.invmod(d, phi_n)
c = pow(m, e, n)
print("n=", n)
print("e=", e)
print("c=", c)
# n = 113881698992379349039968368927979997900777221951663104697020683691495129639829918739755194174063944178083527489820939138302751895652076620380510013941997706327553964127612610209509889011613768847759318892303231846117914554931459295347697888260576901354448014917692680573408654658384481284699735788978230690197
# e = 39068960413447607023613035707248214114819409621234801785480423979473767995171860917209502861408393208940683687475760366491413173744775811644295874981290403938714121977201901942939425294427737703229098649131737380098596135730392902019429964095866394165971291108245774407908011073271822915371753470010435225545
# c = 32897925577913728659288168937025744709859960639901500169867896018406263110205704273203287172003057450591000201857719871686024077615520906540631374442504017489026298422189715372129838501090730593164075113452055617571409044743698645392909829425374093273187125709095368164744188182156849031225036001381531504057
exp1
#解题脚本
import gmpy2
import libnum
def continuedFra(x, y):
"""计算连分数
:param x: 分子
:param y: 分母
:return: 连分数列表
"""
cf = []
while y:
cf.append(x // y)
x, y = y, x % y
return cf
def gradualFra(cf):
"""计算传入列表最后的渐进分数
:param cf: 连分数列表
:return: 该列表最后的渐近分数
"""
numerator = 0
denominator = 1
for x in cf[::-1]:
# 这里的渐进分数分子分母要分开
numerator, denominator = denominator, x * denominator + numerator
return numerator, denominator
def solve_pq(a, b, c):
"""使用韦达定理解出pq,x^2−(p+q)∗x+pq=0
:param a:x^2的系数
:param b:x的系数
:param c:pq
:return:p,q
"""
par = gmpy2.isqrt(b * b - 4 * a * c)
return (-b + par) // (2 * a), (-b - par) // (2 * a)
def getGradualFra(cf):
"""计算列表所有的渐近分数
:param cf: 连分数列表
:return: 该列表所有的渐近分数
"""
gf = []
for i in range(1, len(cf) + 1):
gf.append(gradualFra(cf[:i]))
return gf
def wienerAttack(e, n):
"""
:param e:
:param n:
:return: 私钥d
"""
cf = continuedFra(e, n)
gf = getGradualFra(cf)
for d, k in gf:
if k == 0: continue
if (e * d - 1) % k != 0:
continue
phi = (e * d - 1) // k
p, q = solve_pq(1, n - phi + 1, n)
if p * q == n:
return d
n =
e =
c =
d = wienerAttack(e, n)
print(d)
m = pow(c, d, n)
print(libnum.n2s(m).decode())
把n,e,c补上就行
exp2
或者网上的脚本
import libnum
from RSAwienerHacker import *
n = 113881698992379349039968368927979997900777221951663104697020683691495129639829918739755194174063944178083527489820939138302751895652076620380510013941997706327553964127612610209509889011613768847759318892303231846117914554931459295347697888260576901354448014917692680573408654658384481284699735788978230690197
e = 39068960413447607023613035707248214114819409621234801785480423979473767995171860917209502861408393208940683687475760366491413173744775811644295874981290403938714121977201901942939425294427737703229098649131737380098596135730392902019429964095866394165971291108245774407908011073271822915371753470010435225545
c = 32897925577913728659288168937025744709859960639901500169867896018406263110205704273203287172003057450591000201857719871686024077615520906540631374442504017489026298422189715372129838501090730593164075113452055617571409044743698645392909829425374093273187125709095368164744188182156849031225036001381531504057
d = hack_RSA(e,n)
m = pow(c,d,n)
print(libnum.n2s(m).decode())
维纳攻击三素数
该脚本需要在sagemath9.2上运行
def wiener(e, n):
m = 12345
c = pow(m, e, n)
q0 = 1
list1 = continued_fraction(Integer(e) / Integer(n))
conv = list1.convergents()
for i in conv:
k = i.numerator()
q1 = i.denominator()
for r in range(20):
for s in range(20):
d = r * q1 + s * q0
m1 = pow(c, d, n)
if m1 == m:
return d
q0 = q1
n = 1051380872316823433883636764584789285333736434524933570584976014001214015195582230652890036553897972507709868668015209942849015953126067065245745528656185713975834472569979390688522786334308265267342203713851528468719085926942222541344057327637925939220941677328780957242592769934672272901444344368132925072596706265951382183962516395989020286284674233929275036820658314907868575906130423049124591076625494555958927499995127864266451094815485831694951169813864579090722449382301556276181043387840715294133205479396272801536638003449150191833236756230648343641542001617352347728075031395009393805016183916046647042759712436405458561551257959973189661621088021485676031370872948254252297718720969276447566410825701049555286286171854286210170310303122812022424180992567945938220732070586725895910160295026510702457152084383868466740490026825254620849716745141621210206706738899418272128830937154184366826368016614460538955646609
# p*r*q
e = 401736266490324552517217032225246450087649254466718075727966287757972026925163477893539047721223580215545684494442007744774900721388024851291175127388784748482162997733029569314385345465782341732251402815344448962923207292061517106665954257137567332560956608813590130048988674456360832136718517222056109287921167927946304453828334895683526480626294649396329610693963520850896266343295069273447109718037817671775114733403154525393468056590686142168244467303584451585069101584798590889529292526446832857035880715351476044875846461493125136227486230514153648388383654116769560511713813660841282782474519612727725715364718394717990336084691567425849567195154254431858216101902309862385524999911892987920197370958210721993073768994565808825036701082088990540391431078200077738350023726344360396487614841476654096629864029557926380538230445278881935443675347998379733770494280427033480933837349115145552011734379818969027809471037
d=wiener(e, n)
print(d)