已知p+q高位攻击
题目1:
from Crypto.Util.number import *
p = getPrime(512)
q = getPrime(512)
n = p*q
e = 65537
m = bytes_to_long(b"nbctf{[REDACTED]}")
ct = pow(m,e,n)
print(f"{ct = }")
print(f"{e = }")
print(f"{n = }")
hint = (p+q) >> 200 # I can't be giving you that much!
print(f"{hint = }")
'''
ct = 20030315247290021934293927354887580426070566017560641204155610658927917290198737029903594702064351773446005018155094643288125396810753014936800515440652855824038470725838848349666236623899089094953181436465435270989651491997801177943499187812270081592263331832916362349716591828106306150603120693022149233534
e = 65537
n = 90166344558664675592644684556355545187373291859609367810958775310181360193141550862577281658089332577942193823477148064165061303827534169112815736618901965700400798345371758370344207077280925015891945591352156370597957742921722432314582261224366498475465730899163137511778647694175484386010210005826793007961
hint = 12227137598952006551839416663729660224872609953685427677011433223002140448682395830146750981200
'''
解题思路:
- 题目给了
p+q
的高位,那么直接在实数域上解一个p
,q
的近似值就能得到p
,q
的部分高位,然后copper就可以还原p
,q
解答1:
ct = 20030315247290021934293927354887580426070566017560641204155610658927917290198737029903594702064351773446005018155094643288125396810753014936800515440652855824038470725838848349666236623899089094953181436465435270989651491997801177943499187812270081592263331832916362349716591828106306150603120693022149233534
e = 65537
n = 90166344558664675592644684556355545187373291859609367810958775310181360193141550862577281658089332577942193823477148064165061303827534169112815736618901965700400798345371758370344207077280925015891945591352156370597957742921722432314582261224366498475465730899163137511778647694175484386010210005826793007961
hint = 12227137598952006551839416663729660224872609953685427677011433223002140448682395830146750981200
PR.<x> = PolynomialRing(RealField(1000))
f = x*((hint<<200)-x) - n
phigh = int(f.roots()[0][0])
PR.<x> = PolynomialRing(Zmod(n))
f = phigh + x
res = f.small_roots(X=2^203, beta=0.4)[0]
p = int(phigh + res)
q = n // p
d = inverse_mod(e,(p-1)*(q-1))
flag = pow(ct, d, n)
print(bytes.fromhex(hex(flag)[2:]))
#nbctf{cr34t1v3_fl4gs_4r3_s0_h4rd_t0_m4k3...}
题目2:
from Crypto.Util.number import *
from gmpy2 import *
from secret import flag
BITS = 233
def broken(x, bits):
return x>>bits
def gen():
p,q = getPrime(512),getPrime(512)
n = p*q
e = 65537
return n, broken(p+q, BITS)
n, hint = gen()
e = 0x10001
m = bytes_to_long(flag)
assert m < n
c = pow(m, e, n)
print(n)
print(hint)
print(c)
'''
107847645025513535850791225440130707186374273414737521825714442885442542984529827092766916748308266623066053421754530398675086374798530909982183476265477598220972320436343536618913608933549054793948336438240303192183575843300257235195070331758555882832698815894168120103459360566404203412796086643598204242029
1505246122706281178983443268987790509406564031452059494152554645294649335244676839890
16589212605025468264862689939961340646400626438824064459026078002373801735937861932598660491280834517490394340315480853421268981930217857435669572426110105938015092688880859031418213297139875807487434491329423279700179082306961439610731922669459168752958192842026918421354512654494583087220572962719510130677
'''
解题思路:
法1:
- 题目给了
p+q
的高位,那么直接在实数域上解一个p
,q
的近似值就能得到p
,q
的部分高位,然后copper就可以还原p
,q
法2:
- 本质上就是剪枝思想-逐位爆破
- 参考(p+q)>>nbits(剪枝问题-[p+q]>>nbits)
解答2:
法1:
import gmpy2
N = 107847645025513535850791225440130707186374273414737521825714442885442542984529827092766916748308266623066053421754530398675086374798530909982183476265477598220972320436343536618913608933549054793948336438240303192183575843300257235195070331758555882832698815894168120103459360566404203412796086643598204242029
gift = 1505246122706281178983443268987790509406564031452059494152554645294649335244676839890
c = 16589212605025468264862689939961340646400626438824064459026078002373801735937861932598660491280834517490394340315480853421268981930217857435669572426110105938015092688880859031418213297139875807487434491329423279700179082306961439610731922669459168752958192842026918421354512654494583087220572962719510130677
RF = RealField(1024)
X = polygen(RF)
f =X*((gift << 233)-X) - N
P = int(f.roots()[0][0])
kbits = 245
P_high = (P >> kbits) << kbits
PR.<x> = PolynomialRing(Zmod(N))
f1 = x + P_high
x0 =f1.small_roots(X=2^kbits, beta=0.4,epsilon=0.01)[0]
p = P_high+x0
print(f"p = {p}")
#p = 10105842966112330732247722627092188919461451854374225557888676662498836038661318202837196203332312745217832403973228568718021907973008848945617111153254747
q = N // int(p)
phi = (p-1)*(q-1)
d = gmpy2.invert(65537,gmpy2.mpz(phi))
m = pow(c,d,N)
print(bytes.fromhex(hex(m)[2:]))
#flag{ccc2e285-7bb1-484e-ad62-58cc474ef9d4}
法2:逐位爆破的剪枝思想
#sage
N = 107847645025513535850791225440130707186374273414737521825714442885442542984529827092766916748308266623066053421754530398675086374798530909982183476265477598220972320436343536618913608933549054793948336438240303192183575843300257235195070331758555882832698815894168120103459360566404203412796086643598204242029
gift = 1505246122706281178983443268987790509406564031452059494152554645294649335244676839890
gift = gift<<233
PR.<x> = PolynomialRing(Zmod(N))
ok = False
test=1
def pq_add(tp,tq,tgift,idx):
global ok
global test
if ok:
return
if tp*tq>N:
#print('>')
return
if (tp+(2<<idx))*(tq+(2<<idx))<N:
#print('<', hex((tp+(1<<(idx+2))))[:20], hex(tq+(2<<idx))[:20], hex(N)[:20])
return
if idx<=233:
try:
test += 1
print(test)
for i in range(1024):
tpp = tp+(i<<223)
f = tpp + x
test += 1
rr = f.monic().small_roots(X=2^223, beta=0.4)
if rr != []:
print(rr)
print(tpp)
print('p = ',f(rr[0]))
ok = True
return
except:
pass
return
idx -=1
b = tgift >>idx
one = 1<<idx
#print(hex(tp)[:20],hex(tq)[:20],hex(tgift)[:20],idx,b)
if b==0 or b==1:
pq_add(tp,tq,tgift,idx)
if b==1 or b==2:
pq_add(tp+one,tq,tgift-one,idx)
pq_add(tp,tq+one,tgift-one,idx)
if b==2 or b==3:
pq_add(tp+one,tq+one,tgift-(one<<1),idx)
tp = 1<<511
tq = 1<<511
tgift = gift -tp -tq
pq_add(tp,tq,tgift,511)
# p = 10671810890705142935923698352497956126372923054885272713948800012376136275817384032407712447142702386637160839942871245602734437654810217233791561733480407