*CTF 2022 easyRSA

本文介绍了一种升级版的RSA加密挑战,通过分析密钥生成过程,利用数学原理如Coppersmith方法,成功预测并计算出p和q的精确值,揭示了flag。涉及的知识包括大数分解、异或运算、多项式求根和RSA加密原理。
摘要由CSDN通过智能技术生成

源码:

from Crypto.Util.number import getStrongPrime
from gmpy import next_prime
from random import getrandbits
from flag import flag

p=getStrongPrime(1024)
q=next_prime(p^((1<<900)-1)^getrandbits(300))
n=p*q
e=65537

m=int(flag.encode('hex'),16)
assert m<n
c=pow(m,e,n)

print(hex(n))
#0xe78ab40c343d4985c1de167e80ba2657c7ee8c2e26d88e0026b68fe400224a3bd7e2a7103c3b01ea4d171f5cf68c8f00a64304630e07341cde0bc74ef5c88dcbb9822765df53182e3f57153b5f93ff857d496c6561c3ddbe0ce6ff64ba11d4edfc18a0350c3d0e1f8bd11b3560a111d3a3178ed4a28579c4f1e0dc17cb02c3ac38a66a230ba9a2f741f9168641c8ce28a3a8c33d523553864f014752a04737e555213f253a72f158893f80e631de2f55d1d0b2b654fc7fa4d5b3d95617e8253573967de68f6178f78bb7c4788a3a1e9778cbfc7c7fa8beffe24276b9ad85b11eed01b872b74cdc44959059c67c18b0b7a1d57512319a5e84a9a0735fa536f1b3

print(hex(c))
#0xd7f6c90512bc9494370c3955ff3136bb245a6d1095e43d8636f66f11db525f2063b14b2a4363a96e6eb1bea1e9b2cc62b0cae7659f18f2b8e41fca557281a1e859e8e6b35bd114655b6bf5e454753653309a794fa52ff2e79433ca4bbeb1ab9a78ec49f49ebee2636abd9dd9b80306ae1b87a86c8012211bda88e6e14c58805feb6721a01481d1a7031eb3333375a81858ff3b58d8837c188ffcb982a631e1a7a603b947a6984bd78516c71cfc737aaba479688d56df2c0952deaf496a4eb3f603a46a90efbe9e82a6aef8cfb23e5fcb938c9049b227b7f15c878bd99b61b6c56db7dfff43cd457429d5dcdb5fe314f1cdf317d0c5202bad6a9770076e9b25b1



与【zer0pts CTF 2022】Anti-Fermat  类似,升级版,没做过它的话建议先看看它

nextprime影响的是非常低位的数据,对高位没有影响,所以q约等于p异或2^900-1异或一个300位的随机数,

把p和q拆分开,p=p_{high}+p_{low} ,q=q_{high}+q_{low},high指高124位,low指低900位

p_{high}=x,显然q_{high}=x

且:

p_{low}+q_{low}=2^{900}-1+c1 ,c1是300位随机字符异或影响后的改变量,是个很小的数

所以

n=pq=(p_{high}*2^{900}+p_{low})(q_{high}*2^{900}+q_{low})=2^{1800}x^2+2^{900}x(p_{low}+q_{low})+p_{low}q_{low}=2^{1800}x^2+2^{1800}x+small

则n//(2**1800)就是x+x^2,放到sagemath里解出来x

n=0xe78ab40c343d4985c1de167e80ba2657c7ee8c2e26d88e0026b68fe400224a3bd7e2a7103c3b01ea4d171f5cf68c8f00a64304630e07341cde0bc74ef5c88dcbb9822765df53182e3f57153b5f93ff857d496c6561c3ddbe0ce6ff64ba11d4edfc18a0350c3d0e1f8bd11b3560a111d3a3178ed4a28579c4f1e0dc17cb02c3ac38a66a230ba9a2f741f9168641c8ce28a3a8c33d523553864f014752a04737e555213f253a72f158893f80e631de2f55d1d0b2b654fc7fa4d5b3d95617e8253573967de68f6178f78bb7c4788a3a1e9778cbfc7c7fa8beffe24276b9ad85b11eed01b872b74cdc44959059c67c18b0b7a1d57512319a5e84a9a0735fa536f1b3
f=n//2**1800
e=f-x-x^2
e.solve(x)
#[x == -20226195070633070235386534147535171930, x ==20226195070633070235386534147535171929]

#即x ==20226195070633070235386534147535171929

由于(1<<900-1)的二进制每一位都是1,则(1<<900-1)^p=(1<<900-1)-p(注意这是对于p的301-900位来说,如果对p全部来说,p>(1<<900-1),上述结论不成立)

而异或的随机300位字符不会影响到301-900位,所以对301-900位之间,p+q为一个定值,则易得n=pq当p=q时n最大,p和q相差越大n越小,并且p和q在这个段内每一位上有且只有一个(要么是p要么是q在这个位上)为1,另一个是0,在p,q之和固定时,p,q相差越大,所得的乘积n就会越小,因此我们先把所有的1都给p,0全给q。

然后根据乘积的大小,从高位开始去选择1的去向,求得大概的p值后,还不准确,需要爆破p的准确预测数,coppersmith求出p,解得flag

import gmpy2
from Crypto.Util.number import long_to_bytes
n=0xe78ab40c343d4985c1de167e80ba2657c7ee8c2e26d88e0026b68fe400224a3bd7e2a7103c3b01ea4d171f5cf68c8f00a64304630e07341cde0bc74ef5c88dcbb9822765df53182e3f57153b5f93ff857d496c6561c3ddbe0ce6ff64ba11d4edfc18a0350c3d0e1f8bd11b3560a111d3a3178ed4a28579c4f1e0dc17cb02c3ac38a66a230ba9a2f741f9168641c8ce28a3a8c33d523553864f014752a04737e555213f253a72f158893f80e631de2f55d1d0b2b654fc7fa4d5b3d95617e8253573967de68f6178f78bb7c4788a3a1e9778cbfc7c7fa8beffe24276b9ad85b11eed01b872b74cdc44959059c67c18b0b7a1d57512319a5e84a9a0735fa536f1b3
e=65537
c=0xd7f6c90512bc9494370c3955ff3136bb245a6d1095e43d8636f66f11db525f2063b14b2a4363a96e6eb1bea1e9b2cc62b0cae7659f18f2b8e41fca557281a1e859e8e6b35bd114655b6bf5e454753653309a794fa52ff2e79433ca4bbeb1ab9a78ec49f49ebee2636abd9dd9b80306ae1b87a86c8012211bda88e6e14c58805feb6721a01481d1a7031eb3333375a81858ff3b58d8837c188ffcb982a631e1a7a603b947a6984bd78516c71cfc737aaba479688d56df2c0952deaf496a4eb3f603a46a90efbe9e82a6aef8cfb23e5fcb938c9049b227b7f15c878bd99b61b6c56db7dfff43cd457429d5dcdb5fe314f1cdf317d0c5202bad6a9770076e9b25b1
a=20226195070633070235386534147535171929
p_high=a
p=(p_high<<900)+((1<<900)-1)^^((1<<300)-1)
q=p_high<<900
for i in range(898,299,-1):#爆出pq的近似值
        bit=1<<i
        if (p^^bit)*(q^^bit)<n:
                p^^=bit
                q^^=bit

P.<x>=PolynomialRing(Zmod(n))  #对p进一步爆破,直到能用高位攻击为止,得到p
for i in range(300,500):
    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

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

*CTF{St.Diana_pls_take_me_with_you!}'

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Paintrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值