2022蓝帽杯初赛密码wp(复现)

2022蓝帽杯密码wp(复现)

corrupted_key

题目
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from secret import flag

key = RSA.generate(1024)
open("flag.enc",'wb').write(PKCS1_OAEP.new(key.publickey()).encrypt(flag))
open('priv.pem','wb').write(key.exportKey('PEM'))
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDXFSUGqpzsBeUzXWtG9UkUB8MZn9UQkfH2Aw03YrngP0nJ3NwH
UFTgzBSLl0tBhUvZO07haiqHbuYgBegO+Aa3qjtksb+bH6dz41PQzbn/l4Pd1fXm
dJmtEPNh6TjQC4KmpMQqBTXF52cheY6GtFzUuNA7DX51wr6HZqHoQ73GQQIDAQAB








yQvOzxy6szWFheigQdGxAkEA4wFss2CcHWQ8FnQ5w7k4uIH0I38khg07HLhaYm1c
zUcmlk4PgnDWxN+ev+vMU45O5eGntzaO3lHsaukX9461mA==
-----END RSA PRIVATE KEY-----
解析

给了不完整的PRIVATE KEY,很蓝帽,信息丢失,要恢复私钥。

先分析一下私钥文件。私钥文件包含 n , e , d , p , q , d % ( p − 1 ) , d % ( q − 1 ) , i n v e r t ( q , p ) n,e,d,p,q,d\%(p-1),d\%(q-1),invert(q,p) n,e,d,p,q,d%(p1),d%(q1),invert(q,p)及标签头,再将在这些base64后得到 p e m pem pem文件。将缺失的密钥分成两部分,base64解码后转成16进制查看更清晰。

MIICXgIBAAKBgQDXFSUGqpzsBeUzXWtG9UkUB8MZn9UQkfH2Aw03YrngP0nJ3NwH
UFTgzBSLl0tBhUvZO07haiqHbuYgBegO+Aa3qjtksb+bH6dz41PQzbn/l4Pd1fXm
dJmtEPNh6TjQC4KmpMQqBTXF52cheY6GtFzUuNA7DX51wr6HZqHoQ73GQQIDAQAB

30 82 02 5e 02 01 00 02 81 81 00 d7 15 25 06 aa 9c ec 05 e5 33 5d 6b 46 f5 49 14 07 c3 19 9f d5 10 91 f1 f6 03 0d 37 62 b9 e0 3f 49 c9 dc dc 07 50 54 e0 cc 14 8b 97 4b 41 85 4b d9 3b 4e e1 6a 2a 87 6e e6 20 05 e8 0e f8 06 b7 aa 3b 64 b1 bf 9b 1f a7 73 e3 53 d0 cd b9 ff 97 83 dd d5 f5 e6 74 99 ad 10 f3 61 e9 38 d0 0b 82 a6 a4 c4 2a 05 35 c5 e7 67 21 79 8e 86 b4 5c d4 b8 d0 3b 0d 7e 75 c2 be 87 66 a1 e8 43 bd c6 41 02 03 01 00 01

yQvOzxy6szWFheigQdGxAkEA4wFss2CcHWQ8FnQ5w7k4uIH0I38khg07HLhaYm1c
zUcmlk4PgnDWxN+ev+vMU45O5eGntzaO3lHsaukX9461mA==

c9 0b ce cf 1c ba b3 35 85 85 e8 a0 41 d1 b1 02 41 00 e3 01 6c b3 60 9c 1d 64 3c 16 74 39 c3 b9 38 b8 81 f4 23 7f 24 86 0d 3b 1c b8 5a 62 6d 5c cd 47 26 96 4e 0f 82 70 d6 c4 df 9e bf eb cc 53 8e 4e e5 e1 a7 b7 36 8e de 51 ec 6a e9 17 f7 8e b5 98

通过标签头定位可以得到一下信息:

n = 0xd7152506aa9cec05e5335d6b46f5491407c3199fd51091f1f6030d3762b9e03f49c9dcdc075054e0cc148b974b41854bd93b4ee16a2a876ee62005e80ef806b7aa3b64b1bf9b1fa773e353d0cdb9ff9783ddd5f5e67499ad10f361e938d00b82a6a4c42a0535c5e76721798e86b45cd4b8d03b0d7e75c2be8766a1e843bdc641
e = 0x10001
u = 0xe3016cb3609c1d643c167439c3b938b881f4237f24860d3b1cb85a626d5ccd4726964e0f8270d6c4df9ebfebcc538e4ee5e1a7b7368ede51ec6ae917f78eb598 # u * q % p = 1
dq_low = 0xc90bcecf1cbab3358585e8a041d1b1 # dq_low = d % (q - 1) % 2**120

之后就是恢复私钥。

一般常见的是泄露 d p dp dp, 可以恢复 p p p。同理,在这里给了 d q dq dq低120位,那么就恢复 q q q的低120位,再通过 q q q的低120位和 u u u恢复 q q q
e ∗ d q = k ∗ ( q − 1 ) + 1 ∵   d q < q − 1 ,   ∴   e > k e ∗ d q + k − 1 = k ∗ q   m o d (   2 120 ) ( e ∗ d q + k − 1 ) ∗ i n v e r t ( k , 2 120 ) = q   m o d (   2 120 ) e * dq = k*(q-1) + 1 \\ ∵\ dq < q-1,\ ∴\ e > k \\ e * dq + k - 1 = k * q\ mod(\ 2^{120})\\ (e * dq + k - 1) * invert(k, 2^{120}) = q\ mod(\ 2^{120}) edq=k(q1)+1 dq<q1,  e>kedq+k1=kq mod( 2120)(edq+k1)invert(k,2120)=q mod( 2120)
所以遍历 k ← ( 1 , 65537 ) k ←(1,65537) k(1,65537)即可求出 q q q的低120位。

然后求 q q q
u ∗ q = 1   m o d ( q ) u ∗ q = k ∗ p + 1 u ∗ q ∗ q − q = k ∗ p u ∗ q ∗ q − q = 0   m o d ( p ) u * q = 1\ mod(q)\\ u * q = k*p + 1\\ u * q * q - q = k * p\\ u*q*q-q = 0\ mod(p) uq=1 mod(q)uq=kp+1uqqq=kpuqqq=0 mod(p)
然后 C o p p e r s m i t h Coppersmith Coppersmith一下就可以啦

image-20220711175435089

exp
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Util.number import *
from gmpy2 import *
from tqdm import tqdm

n = 0xd7152506aa9cec05e5335d6b46f5491407c3199fd51091f1f6030d3762b9e03f49c9dcdc075054e0cc148b974b41854bd93b4ee16a2a876ee62005e80ef806b7aa3b64b1bf9b1fa773e353d0cdb9ff9783ddd5f5e67499ad10f361e938d00b82a6a4c42a0535c5e76721798e86b45cd4b8d03b0d7e75c2be8766a1e843bdc641
e = 0x10001
cf = 0xe3016cb3609c1d643c167439c3b938b881f4237f24860d3b1cb85a626d5ccd4726964e0f8270d6c4df9ebfebcc538e4ee5e1a7b7368ede51ec6ae917f78eb598
d_low = 0xc90bcecf1cbab3358585e8a041d1b1
q_low = []
for i in tqdm(range(1, e, 2)):
    try:
        q0 = invert(i, 2 ** 120) * (e * d_low + i - 1) % 2 ^ 120
        q_low.append(q0)
    except:
        continue
PR.<x> = Zmod(n)[]
roots = []
for i in tqdm(range(len(q_low))):
    f = cf * (2^120*x + int(q_low[i])) ^ 2 - (2^120*x + int(q_low[i]))
    root = f.monic().small_roots(X = 2^(512-120))
    if root:
        q = 2^120*int(root[0]) + int(q_low[i])
        p = n // q
        assert p * q == n
        d = inverse(e, (p - 1) * (q - 1))
        rsa = RSA.construct((int(n), int(e), int(d), int(p), int(q)))
        # c = bytes_to_long(open('flag.enc', 'rb').read())
        c = 96458723724899437870554342796876171017896652413964521193266438981853945238446913579867464909353925601873532290626111170073532116639383463734148270579305067733147411306325252107181823453497914478588342362177625026365513002442585949837516090367171824895036711246039928723021679235071368954348296729327873680822
        c = long_to_bytes(c)
        print(PKCS1_OAEP.new(rsa).decrypt(c))
# c = 96458723724899437870554342796876171017896652413964521193266438981853945238446913579867464909353925601873532290626111170073532116639383463734148270579305067733147411306325252107181823453497914478588342362177625026365513002442585949837516090367171824895036711246039928723021679235071368954348296729327873680822
# p = 12112790828812363063315417237469719611888243756064158121348026938824270601623590308149025542977097905953795136774300936003505715307199422663647014200158449
# q = 12469144192094336933187534132907623337514842804208163244218540727384104398951558782195384932941310035462094951428865175221316720981428462265191789302379089
# d = inverse(e, (p - 1) * (q - 1))
# rsa = RSA.construct((n, e, d, p, q))
# print(PKCS1_OAEP.new(rsa).decrypt(open('flag.enc', 'rb').read()))
小总结

比赛的时候想到了单纯的用 u ∗ q ∗ q − q = 0 u*q*q-q=0 uqqq=0来求 q q q,但是没有出来,可能约束不够吧。

第二天上午复现的时候想到了通过 d q dq dq低位求 q q q的低位,但把同时将上面的联立起来给忘记了,虽然 q q q的低位也没求出来

下午有了脚本后豁然开朗(从别的师傅那里来的),思路还是不够灵活,不能串在一起,老了。

遇到的一点点问题:

上面说到 ( e ∗ d q + k − 1 ) ∗ i n v e r t ( k , 2 120 ) = q   m o d (   2 120 ) (e * dq + k - 1) * invert(k, 2^{120}) = q\ mod(\ 2^{120}) (edq+k1)invert(k,2120)=q mod( 2120),但 ( e ∗ d q − 1 ) ∗ i n v e r t ( k , 2 120 ) + 1 = q   m o d (   2 120 ) (e * dq - 1) * invert(k, 2^{120}) + 1 = q\ mod(\ 2^{120}) (edq1)invert(k,2120)+1=q mod( 2120)

不太行;

解出来得到 p , q , d p,q,d p,q,d后直接 p o w ( e , d , n ) pow(e,d,n) pow(e,d,n)也不太行(可能和 P K C S 1 _ O A E P PKCS1\_OAEP PKCS1_OAEP有点关系吧)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

mxx307

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

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

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

打赏作者

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

抵扣说明:

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

余额充值