crypto_solveit2022(rsa中coppersmith攻击应用)

今年遇到的另一道rsa题,知识点比较杂记录一下。

题目很简单,给出两段rsa加密逻辑:

from libnum import s2n
from gmpy2 import next_prime
from Crypto.Util.number import getPrime, getStrongPrime

flag = b'***************************'
m = s2n(flag)
data1 = getPrime(128)
data2 = getPrime(128)

if data1 > data2:
    data1, data2 = data2, data1

pad = data1 * data2
e = 65537
p = getStrongPrime(512)
q = next_prime(p ^ (1 << 512) - 1 ^ 1145141919810)
n = p * q
m = m ^ (pad**3)
c = pow(m, e, n)
print("c = {}".format(c))
print("n = {}".format(n))

'''
c = 4876198060325558549288995522100507087517821034108816602164382070749684285584225421889164875913824962554132279846256774271230741598793103772088831581334775807966395144586271639023739926023422461534946692758208303683848234357028505178292070426362296226890794270835780238370200672015289469862799153558118626538
n = 22496691787129427749959005524646018077441588595947356500541791402307996665819440265849843924260051516521718141146431339445253436586359746245186586849516881880135888115635970343512176471451755147483038942057104297542535022428306408447982927962678529654674038001433905787928883880082539446749721026403230355477
'''

*******************************
bound = 2**128
prec = 400
ring = RealField(prec)
data3 = ring(data1 / data2)

#data3 = 0.576745262648089166053295786066675247383735995449723064673392221201629992787992198615151331712300834922059228957126784067
*******************************

大概分析一下,p和q是512bit的大素数,明文先与pad**3进行异或以后rsa加密,所以本题关键的两个问题一个就是求解p和q,另一个就是求解pad。

首先求解pad想到的是应用连分数攻击,找到分子分母128bit的渐进分数逼近data3:

#sage exp
data3 = 0.576745262648089166053295786066675247383735995449723064673392221201629992787992198615151331712300834922059228957126784067

c = continued_fraction(data3)
print(c)

alist = c.convergents()
print(alist)

for i in alist:
    a = str(i).split('/')
    if len(a)>1 and gcd(int(a[0]),int(a[1])) == 1 and is_prime(int(a[0])) and is_prime(int(a[1])) and int(a[0]).bit_length()==128 and int(a[1]).bit_length()==128:
            print(a)

#['182219017730986958273958989689968387899', '315943674845875518476789636594922239111']

如此一来pad问题就解决了。接下来需要求p和q。先去factordb查了一波没查到结果,只能想办法硬算,近似算法具体算法参考以下这篇:

【zer0pts CTF 2022】 Anti-Fermat(p、q生成不当)_Paintrain的博客-CSDN博客

针对本题的话根据p+q\approx1<<512 

可以得到近似p=(iroot(pow(2,1024)-4*n,2)[0]+pow(2,512))//2+1145141919810

然后用coppersmith方法攻击p值的低位原理参考这篇:

【CTF RSA】Coppersmith攻击 - 简书

所以解密脚本为:

#sage exp
from Crypto.Util.number import *
import gmpy2
c = 4876198060325558549288995522100507087517821034108816602164382070749684285584225421889164875913824962554132279846256774271230741598793103772088831581334775807966395144586271639023739926023422461534946692758208303683848234357028505178292070426362296226890794270835780238370200672015289469862799153558118626538
n = 22496691787129427749959005524646018077441588595947356500541791402307996665819440265849843924260051516521718141146431339445253436586359746245186586849516881880135888115635970343512176471451755147483038942057104297542535022428306408447982927962678529654674038001433905787928883880082539446749721026403230355477
e=65537

#estimate p
px=(gmpy2.iroot(pow(2,1024)-4*n,2)[0]+pow(2,512))//2+1145141919810
print(px)
p=int(px)

P.<x>=PolynomialRing(Zmod(n))  #对p进一步爆破
for i in range(100,1000):
    f=x+ZZ(((p>>i)<<i))      #注意加上整数环ZZ,因为x是个环内的数,不然会报错,不信你可以试试
    root=f.small_roots(X=2^i,beta=0.4)
    if root!=[]:
        p=root[0]+ZZ(((p>>i)<<i))
        break
print(p)

q=ZZ(n)//ZZ(p)
phi=ZZ((p-1)*(q-1))
d=gmpy2.invert(e,phi)
m=ZZ(pow(c,d,n))
print(m)

data1=182219017730986958273958989689968387899
data2=315943674845875518476789636594922239111
pad = data1 * data2
print(pad**3)

#190813940127169285428485324804754938788990669565404586938424781084071030386363403117434253462457023978333955353156254005360622226335647610163254072330538141918676938868012557681771059410152661947776076466998765803516367248870831928
#190813940127169285428485324804754938788990669565404586938424781084071030386363403117434253462457023978333955353156254005360622226315064447374106848135025311597743809754751326596877994873102973248296727123176719173187699013097440069
mm=m^^(pad**3)
#mm=56006392793427429214108738999096395450496940694719089841200007225830160331551005145390312324435424381
flag=long_to_bytes(mm)
print(flag)

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值