题目
from Crypto.Util.number import *
from hashlib import sha256
flag = open("flag.txt").read()
p = getPrime(512)
q = getPrime(512)
e = getPrime(256)
n = p*q
d = inverse(e,(p-1)*(q-1))
d_m = ((d >> 512) << 512)
print("d_m = ",d_m)
print("n = ",n)
print("e = ",e)
assert flag[6:-1] == sha256(str(p).encode()).hexdigest()[:32]
# d_m = 54846367460362174332079522877510670032871200032162046677317492493462931044216323394426650814743565762481796045534803612751698364585822047676578654787832771646295054609274740117061370718708622855577527177104905114099420613343527343145928755498638387667064228376160623881856439218281811203793522182599504560128
# n = 102371500687797342407596664857291734254917985018214775746292433509077140372871717687125679767929573899320192533126974567980143105445007878861163511159294802350697707435107548927953839625147773016776671583898492755338444338394630801056367836711191009369960379855825277626760709076218114602209903833128735441623
# e = 112238903025225752449505695131644979150784442753977451850362059850426421356123
解题思路
- 这是一个已知 $d$ 高位攻击类型的题目,但是这个 $d$ 未知的位数达到了总体的一半
解答
from tqdm import trange
from Crypto.Util.number import inverse
from multiprocessing import Pool
from hashlib import sha256
import gmpy2
d_m = 54846367460362174332079522877510670032871200032162046677317492493462931044216323394426650814743565762481796045534803612751698364585822047676578654787832771646295054609274740117061370718708622855577527177104905114099420613343527343145928755498638387667064228376160623881856439218281811203793522182599504560128
n = 102371500687797342407596664857291734254917985018214775746292433509077140372871717687125679767929573899320192533126974567980143105445007878861163511159294802350697707435107548927953839625147773016776671583898492755338444338394630801056367836711191009369960379855825277626760709076218114602209903833128735441623
e = 112238903025225752449505695131644979150784442753977451850362059850426421356123
# 计算 k
k = (e*d_m) // n + 1
# 计算p mod e的值
k_inv = inverse(k,e)
s = (n + 1 + k_inv) % e
R.<x> = PolynomialRing(Zmod(e))
f = x^2 - s*x + n
res = f.roots()
may_p_mod_e = [int(res[0][0]),int(res[1][0])]
def attack(range):
low = range[0]
up = range[1]
for pl in may_p_mod_e:
R.<x> = PolynomialRing(Zmod(n))
for i in trange(low,up):
f = (x * 2^14 + i) * e + pl
res = f.monic().small_roots(X=2^242,beta=0.49,epsilon=0.02)
if res != []:
print(f"res = {res}")
print(f"i = {i}")
for root in res:
p = (int(root) * 2^14 + i) * e + pl
if n % p == 0:
flag1 = "SUCTF{" + sha256(str(p).encode()).hexdigest()[:32] + "}"
flag2 = "SUCTF{" + sha256(str(n // p).encode()).hexdigest()[:32] + "}"
print(flag1)
print(flag2)
return
ranges = [(i,i + 512) for i in range(0,2^14,512)]
with Pool(32) as pool:
r = list(pool.imap(attack,ranges))
'''
res = [4905784199556797483981650640778180846920923535274112964972302055716194418]
i = 2126
SUCTF{1c56d344aba19600db3956abebc34425}
SUCTF{c1864501fab1841178177d4f15af4ad8}
'''
from multiprocessing import Pool
from tqdm import trange
import sys
def attack(range_):
n = 102371500687797342407596664857291734254917985018214775746292433509077140372871717687125679767929573899320192533126974567980143105445007878861163511159294802350697707435107548927953839625147773016776671583898492755338444338394630801056367836711191009369960379855825277626760709076218114602209903833128735441623
e = 112238903025225752449505695131644979150784442753977451850362059850426421356123
res = [(68696458789499884692247635135148296989030879976312427541751994081257774325189,1),(56220299912083199824680953877514275031991586299490111910943821482768735249418,1)]
R.<k3h> = Zmod(n)[]
low = range_[0]
high = range_[1]
for pl in res:
for i in trange(low, high):
bits = int(pl[0]).bit_length()
f = (2 ^ 14 * k3h + i) * e + pl[0]
root = f.monic().small_roots(X = 2 ^ (512 - bits - 14), beta = 0.49, epsilon = 0.02)
if root:
p = (2 ^ 14 * int(root[0]) + i) * e + pl[0]
assert n % p == 0
print(p)
sys.exit()
if __name__ == "__main__":
ranges = [(i, i + 1024) for i in range(0, 2 ^ 14, 1024)]
with Pool(16) as pool: #2 ^ 14 // 16 = 1024
try:
list(pool.imap(attack, ranges))
except:
pool.terminate() # 强制终止线程池
pool.join() # 等待线程清理
'''
9021355410009950348639875237199118006505512170606972234278412660410503971242219008091386834585426483874880261151641622040094401795529954768919085685089663
'''
from Crypto.Util.number import *
d_m = 54846367460362174332079522877510670032871200032162046677317492493462931044216323394426650814743565762481796045534803612751698364585822047676578654787832771646295054609274740117061370718708622855577527177104905114099420613343527343145928755498638387667064228376160623881856439218281811203793522182599504560128
n = 102371500687797342407596664857291734254917985018214775746292433509077140372871717687125679767929573899320192533126974567980143105445007878861163511159294802350697707435107548927953839625147773016776671583898492755338444338394630801056367836711191009369960379855825277626760709076218114602209903833128735441623
e = 112238903025225752449505695131644979150784442753977451850362059850426421356123
k = e*d_m // n + 1
# s=p+q
# ed_l+ks+[ed_h-1-k(n+1)]=0
#(d_l,s,1)*L=(d_l,s,1)
L = Matrix(ZZ, [
[1, 0, e],
[0, 1, k],
[0, 0, e*d_m - 1 - k*(n+1)],
])
# 配平目标向量
# 513就行了(512也不行),至于为啥,我不清楚
L[:, -1:] *= 2^513
L = L.LLL()
# L[0]:(-k,e,0)
# L[1]:(d_l-t*k,s+t*e,0)
# 理解:e和k只有256bit,比我们想要的d_l(512bit)和s(512bit)都要短
# LLL之后肯定是前者这个较短的向量,所以从第二小的向量入手
res=L[1] # s+t*e
s=res[1]%e
PR.<x> = PolynomialRing(Zmod(e))
f = x^2 + n - s*x #p*p+p*q-p*s
res = f.roots()
pl = int(res[0][0]) # p%e
import multiprocessing
import tqdm
from hashlib import sha256
def copper_attack(i):
PR.<x> = PolynomialRing(Zmod(n))
f = e*(2^12*x + i) + pl
f = f.monic()
res = f.small_roots(X=2^244, beta=0.499, epsilon=0.02)
if(res != []):
t = int(res[0])
p = e*(2^12*t + i) + pl
q = n // p
assert p * q == n and isPrime(p) and isPrime(q)
print(sha256(str(p).encode()).hexdigest()[:32])
print(sha256(str(q).encode()).hexdigest()[:32])
return True
with multiprocessing.Pool(processes=16) as pool:
for _ in tqdm.tqdm(pool.imap(copper_attack, range(2^12)), total=int(2^12)):
if(_):
break
"""
1c56d344aba19600db3956abebc34425
c1864501fab1841178177d4f15af4ad8
"""