题目:
from Crypto.Util.number import *
from Crypto.PublicKey import RSA
from hashlib import sha256
import random, os, signal, string
def proof_of_work():
random.seed(os.urandom(8))
proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
_hexdigest = sha256(proof.encode()).hexdigest()
print(f"sha256(XXXX+{proof[4:]}) == {_hexdigest}")
print('Give me XXXX: ')
x = input()
if len(x) != 4 or sha256(x.encode()+proof[4:].encode()).hexdigest() != _hexdigest:
print('Wrong PoW')
return False
return True
if not proof_of_work():
exit(1)
signal.alarm(10)
print("Give me a bad RSA keypair.")
try:
p = int(input('p = '))
q = int(input('q = '))
assert p > 0
assert q > 0
assert p != q
assert p.bit_length() == 512
assert q.bit_length() == 512
assert isPrime(p)
assert isPrime(q)
n = p * q
e = 65537
assert p % e != 1
assert q % e != 1
d = inverse(e, (p-1)*(q-1))
except:
print("Invalid params")
exit(2)
try:
key = RSA.construct([n,e,d,p,q])
print("This is not a bad RSA keypair.")
exit(3)
except KeyboardInterrupt:
print("Hacker detected.")
exit(4)
except ValueError:
print("How could this happen?")
from secret import flag
print(flag)
关键在想办法报ValueError,查看construct函数的源码,可以分析出是n、d不互素:
if Integer(n).gcd(d) != 1:
raise ValueError("RSA private exponent is not coprime to modulus")
构造出合适的d:
令$d = m \cdot p = m + m \cdot (p-1)$
两边同乘上e:
$e \cdot d = e \cdot m + e \cdot m \cdot(p-1)$
结合$e \cdot d \equiv 1 \space mod \space \phi(n)$,可得:
$e \cdot m \equiv 1 \space mod \space \phi(n) \equiv 1 \space mod \space (p-1)$
$p$随机生成,则可以求出m来。
$e \cdot d = e \cdot m \cdot p = 1 + k \cdot (p-1) \cdot (q-1)$
$(q-1) = \frac{e \cdot m \cdot p - 1}{k \cdot (p-1)}$,$k在(1,e)$,可以爆破。
代码如下:
from pwn import *
import string
import hashlib
def hashstring(partstr, hashstr):
str = string.ascii_letters + string.digits
for i1 in str:
for i2 in str:
for i3 in str:
for i4 in str:
plain = i1 + i2 + i3 + i4 + partstr
maystr = hashlib.sha256(plain.encode()).hexdigest()
if maystr == hashstr:
print(i1 + i2 + i3 + i4)
return i1 + i2 + i3 + i4
def getPQ():
e = 65537
p = getPrime(512)
m = inverse(e,p-1)
res = (e*m*p-1) // (p-1)
for k in range(0,e):
if res % k == 0:
q = res // k + 1
return p,q
s = remote("...", ...)
s.recvuntil(b"XXXX+")
partstr = s.recvuntil(b')')[:-1].decode()
print(partstr)
s.recvuntil(b"== ")
hashstr = s.recvline()[:-1].decode()
print(hashstr)
knownpart = hashstring(partstr, hashstr)
s.recvuntil(b"Give me XXXX: ")
s.sendline(knownpart.encode())
print(s.recvuntil(b"Give me a bad RSA keypair."))
p,q = getPQ()
解出p、q就不多bb了。
参考:
2023CISCN-badkey1 - L00kback - 博客园 (cnblogs.com)
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1666739907@qq.com