维纳攻击及变形题

先理解以下维纳攻击的原理

攻击条件:e过大或过小

在e过大或过小的情况下,可使用算法从e中快速推断出d的值

模数N=pq ,其中q < p < 2p,若d<\frac{1}{3}{}\times N^{\frac{1}{4}}时,给定公钥(N,e),且ed\equiv 1 mod\lambda(N)

\lambda (N)=lcm(p-1,q-1)=\frac{(q-1)(p-1)}{G}=\varphi (n)

其中G=gcd(p-1,q-1)

那么就可以有效的得到私钥d

这里与常见得RSA加密不同得是使用了\lambda (N),并不是我们所熟知的\varphi (n)。这两个玩意相差了整数G,其实是差不多的

使用原理

维纳攻击(wiener attack)是依靠连分数进行的攻击方式,使用与非常接近某一个值时,求一个比例关系,通过改比例关系再来反推关键信息就简单多了。

这种攻击方式对于解密指数d很小时有很好的效果,一般的用法是通过如下方式:

ed\, \, mod \, \, \varphi (n) =1得到ed = k\varphi (n)+1\frac{e}{\varphi (n)}-\frac{k}{d}=\frac{1}{\varphi (n)d}

这种情况下\varphi (n)\approx n,\varphi (n)非常大,也就是说\varphi (n)\approx 0

所以有\frac{e}{\varphi (n)}-\frac{k}{d}=\frac{1}{\varphi (n)d}  ==》\frac{e}{n}-\frac{k}{d}=\varphi (n)也就是说\frac{k}{d}\frac{e}{n}非常接近,而\frac{e}{n}又是已知量

对于\frac{e}{n}进行连分数展开,得到一串分数得分母很可能就是d

公式推导

\lambda(n)=lcm(p-1,q-1)=\tfrac{(p-1)(q-1)}{G}=\frac{\varphi (n)}{G}

其中G=gcd(p-1,q-1)

因为ed=k\varphi (n)+1=\frac{k}{G}(p-1)(q-1)+1

k=\frac{K}{gcd(K,G)}g=\frac{G}{gcd(K,G)}带入上式得:

ed=\frac{k}{g}(p-1)(q-1)+1=\frac{k}{g}\varphi (n)+1

解题脚本及出题脚本

出题脚本

#出题脚本
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

或者网上的脚本

pablocelayes/rsa-wiener-attack: A Python implementation of the Wiener attack on RSA public-key encryption scheme.

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值