(p+q)>>nbits
题目:
from Crypto.Util.number import *
import uuid
flag = "flag{" + str(uuid.uuid4()) + "}"
print(flag)
m = bytes_to_long(flag.encode())
p = getPrime(1024)
q = getPrime(1024)
e = 65537
gift = (p + q) >> 400
n = p * q
print(gift)
print(n)
c = pow(m, e, n)
print(c)
'''
n = 22398699297762429492240463695149209598953191913914250274334959408936466626709767203795928260632633526529986584516612990634853439372145270966645004610843264907486995514891241264900062942677946045045102531217747973015030965015115984831603228162539840321760619025278925339356880648514285731088578156632342855265866008190857967855561352802052119373432686410402584018364224892529791407346844329490691835861851663985544831188244011267819905082223999055440614384023833104923725075939687869221677886604547462159479192421742664500289270937685723384566928149675802958103124877898785273157964165967194692892199269557387215118229
gift = 115949464135543873667356544321114013642432063020632381195983542969535286109623221762809011120770679450341205761868649044031660422145112658119966580941713678634616521251250585930471772508493
c = 19459058015255747979675566411760591387346930072958488102496553309827275614011341119722879974026004366424863422880372837878804781704271505404623120814555506455826259972089765470140479884289985712921947355761601869625995897130103364150827575977235103104847368754689754720329382142627108882164642140768775016478179380366695382520008383095848532521930405358232646114695494383241366145651188440368307287111495552004475154269836050543588580181088681136438760452956902516502218922299785695909716583660334898109530985544093303113936983845962257477613846013387047985121910005480321268621195236709378225161923355920272534358550
'''
解题思路:
这是逐位爆破的剪枝思想
不同点
只给p+q的话可以解方程求
但是p+q进行移位操作,还是需要对数据逐位爆破求,和一种场景不同的是,这个+运算会产生进位操作
所有情况如下:
当gift当位剩余b
b==0,p,q都不变进行下一步
b==1,三种情况(p+1,q,gift-1)(p,q+1,gift-1)(p,q,gift)
b==2,三种情况(p+1,q,gift-1)(p,q+1,gift-1)(p+1,q+1,gift-2)
b==3,最后一种(p+1,q+1,gift-2)
还有一种做法是把他当成已知p+q高位攻击
解答:
法1:
N = 22398699297762429492240463695149209598953191913914250274334959408936466626709767203795928260632633526529986584516612990634853439372145270966645004610843264907486995514891241264900062942677946045045102531217747973015030965015115984831603228162539840321760619025278925339356880648514285731088578156632342855265866008190857967855561352802052119373432686410402584018364224892529791407346844329490691835861851663985544831188244011267819905082223999055440614384023833104923725075939687869221677886604547462159479192421742664500289270937685723384566928149675802958103124877898785273157964165967194692892199269557387215118229
gift = 115949464135543873667356544321114013642432063020632381195983542969535286109623221762809011120770679450341205761868649044031660422145112658119966580941713678634616521251250585930471772508493
gift = gift<<400
PR.<x> = PolynomialRing(Zmod(N))
ok = False
def pq_add(tp,tq,tgift,idx):
global ok
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<=400:
try:
f = tp + x
rr = f.monic().small_roots(X=2^400, beta=0.4)
if rr != []:
print(rr)
print(tp)
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<<1023
tq = 1<<1023
tgift = gift -tp -tq
pq_add(tp,tq,tgift,1023)
'''
[2265413419538307713569572150316066691404059965822822570367055437867695188522685886378081839716237050660641008581211789791]
153305387463348037357487373035059049858328853159142649103487512945187364968009787569616241281858216580389833745138207790411915561161286910364146345998580015250170791603381228114031585408078683245850975598944792085448891508939953190843530518976453421722771682258651068744935276880834873100859818443094624305152
p = 153305387463348037357487373035059049858328853159142649103487512945187364968009787569616241281858216580389833745138207790411915561161286910364146345998580015250170791603381228114031585408080948659270513906658361657599207575631357250809353341546820477160639377447173754631313358720551110151520459451675836094943
'''
from Crypto.Util.number import *
import gmpy2
n = 22398699297762429492240463695149209598953191913914250274334959408936466626709767203795928260632633526529986584516612990634853439372145270966645004610843264907486995514891241264900062942677946045045102531217747973015030965015115984831603228162539840321760619025278925339356880648514285731088578156632342855265866008190857967855561352802052119373432686410402584018364224892529791407346844329490691835861851663985544831188244011267819905082223999055440614384023833104923725075939687869221677886604547462159479192421742664500289270937685723384566928149675802958103124877898785273157964165967194692892199269557387215118229
c = 19459058015255747979675566411760591387346930072958488102496553309827275614011341119722879974026004366424863422880372837878804781704271505404623120814555506455826259972089765470140479884289985712921947355761601869625995897130103364150827575977235103104847368754689754720329382142627108882164642140768775016478179380366695382520008383095848532521930405358232646114695494383241366145651188440368307287111495552004475154269836050543588580181088681136438760452956902516502218922299785695909716583660334898109530985544093303113936983845962257477613846013387047985121910005480321268621195236709378225161923355920272534358550
p = 153305387463348037357487373035059049858328853159142649103487512945187364968009787569616241281858216580389833745138207790411915561161286910364146345998580015250170791603381228114031585408080948659270513906658361657599207575631357250809353341546820477160639377447173754631313358720551110151520459451675836094943
e = 65537
q = n // p
phi = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))
#flag{53fd644f-56f3-47d4-9ad9-cbce363c0869}
法2:
ct = 19459058015255747979675566411760591387346930072958488102496553309827275614011341119722879974026004366424863422880372837878804781704271505404623120814555506455826259972089765470140479884289985712921947355761601869625995897130103364150827575977235103104847368754689754720329382142627108882164642140768775016478179380366695382520008383095848532521930405358232646114695494383241366145651188440368307287111495552004475154269836050543588580181088681136438760452956902516502218922299785695909716583660334898109530985544093303113936983845962257477613846013387047985121910005480321268621195236709378225161923355920272534358550
e = 65537
n = 22398699297762429492240463695149209598953191913914250274334959408936466626709767203795928260632633526529986584516612990634853439372145270966645004610843264907486995514891241264900062942677946045045102531217747973015030965015115984831603228162539840321760619025278925339356880648514285731088578156632342855265866008190857967855561352802052119373432686410402584018364224892529791407346844329490691835861851663985544831188244011267819905082223999055440614384023833104923725075939687869221677886604547462159479192421742664500289270937685723384566928149675802958103124877898785273157964165967194692892199269557387215118229
hint = 115949464135543873667356544321114013642432063020632381195983542969535286109623221762809011120770679450341205761868649044031660422145112658119966580941713678634616521251250585930471772508493
PR.<x> = PolynomialRing(RealField(1000))
f = x*((hint<<400)-x) - n
phigh = int(f.roots()[0][0])
PR.<x> = PolynomialRing(Zmod(n))
f = phigh + x
res = f.small_roots(X=2^406, 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:]))
#flag{53fd644f-56f3-47d4-9ad9-cbce363c0869}