已知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
posted @ 2025-03-11 22:06  sevensnight  阅读(51)  评论(0)    收藏  举报