CNSS Summer 2023
随便看看,图一乐2333。
cyclic group
p = 134994058501022133829793113756450648798182080773931273262418798773562440624857106163310596590759607340807163876539520282102901165977612358002331391089851066812663281502398201018663717659213732276911585751665516661301930410244101046617666467321456930120075263141242119953757880295718825254018040413826880843763
e = 12927587515508549311645504126259938927362775210786958053823827936884288861306268493761629822045846148118653977616493302703588300283111036739875491883808759
c = 46583597391505868783218970830156160405763802889228578452060606957717500160663392513770581781157233604314178955789908254475724009921579917780127649365498088467948777432657442293331639740286781008682662602974865442032279819833194544535317410041738966384493317240586005380761492762248899523164168679218802048162
from Crypto.Util.number import *
d = inverse(e,p-1)
print(long_to_bytes(pow(c,d,p)))
cnss娘的代码Ⅰ
key = [179283057970236760812385016853348861313, 243730152305882610684268424505624182831, 276375013783217805474364273321195364813, 338363147025326331069698214354955107607]
secret = [42312333420922777926503668120694248887, 188911830445106862831548334980052602782, 202272400826094059912187609891368651300, 16939666639933430404336668949000187621]
from sympy.ntheory.modular import crt
from Crypto.Util.number import *
m = crt(key,secret)[0]
print(long_to_bytes(m))
cnss娘的代码 Ⅱ
from Crypto.Util.number import *
h = 106414500627466044750537699496116452216938505790285966641538755230718107434518035561502262320845803494959251547594598724676292650073
p = 149223181221309438217142971731290162048502071683234438807455153639165894737664410172266260056805353255967638568356843140306590887937
F = GF(p)
g = F(7)
h = F(h)
print(long_to_bytes(ZZ(h.log(g))))
cnss娘的代码 Ⅲ
from Crypto.Util.number import *
p = 9536720961414799253
A = [[7907672172473958392, 4938237561047760432 ,5072996306459844921 ,800347085054263333 ,2241217299487989740, 5452520396763079026 ,7354205761061650589, 5632270298193588206],
[6856262700627435223, 7218982369550725117 ,3069216736555490147 ,9043167152368671477 ,6651431740452419751 ,2904199636400840775 ,1984801523985180355, 9424612078019686546],
[ 190015986177831045 , 594687507332748466, 2546708346651205091, 3864956414971412519 ,2586812319675472372 ,2541554633306459284, 2840981234492698127 ,400426130440806923],
[ 354930743948767363 , 374079227033274174 ,7821379197355217415 ,4073976921774664952 ,8974661879090783904 ,8725597754431417139 ,1723115467249027682 , 914056616366301410],
[9032929938905307703 ,569436029465728354 ,3230536280479973685 ,9499318835507740454 ,460664783708095350 ,3815328100857956310 ,6866516203996475375 ,9142528333783640721],
[6647724854667560614 ,1564543033588842443 , 980081446425820918 ,4482664640152609224 ,9361385831487208956 ,5729265277086036438 ,8521779175294512538 ,7872078731489374461],
[2426759667632064565, 2564361116290067541 ,5109836057988930695 ,3948680632682199428 ,8561341181219447072 ,5099840518920477627 ,9347277712921710222 ,4364598388067284951],
[2143804620259054744 ,4318231909289693782 ,6284698432978577252 ,5529804751795288609 ,7903556036971407808 ,3730126758887833322 ,8782120630459581951 ,9050476736532525999]]
v = (4088048241727106122, 258857328202723850, 7303598013681209756, 3446975206276714926, 176458751236949790, 8151363680348349027, 8771366063042882128, 9003511237633705064)
A = matrix(GF(p),A)
x = A.solve_left(vector(v))
m = b''
for i in x:
m = m + long_to_bytes(ZZ(i))
print(m)
RSA Ⅰ
异或剪枝,分类讨论一下。
from Crypto.Util.number import *
c = 64949799997326584007544788513993497249594769744995858720976935000014197232306799968807213667255871030075230919683627404813038995304033226711042639925325815395252041199650244620814678407788637241064396318107929964286966081900052163098825412222835465966640369222321472659135622216530966800717417560715221275591
n = 106750680418525866311589462967145265327203310954735134383588573660691518247034803380198999333962213971657327515092895034635965957228036264848532931376595751503164297061094511187060069380048933807326213369464059701069965785612620370291933800122445966488267918733547599024267999872488061941892122230382138042783
mask = 12270330408774238331968219216635392599519489634111741706590917012819298856158311310855782884352875794146685141255943386189197362902992928716839082520848927
m1 = 13112112110892990771168306272793201342028151601627796725313855804865001339738164412798270175076178951452110894792943424133718769511979832250960465757056799
m2 = 11731832079629748669705816329667815638461774924918417348984676937048335348013101619038697983623814812736529127108466295988845879378764866277739393693264401
b_mask = bin(mask)[2:]
b_m1 = bin(m1)[2:]
b_m2 = bin(m2)[2:]
p = ''
for i in range(512):
if b_m2[512-i-1] == '1':
p = '1' + p
else:
if b_m1[512-i-1] == '0':
p = '0' + p
else:
if b_mask[512-i-1] == '0':
p = '1' + p
else:
p = '0' + p
p = int(p,2)
q = n//p
assert p * q == n
fi = (p-1)*(q-1)
d = inverse(65537,fi)
print(long_to_bytes(pow(c,d,n)))
RSA Ⅱ
这个剪枝需要同时用到p和q的比特关系,还挺有意思。
from Crypto.Util.number import *
c = 21645208345867622053024283678631971385301103104312441336174301067402923208233033116071987870811290403578077414872467955871236843078200772311176723821275372545792521252126496488134168455430882670865862282658077115199048181151105823370547063726203692258934054391552916645628374539820099986794258298843501009240
n = 87282921750815275717132715603847471604654006135344540742956637574882193904171665195367477260090328888053170090015909620539666069545618781812315864580009968838414539707616636379202667918204792277927294032362873240288573251987386601263377458038218959813925307265939433229169884527274177006792047369788293125409
mask1 = 8802124635072632944677646490123224379036416333544329119490072003355821545476873187055484863111312282268555945525261726909784693138184611507738758202965723
mask2 = 10267484648659998697412163107809730542736732193409802323765378917769614002176050843098384409535095473863894691160595931186139418791709781214996751031082601
h1 = 6706231204421711988537353586716977912583550778985616494052350868539347641557164021930575245010900470979740623857738159245103694128834121517146255441177729
h2 = 6704397956705493482354535847135592349486638396996488745737387153856868045426992197309829534096366784379171117205125136777653995357887539312554042026362473
# def findp(p,q):
# if len(p)==512:
# pp=int(p,2)
# if n%pp==0:
# print(pp)
# print(n//pp)
# else:
# l=len(p)
# pp=int(p,2)
# qq = int(q,2)
# if (pp&int(bin(mask1)[2:][-l:],2))%(2**l)==h1%(2**l) and (qq&int(bin(mask2)[2:][-l:],2))%(2**l)==h2%(2**l) and pp*qq%(2**l)==n%(2**l):
# findp('1'+p,'1'+q)
# findp('1'+p,'0'+q)
# findp('0'+p,'1'+q)
# findp('0'+p,'0'+q)
#
# findp('1','1')
e = 65537
p = 10172774442863868719013872884099170294615753094066736187886125116462340120031133533430755779832487215255546434139069419394249074006281284289077492708469893
q = n//p
fi = (p-1)*(q-1)
d = inverse(e,fi)
print(long_to_bytes(pow(c,d,n)))
HomoBlock
先把key搞出来,然后分析密文异或key得到的中间值的高低两段比特分别是什么就行。
from Crypto.Util.number import *
s = b'cnss{I_a'
s = bytes_to_long(s)
mask1 = 0xffffffff00000000
cipher = [4840951631397558164, 5492303526413306583, 6271460196030786735, 6127905759336302986, 601209385465514967]
iv = 32
mask2 = 16500653344889503744
print(bin(s<<iv))
print(bin(mask1))
# for low in range(2**16):
# mask1 = 0xffffffff00000000 + low
# key = ((s<<iv)&mask1)^((s>>iv)|mask2) ^ cipher[0]
# print(key)
key = 15895952372462183655
print(((s<<iv)&mask1)^((s>>iv)|mask2)^key)
print(bin(mask2))
m = b''
for i in cipher:
tmp = i ^ key
h = bin(tmp)[2:][-32:]
m1 = long_to_bytes(int(h,2))
tmp_l = bin(tmp)[2:][:32]
# 异或mask2高位
l = int(tmp_l,2) ^ 0b11100100111111100001100011001011
m2 = long_to_bytes(l)
m = m + m1+m2
print(m.decode())
ezLFSR
state空间太小,爆就完了。
from Crypto.Util.number import long_to_bytes
class LFSR():
def __init__(self, seed, mask, length):
self.length_mask = 2 ** length - 1
self.mask = mask & self.length_mask
self.state = seed & self.length_mask
def next(self):
next_state = (self.state << 1) & self.length_mask
i = self.state & self.mask & self.length_mask
output = 0
while i != 0:
output ^= (i & 1)
i = i >> 1
next_state ^= output
self.state = next_state
return output
def getrandbit(self, nbit):
output = 0
for _ in range(nbit):
output = (output << 1) ^ self.next()
return output
c = open('cipher.enc','rb').read()
seed = 37285
for mask in range(2**16):
lfsr = LFSR(seed, mask, 16)
m = b''
for cc in c:
tmp = lfsr.getrandbit(8) ^ cc
m = m + long_to_bytes(tmp)
if b'cnss' in m:
print(m)
break
BabyLattice
带模的背包,简单svp。
p = 4653980939589101565044285021945025573290906789132633751963110127801187748089540230208429714310516635848025358481189017398970169440484136391436220837417791
t= [7163515288721018524391838724005494502072524058809935946689587023614778895762400663698973734684519790842142248155478226513293289043832391054661263177469005,13155134533945105613277690072743652931283618211062662861216511364398097684219572559463369279253337759860439150691008846033587645344197431244106331100681641,8450640520436960190933104494093081291057363628588171820766164606066614201483259024304043681871965360847257453187101669512010469318096007617859083021766564,798383352075970107818638521362593273862636131165588181505120596765884650403289567593307005746576184176902675297124272602141002375036927828390204063589274]
c = 58831711102590059067743519228568722360433408071362335858674496753241059990433991177195518029785828762522018556332340356592798263267784406825183284767956
print(len(t))
A = Matrix(ZZ, 6, 6)
for i in range(4):
A[i,i] = 1
A[i,5] = -t[i]
A[4,4] = 1
A[4,5] = c
A[5,5] = p
print(A.LLL())
MidLattice
agcd,照着经典格子打,但是需要根据界来计算\(\lambda\)的大概取值。
import hashlib
N = []
Q = []
R = []
D = []
t = 0
for _ in range(120):
print(_)
M = 2^180
L = [[0 for _ in range(120)] for _ in range(120)]
L[0] = [M]+N[0:t] + N[t+1:]
for i in range(120):
L[i][i] = - N[t]
L[0][0] = M
MQ = abs(matrix(L).LLL()[0][0])
assert MQ % M == 0
Q.append(MQ // M)
print(Q)
t+=1
for n,q in zip(N,Q):
R.append(n % q)
p = (N[0] - R[0]) // Q[0]
print(p)
flag = 'cnss{'+hashlib.sha256(long_to_bytes(p)).hexdigest()+'}'
print(flag)
ezSignature
dsa共用k attack。
from pwn import *
from hashlib import *
import string
import itertools
from Crypto.Util.number import *
table = string.ascii_uppercase + string.ascii_lowercase + string.digits
z1 = bytes_to_long(sha256(b'I want to tell you a secret').digest())
z2 = bytes_to_long(sha256(b'Can you find it?').digest())
io = remote('43.156.14.141',6943)
def proof():
s1 = io.recvline()
print(s1)
p1 = s1.find(b'X+')
p2 = s1.find(b')')
p3 = s1.find(b'== ')
s = s1[p1+2:p2]
h = s1[p3+3:-1]
h = h.decode()
for i in itertools.product(table, repeat=4):
d = ''.join(i).encode()
dd = d + s
#print(dd)
if sha256(dd).hexdigest() == h:
print(d)
io.sendline(d)
break
proof()
#io.interactive()
io.recvuntil(b'Give me your option:')
io.sendline(b'3')
exec(io.recvline())
exec(io.recvline())
exec(io.recvline())
exec(io.recvline())
io.recvuntil(b'Give me your option:')
io.sendline(b'1')
r1,s1 = eval(io.recvline()[19:])
r2,s2 = eval(io.recvline()[19:])
k = (z1*r2-z2*r1) * inverse(s1*r2-s2*r1,q) % q
x = (k*s1-z1)*inverse(r1,q) % q
m = b"I'm Admin.I want flag."
h = bytes_to_long(sha256(m).digest())
r = pow(g, k, p) % q
s = inverse(k, q) * (h + x * r) % q
io.recvuntil(b'Give me your option:')
io.sendline(b'2')
io.recvuntil(b'message:')
io.sendline(b"I'm Admin.I want flag.")
io.recvuntil(b'r:')
io.sendline(str(r).encode())
io.recvuntil(b's:')
io.sendline(str(s).encode())
io.interactive()
#cnss{1ts_Dr4nger0us_t0_u5eThe_Same_K}
StrangeCurve
smart_attack.
from sage.all import EllipticCurve
from sage.all import Qp
from sage.all import ZZ
# Lifts a point to the p-adic numbers.
def _lift(E, P, gf):
x, y = map(ZZ, P.xy())
for point_ in E.lift_x(x, all=True):
_, y_ = map(gf, point_.xy())
if y == y_:
return point_
def attack(G, P):
"""
Solves the discrete logarithm problem using Smart's attack.
More information: Smart N. P., "The discrete logarithm problem on elliptic
curves of trace one"
:param G: the base point
:param P: the point multiplication result
:return: l such that l * G == P
"""
E = G.curve()
gf = E.base_ring()
p = gf.order()
assert E.trace_of_frobenius() == 1, f"Curve should have trace of Frobenius =1."
E = EllipticCurve(Qp(p), [int(a) + p * ZZ.random_element(1, p) for a in
E.a_invariants()])
G = p * _lift(E, G, gf)
P = p * _lift(E, P, gf)
Gx, Gy = G.xy()
Px, Py = P.xy()
return int(gf((Px / Py) / (Gx / Gy)))
p=1096126227998177188652856107362412783873814431647
a=0
b=5
E = EllipticCurve(GF(p), [a, b])
P=E(626099523290649705896889901241128842906228328604,886038875771695334071307095455656761758842526929)
Q = E(240653647745552223089451307742208085297121769374 , 1041806436100548540817642210994295951394712587396)
print(E.order())
attack(P,Q)
牛头人
#多项式
N = 160
p = 3
q = 65536
Q.<x> = Zmod(q)[]
P.<y> = Zmod(p)[]
ex = -26801*x^159 - 25103*x^158 + 29811*x^157 - 12251*x^156 - 13386*x^155 - 28030*x^154 - 16511*x^153 + 23761*x^152 + 28329*x^151 - 16406*x^150 + 30931*x^149 + 5326*x^148 + 19877*x^147 - 23165*x^146 - 31540*x^145 - 7923*x^144 + 5880*x^143 - 27078*x^142 - 25436*x^141 - 17162*x^140 + 1471*x^139 + 14486*x^138 + 7702*x^137 - 29890*x^136 + 29315*x^135 + 558*x^134 - 22429*x^133 - 361*x^132 + 19049*x^131 - 30437*x^130 - 32610*x^129 - 3024*x^128 - 4313*x^127 + 29174*x^126 - 2837*x^125 - 2812*x^124 + 13450*x^123 - 15001*x^122 - 25791*x^121 - 8702*x^120 - 4968*x^119 - 15340*x^118 + 31744*x^117 - 32478*x^116 + 19737*x^115 - 12629*x^114 - 27847*x^113 + 27322*x^112 - 31375*x^111 + 14777*x^110 + 29825*x^109 - 25883*x^108 - 13335*x^107 + 32517*x^106 + 14871*x^105 - 7287*x^104 + 13398*x^103 - 32710*x^102 + 20805*x^101 + 29734*x^100 - 14579*x^99 + 17483*x^98 - 16864*x^97 - 26745*x^96 + 3254*x^95 + 7280*x^94 - 29046*x^93 - 7531*x^92 - 8791*x^91 + 15033*x^90 - 1125*x^89 - 14713*x^88 - 12273*x^87 + 8616*x^86 + 2486*x^85 + 31810*x^84 + 27795*x^83 - 21731*x^82 + 21743*x^81 - 27595*x^80 - 3592*x^79 - 27206*x^78 - 32156*x^77 + 32124*x^76 - 11212*x^75 - 6662*x^74 - 23103*x^73 - 3660*x^72 - 31043*x^71 - 17131*x^70 + 24544*x^69 - 32326*x^68 - 31047*x^67 + 19814*x^66 + 10874*x^65 - 8449*x^64 + 11744*x^63 + 2245*x^62 - 967*x^61 + 9120*x^60 + 8983*x^59 - 24573*x^58 + 24885*x^57 + 15649*x^56 - 18970*x^55 + 7354*x^54 - 12282*x^53 - 22474*x^52 + 4395*x^51 + 8428*x^50 - 32592*x^49 + 25980*x^48 - 4599*x^47 + 16310*x^46 + 18559*x^45 + 22897*x^44 + 19080*x^43 - 26065*x^42 - 9*x^41 + 29202*x^40 + 2121*x^39 - 5004*x^38 + 5299*x^37 - 28301*x^36 - 13519*x^35 + 24241*x^34 + 529*x^33 - 20574*x^32 - 27391*x^31 + 31976*x^30 + 22824*x^29 - 31410*x^28 - 20976*x^27 + 21661*x^26 - 15132*x^25 + 1905*x^24 - 30870*x^23 + 18109*x^22 - 17373*x^21 + 5342*x^20 - 22447*x^19 + 1893*x^18 - 17545*x^17 + 30097*x^16 - 21731*x^15 + 17390*x^14 + 10991*x^13 - 5384*x^12 + 15960*x^11 + 24268*x^10 - 29867*x^9 + 22532*x^8 + 10133*x^7 - 26576*x^6 - 5742*x^5 - 16252*x^4 + 13019*x^3 - 25984*x^2 + 14004*x + 22500
hx = -11891*x^159 + 16347*x^158 - 32137*x^157 + 14988*x^156 + 16657*x^155 - 25785*x^154 - 21976*x^153 - 31745*x^152 - 4232*x^151 + 29569*x^150 + 27140*x^149 + 19617*x^148 - 16656*x^147 + 8925*x^146 + 8728*x^145 - 8802*x^144 - 10794*x^143 - 28159*x^142 - 6454*x^141 - 10259*x^140 - 19169*x^139 - 14357*x^138 + 3501*x^137 + 9885*x^136 - 7441*x^135 + 18268*x^134 - 27183*x^133 + 26085*x^132 + 19147*x^131 + 17153*x^130 - 22887*x^129 + 32476*x^128 - 21698*x^127 + 19138*x^126 + 11585*x^125 + 22755*x^124 - 5920*x^123 + 7581*x^122 + 25973*x^121 + 13787*x^120 - 22762*x^119 + 29207*x^118 - 17916*x^117 - 11502*x^116 + 18275*x^115 + 318*x^114 - 6890*x^113 - 22751*x^112 - 27677*x^111 - 11114*x^110 + 8623*x^109 - 15725*x^108 - 6835*x^107 - 8288*x^106 - 5235*x^105 - 28697*x^104 + 10696*x^103 + 17117*x^102 + 24696*x^101 - 7801*x^100 - 31874*x^99 - 17668*x^98 - 11204*x^97 + 19147*x^96 + 24644*x^95 - 29380*x^94 - 26237*x^93 - 27390*x^92 + 19982*x^91 + 4074*x^90 - 17248*x^89 - 11027*x^88 - 32690*x^87 + 5124*x^86 - 20823*x^85 - 11779*x^84 + 13781*x^83 + 29356*x^82 - 9740*x^81 - 31484*x^80 - 540*x^79 + 32360*x^78 + 24795*x^77 - 8864*x^76 + 17363*x^75 + 9670*x^74 + 32268*x^73 + 17961*x^72 + 6388*x^71 + 580*x^70 + 128*x^69 + 339*x^68 + 3412*x^67 - 4519*x^66 - 25056*x^65 + 6096*x^64 + 18720*x^63 - 5338*x^62 + 16910*x^61 + 3353*x^60 + 15433*x^59 - 28053*x^58 - 18883*x^57 + 7688*x^56 - 31198*x^55 + 9950*x^54 - 9388*x^53 + 21235*x^52 + 2847*x^51 + 24383*x^50 + 19431*x^49 + 21244*x^48 - 8498*x^47 - 28998*x^46 + 962*x^45 + 20579*x^44 + 28002*x^43 - 6040*x^42 + 4241*x^41 + 11655*x^40 - 32419*x^39 + 21531*x^38 + 7348*x^37 - 5503*x^36 + 29820*x^35 + 28896*x^34 + 8754*x^33 + 17978*x^32 + 7552*x^31 + 27240*x^30 - 29515*x^29 - 20322*x^28 + 2201*x^27 + 8857*x^26 - 50*x^25 - 3780*x^24 - 12138*x^23 + 10893*x^22 + 23133*x^21 + 6142*x^20 - 23798*x^19 - 15236*x^18 + 32564*x^17 + 25683*x^16 - 24010*x^15 - 4355*x^14 + 22552*x^13 - 27155*x^12 + 27649*x^11 + 17781*x^10 + 7115*x^9 + 27465*x^8 - 4369*x^7 + 24882*x^6 - 11675*x^5 - 612*x^4 + 12361*x^3 + 20120*x^2 + 6190*x - 10843
print('-------decrypt------')
qq = x^N-1
pp = y^N-1
hn = [int(x) for x in hx.coefficients()]
n = len(hn)
A1 = matrix.identity(n)
A0 = matrix.zero(n)
Aq = matrix.identity(n) * q
Ah = matrix(ZZ, [hn[-i:] + hn[:-i] for i in range(n)])
M = block_matrix([A1,Ah,A0,Aq],nrows=2)
L = M.LLL()
v = L[0]
f = list(v)[:n]
g = list(v)[n:]
fx = Q(f)
fy = P(f)
gx = Q(g)
Fqx = fx.inverse_mod(qq)
Fpy = fy.inverse_mod(pp)
#hxx = (Fqx*gx).mod(x^N-1)
#print(hxx==hx)
ax = (fx*ex).mod(qq)
an = [int(x) for x in ax.coefficients()]
#中心提升(centerlift),使域范围从[0,q)变换到(-q/2,q/2)
for i in range(len(an)):
if an[i] > q//2:
an[i] -= q
ax = P(an)
print(ax)
out = (Fpy * ax).mod(pp)
print(out)
print(bytes(out.coefficients()))
铜匠的世界
有个师傅说见过,但一直没找到是哪个比赛,最后终于破案是SEETF2023_shared。首先需要剪枝分解n,已知两个sqrt值异或的结果,利用异或值遍历根号p和根号q的对应比特位的所有可能取值,在遍历时设置根号p根号q低位比特全为1,乘积得到n1,要求n1大于n;同理设置比特全为0,乘积得到n0,要求n0小于n。这样遍历得到若干组根号p根号q,一定有一组是正确的根号p(要求p是两个因子中较大那个)。正确性验证:
from Crypto.Util.number import *
from math import isqrt
p, q = getPrime(512), getPrime(512)
n = p * q
# 必须保证p是更大的那个因子
if q > p:
p,q = q,p
hint = isqrt(p) ^ isqrt(q)
p_ = isqrt(p)
print(p_)
# yp = isqrt(p)**2
# yq = isqrt(q)**2
# print(bin(p)[2:])
# print(bin(yp)[2:])
# print(bin(q)[2:])
# print(bin(yq)[2:])
hint = bin(hint)[2:].rjust(256,'0')
P = []
def backtrace(p,q,t):
if t == 256:
if int(p,2) not in P:
P.append(int(p,2))
return
if t > 0:
if int(p,2) < int(q,2):
return 0
p0 = int(p.ljust(256,'0'),2)
q0 = int(q.ljust(256,'0'),2)
p1 = int(p.ljust(256,'1'),2)
q1 = int(q.ljust(256,'1'),2)
if int(p,2) ^ int(q,2) != int(hint[:t],2):
return 0
if (p0**2 * q0**2 > n):
return 0
if ((p1+1)**2 * (q1+1)**2 < n):
return
pos_p = [p+'0',p+'1']
pos_q = [q+'0',q+'1']
for p in pos_p:
for q in pos_q:
backtrace(p,q,t+1)
backtrace('','',0)
print(P)
print(len(P))
print(p_ in P)
# 结果一定是true
第二步需要测试isqrt再平方得到的p_和p的精度差别,经测试大概率高254-256比特准确:
from math import isqrt
from Crypto.Util.number import getPrime
p = getPrime(512)
q = getPrime(512)
if q > p:
p,q = q,p
p_ = isqrt(p) ** 2
for index in range(300):
if bin(p)[2:][index] == bin(p_)[2:][index]:
continue
else:
print(index)
break
第三步需要分析已知p高位攻击最少需要多少比特,因为已知256比特肯定是不够的一定要爆破。与此同时还需要兼顾small_root的效率,因此beta不要太大。最后得到的参数如下,需要已知264比特(512位p):
n= 67518754871056493015937553063056605148447516393244848436046567143008151906615713710596915778332474673092876025522093320232790051070406616314726673930019394466125551013510164830083948320739951978945250453462682446270710051172851054615279542021789378525896262943610565856273307453792400589396717465938309926917
ph = 21210174215655240909139072477252472483513350457108668654453356707958281305885371
pbits=512
print(ph.nbits())
kbits=pbits - ph.nbits()
ph = ph << kbits
PR.<x> = PolynomialRing(Zmod(n))
f = x + ph
roots = f.small_roots(X=2^kbits,beta=0.40,epsilon=0.01)
print(roots)
最后爆破msb的8位即可,后来看大佬博客了解到爆lsb更好,因为最低位为1已知,这样就只需要爆7位。即使是这样均衡各方面的复杂度,也需要爆破好几个小时,我最后没有跑完,不过感觉分析至此结果也不重要了。
from tqdm import tqdm
P = [112429064499829317536109655488565720356319606791895012400928462859086364101584, 112429064499829317536109655488565720356319606791895012400928462859086364101585, 112429064499829317536109655488565720356319606791895012400928462859086364101588, 112429064499829317536109655488565720356319606791895012400928462859086364101589, 112429064499829317536109655488565720356319606791895012400928462859086364101602, 112429064499829317536109655488565720356319606791895012400928462859086364101603, 112429064499829317536109655488565720356319606791895012400928462859086364101606, 112429064499829317536109655488565720356319606791895012400928462859086364101607, 112429064499829317536109655488565720356319606791895012400928462859086403132456, 112429064499829317536109655488565720356319606791895012400928462859086403132457, 112429064499829317536109655488565720356319606791895012400928462859086403132462, 112429064499829317536109655488565720356319606791895012400928462859086403132463]
n = 85404423344841677974087657659736161235661371072424467828040714876602706438511794670195915251038316685200550396898521246532238184171610202260808362573973358649489859739377219665083353960986881177279315590581777896976153899765953910931555330824054172366095461986394627542626117519624886018101305667394230690241
c = 19771222413844352631385715488753476758377273736688852768996964594019231638669697870409256892886494956719082541038530128231778575768552216334354854019126139003782852207071549956953446472517410158388833668611141062328959917017080292879996106665465487753670322759387144032463518586362415629216383494479440197516
pbits=512 #p原本的位数
for _ in P:
p_ = _ ^ 2
ph = int(bin(p_)[2:2+256],2)
print(ph.bit_length())
ph_ = ph << (pbits - ph.bit_length())
kbits=pbits - ph.bit_length() - 8
PR.<x> = PolynomialRing(Zmod(n))
for i in tqdm(range(2^8)):
f = x + ph_ + 2 ^ kbits * i
roots = f.small_roots(X=2^kbits,beta=0.40,epsilon=0.01)
if len(roots) > 0:
print(roots)