赣网杯 2022

cry1

祥云原题,原理还是一知半解的,但是直接打就行。

from Crypto.Util.number import *
n = 226165344948523695550317829045043301755038098520452624660349292451995383453438289393781798353852345351793447259067034277175312000439714746707076461950784526936960213165522383440080690205136204470885632591338647238110900688476644840652840550811475271011865045295673906950241527927296639555904136659503883578477
e = 5567244806132990650525283298184362097543657183189728255568114179202725826111751535660207402892872159118913249819234722178944445439968738188714785145503922061686027757846021298576445706913642685977037770387737999
c = 57682158710465983171562026269739297396728817506153693021896820074106872415768816411139367981754433123318218398135998490673098044266600075040944872524869723199130235787419190583390252662209383842910402954721426214605921626460687965255321698030504911332211630203201003008746669994467884389565443089663096988198

gamma = 320/1024
delta = 135/1024
m = 2
tau = (1 / 2 + gamma - 4 * delta) / (2 * delta)
t = ZZ(floor(tau * m))

X = ZZ(floor(n ^ delta))
Y = ZZ(floor(n ^ (delta + 1 / 2 - gamma)))
Z = ZZ(floor(n ^ (delta + 1 / 2 - gamma)))
W = ZZ(floor(n ^ (2 + 2 * delta - 2 * gamma)))
R = W * X ^ (2 * (m - 1) + t) * (Y * Z) ^ (m - 1)

# assert X ^ (7 + 9 * tau + 3 * tau ^ 2) * (Y * Z) ^ (5 + 9 * tau / 2) < W ^ (3 + 3 * tau)

P = PolynomialRing(ZZ, 'x,y,z')
x,y,z = P.gens()

# we know that ed = k(2gab) + 1 = k(p - 1)b + 1 = ka(q - 1) + 1
# we can multiply the last two expressions to get a semi-symmetric equation for
# (ed)^2, of which we want to find its roots
f = e^2 * x^2 + e * x * (y + z - 2) - (n - 1) * y * z - (y + z - 1)
assert f.constant_coefficient() == 1

M = set()
S = set()
# generate monomials
# S contains monomials of f^{m - 1} with x-shifts
# M contains monomials of f^{m} with x-shifts \setminus S
for i3 in range(0, m):
    for i2 in range(0, m):
        for i1 in range(0, 2 * (m - 1) - (i2 + i3) + t + 1):
            S.add(x ^ i1 * y ^ i2 * z ^ i3)
for i3 in range(0, m + 1):
    for i2 in range(0, m + 1):
        for i1 in range(0, 2 * m - (i2 + i3) + t + 1):
            M.add(x ^ i1 * y ^ i2 * z ^ i3)
M_S = M - S
M_S = sorted(M_S)
S   = sorted(S)
M   = sorted(M)

# use a dict to map each shift polynomial with its lowest order monomial to
# make diagonalizing the basis matrix easier
g   = {}

# generate shift polynomials
# the shift polynomials are generated with a polynomial derived from f (mod R)
# namely ff = a0^{-1} * f (mod R) such that the constant term of ff is 1
# i am fairly certain any polynomial with constant term 1 and the correct roots
# can be used here, although i have only tested it with ff and f
ff = f.change_ring(Zmod(R)).change_ring(ZZ)
for mono in S:
    i1, i2, i3 = mono.degree(x), mono.degree(y), mono.degree(z)
    fn = mono * ff(x, y, z) * X ^ (2 * (m - 1) + t - i1) * Y ^ (m - 1 - i2) * Z ^ (m - 1 - i3)
    fn = expand(fn(x * X, y * Y, z * Z))
    g[mono] = fn
for mono in M_S:
    fn = R * mono
    fn = expand(fn(x * X, y * Y, z * Z))
    g[mono] = fn

npolys = len(g)
nmonos = len(M)
print("polynomials: {}".format(npolys))
print("monomials:   {}".format(nmonos))
assert npolys == nmonos

B = Matrix(ZZ, npolys, nmonos)
C = Matrix(ZZ, npolys, nmonos)

for row, mono in enumerate(M):
    i1, i2, i3 = mono.degree(x), mono.degree(y), mono.degree(z)
    for c, mono_ in g[mono]:
        col = M.index(mono_)
        C[row, col] = 1
        B[row, col] = c

    # assert that diagonal elements are what they should be
    idx = M.index(mono)
    if mono in S:
        assert B[idx, idx] == X ^ (2 * (m - 1) + t) * (Y * Z) ^ (m - 1)
    elif mono in M_S:
        assert B[idx, idx] == R * X ^ i1 * Y ^ i2 * Z ^ i3
    else:
        raise Exception("what")

print(C.str())

# assert triangular form
for col in range(nmonos):
    for row in range(col + 1, npolys):
    # for row in xrange(col):
        assert B[row, col] == 0
    assert B[col, col] != 0

print("LLL...")
BB = B.LLL(algorithm='fpLLL:proved', fp='rr')
CC = Matrix(ZZ, npolys, nmonos)
for row in range(npolys):
    for col in range(nmonos):
        if BB[row, col] != 0:
            CC[row, col] = 1
print(CC.str())

# helper to construct a polynomial from coefficients
def topoly(r):
    RR = PolynomialRing(QQ, 'x,y,z')
    pol = 0
    for col in range(nmonos):
        pol += r[col] * M[col]
    pol = RR(pol(x / X, y / Y, z / Z))
    for c, _ in pol:
        assert c.is_integer()
    return P(pol)

# pull out h1, h2
hv = [expand(topoly(r)) for r in BB]
h1, h2 = hv[0:2]

# at some point we need to polynomial engines to something that can solve for
# roots, the default univariate engine works
s, = PolynomialRing(ZZ, 's').gens()

# these should be algebraically independent
assert h1.gcd(f).degree() == 0
assert h2.gcd(f).degree() == 0
assert h1.gcd(h2).degree() == 0

# take care that resultants are computed with f and not ff, which is a
# polynomial mod R
# these resultants eliminate z
h1x = h1.resultant(f, z)
h2x = h2.resultant(f, z)
hh  = h1.resultant(h2, z)

# this eliminates y
hy = h1x.resultant(h2x, y)

# now we can solve for roots via back substitution
d = []
for r, m in hy(x=s).roots():
    if r == 0:
        continue
    d.append(r)
assert len(d) == 1
d = d[0]

ka = []
for r, m in hh(x=d, y=s).roots():
    if r == 0:
        continue
    ka.append(r)
# f(x, y, z) = f(x, z, y) so we should have two solutions here
assert len(ka) == 2
ka = ka[0]

kb = []
for r, m in f(x=d, y=ka, z=s).roots():
    if r == 0:
        continue
    kb.append(r)
assert len(kb) == 1
kb = kb[0]

print("found d  = {}".format(d))
# 用d解密

cry2

首先第一部分的椭圆曲线是奇异的,即\(\small 4a^3+27b^2 mod p=0\),这种曲线的脆弱性在于其容易找到奇点并通过换元与\(\small y^2=x^3 modp\)同构,并转化到数域上求解dlp——详见参考资料

image
第二部分的rsa是经典论文里的第一种attack,注意由于是标准rsa所以参数z=1,那么构造一元copper即可求解。
第三部分是\(p^k\)有限域上的dlp,因为\(p^7\)已经比flag长所以q上的离散对数不用管了。具体操作就是转化为p-adic field上的dlp。最后给一个exp:

# 奇异曲线的dlp
p=121214699563163221600396985947034565543733038965924158879531736409999381372719
a=242429399126326443200793971894069131087466077931848317759063472819998762745438
b=606073497815816108001984929735172827718665194829620794397658682049996906863595
P = (106184556228231416346741068038440827029883559538808315140596781295670517173518, 8660239066577797123339324161343234387431273668128405633843568569576177837746)
Q = (19340631967671197050020386277019943687310503352075178625699396355667847281791, 60123743100919663876555030026689507680988172884161606252674847415633912950078)
# 验证是奇异曲线
print((4*a^3 + 27*b^2)%p)
# 做同构再dlp,会很容易
Fp = GF(p)
Px, Py = P
kPx, kPy = Q
k = (Fp(kPx) / Fp(kPy)) / (Fp(Px) / Fp(Py))

print(f'{k}')
from Crypto.Util.number import *
part1 = long_to_bytes(int(k))

r = 7
e = 5117361311133743032945459437001701377797311468233193508181647312549949887586775613699751748516434528742601341462420058950692435479684129919400934233630543106085840324860375993131472640348847844809287257457117800223313792719349416901225327992088506064749020530478869731525088882898744582589260515686276726164573934302450643235007309138290997676036222641561151800267779837538635483450340889088974555447750568842239157916502494428296957988605219878809523646298116025293406325895856524371722750273578291882726017729389038721803905543476466257308111268740274302779060991481043026937680784383146970421597088995847727186086488210237247597909360274678826369655298328454553131364900516422484828973566166801702757224451057755670092214340109224028903865028665672510317444457347367601900374008829970842014886902522584726733150890721700002177372721399721758411854458424103195735375608279439681017795759753332009915451339686296476442870452345728706124488833510757132863615067996927728862113679661282107793240090029270775576185496158646785136529890263841863434451355615103668916266059942101356884690770914905246631845978415602806804453587071114935342046327546575634368013458159533376648797251042333834828194403410905412286715742251390274793423989085746942547111224062306270953109010257908516493517072094995162003125927674134706237624885034741725504078111564450419056170792076019296521234630840603937435276435557596048198840645340128421350089477438485479463739678065657863983991677726081409314495896511923632154385587851418164639442367734089796431949822934562995475657023426016725073105088694845731298207309003791077838673009736651943937905539564969512129393665942200781627767535893375691082645236158094019072463239051913112937176121251215796327860655548135174834884048029320237387538336355309973316637508896054445173550482853183276200197754412140810322207972936333353893384028024815101886666166109249636800209781857784758222158172523731810678105455676831586570116438096023289776736864579594819693720876983685922512928436869679186932179118701808089869677037981206625931375277014065986897433253215142510214621704559844133169738095313305381318697198845030949759402326159360523460784355694187702446205546152730215511926304586414278340282210940487821726658340310714971075539825283298372960797065614393106328310386766774636594299631256678302644662606869870955049903526912298623126056589739271872292936637383943555919318405193264475293098927407666713613893462102528097369426614171870242
n = 48378697136314948055042568333082624951790787304549593006826413582729248623048594287582620166429611076768309894364199249821261783248469510348423960344283589662791458059202893381839166715784972525889346127460104453459169037673074371973833815847435868700548702779657815493991664027018236791503428745483359932452947636147198344039291271428515063972695570684552170372328619533136766377631203847937676468449558649538395882089333983841029668487391893528460177324028796103184743567370785881499126372899929828736059153355602404386299366620749692794811460567081871724655197986831888892409602597460747311064668563159124424489492414177632242350017625509821063636062944784889530514851661038278401828138790282165637730846020342931516891869738302536243031814197262209347307928558945988274560749563008412193434147429228889709104186248300933778761461589810976297891545902779410163792015267725259698788796004606445553369318973956959317796061669981130999740973718675559523020924008992611838667997910501781856648381591425565286125187762084049771917901305506943056439198824131586539918715717499776548458793828794680753491162602815978514099024595116584942587281555459687826213410710693717930803949990032564367016576839996969401087816460895492893998161619868352669790138888570218500864418616922801615108964690000474087841646357769457089325215353361565225520317804460717831955814601476338522294124492269637706774889495202485550233537306260682728384631328143185698804265077326274456531240160985497378705252168665001975262852728427625628787711514549965690408844980567884755127118881593443368040602237159540226926159554313324490734538150232982161920374720148523192687110099214727769537230122119649713923473084018486652127436993990535775663276669715912383293095135505367921763810906511718236781614503688223481916484369567933619493314373542201356785047815983615742121078762148755902505905976630102294524755228370355648360747091523419870066603672383704603423699987369903561529936968916150024021458419443774624505797006839115423613041826523642442481149964927891342998060102459635543131855368198908453515791942579254889951889542422439096367319153440253851902109214736071271405372557795672646960413831576099361428063220716961797078080440039926003421733370172610651937025104638721902220365420200671780534365364409544052805159647489745257262815658178413124281643682430225907892124295013278687434189817392350249755806623664729646317498859332714930579944311308003115250566604544240180731617634498334969
c = 22016704411488940982133231356868078738178910066417644162065258194717833460873315013711507350282885012556105239867001475647697717206786940668150352274652192085022210603492836810647958659589075068366239125934672276472057548990586631022279281845063351201221067230846971218486696712503105164669832374447345335498116648322996046536152485338199255562040477128907385437689225816199379935407277702782738903521315715116828568320314532596655487947586262200454186170812398721922203444473359675373257402665138909099845642799268416478533961518706690394308784338630494306298693098681274834037059934667029098349170317659462394362934884624598023280053367676505353650467666037348647978302619275091673484132202050398944440392177903887414890391117597909177733698363751422445003688964275586272255350611758293578947372840321468867711640340144516761416165052611819783038818589684782779649307887177770373634728467891589835918047358618791935442591584451086723425149432241017105690875969203510761773260373000407714773575601945447567449385105041752828296799966521362518376104632083008339034747181257770041518545476431760775810876844281545384284920253160206413665106846524912521652391102442727672586660726823182556145694391782609661581850158508575109853236718449072258853272292577209782429495271447423949815906821732654318858576367348867262980421351605809252684422727133310811673657330492459653275174324787976378994523187324373913793254529460789454762255806491056187398274167206509824854145997885659565779040052411395298440066054627390235091932209459185201536876630949558616199176310042251282005063876126609328428173782236633173747797976021787792687655740286867721403421110121929527446115842125460521482139256810634636679835186617015608856965316555820371303295042389974436384861951250412709157116449610859293262338781471401003546208233590741888677189588143776309506187908119436553306130647626318205132925618525902083767621661879700933954271677215866359633161705188823784467468066651933678597569686053975506385073413437406639911200064884958305667369682507580035421088232767775921772394088346686676660696658561042977230189734917180631567155363880505331297587581589914724383490103440729827744271750548289484745382040137153777858336457352343529054484871491327302644180690550793241358503819334338724769023289753926314068879469646465879492810583624710161495442265054980042367068000714196772054062644881451050603728030098275470392706107394887223498874985241391334871127468066643929620461699578414569

PR.<x> = PolynomialRing(Zmod(n))
f = e*x - 1
f = f.monic()
roots = f.small_roots(X = 2^4096 , beta=0.4)
d = roots[0]

from gmpy2 import iroot
from Crypto.Util.number import *
p_ = gcd(e*d-1,n)
p = iroot(int(p_),6)[0]
q = n//(p^7)
assert p^7 * q == n 

Qpp = Qp(p, prec=7)
print(Qpp)
s2 = (Qpp(c).log() / Qpp(e).log()).lift()
part2 = long_to_bytes(s2)
print(part1 + part2)

cry3

看到很多参数都给了比特信息,基本确定是造格子规约。只是化简的过程比较麻烦。首先根据p q的生成方式把已知式子列一下(p和q是一样的所以只写p了):
\(\small a_pE+b_pK_p=1,p=-b_p+E+1,\)
\(\small d_p=a_p + k_p\),则易得\(\small Ed_p-k_p(p-1)=1,Ed_q-k_q(q-1)=1\),改写为\(\small Ed_p=k_p(p-1)+1,Ed_q=k_q(q-1)+1\)zz,两边分别相乘,并作一些化简得到\(\small E^2d_pd_q-k_pk_q(n-1)=k_pk_q(-p-q)+2k_pk_q+k_p(p-1)+k_q(q-1)+1=k_pk_q(-p+1)+k_pk_q(-q+1)+k_p(p-1)+k_q(q-1)+1\),利用\(\small k_p(p-1)=Ed_p-1\)把以上式子中的部分进行替换得到最终需要的结论:\(\small E^2d_pd_q+E(d_p(k_q-1)+d_q(k_p-1))-k_pk_q(n-1)=k_p+k_q-1\),由于k是400比特,所以等式右端大约也就是400比特。造格子:
image
M取2^400即可,这样可以让整个格最短向量的界上升到960比特左右,而LLL规约后的向量大约在800多比特,所以是可行的。如果不乘M调系数是无法规约的。规约之后可以利用向量的后两维解方程得到k,然后求出p q即可解密。

E= 145106294105031284362950025863529581747975861699820575710872716519879803001392108419450056017622997630126276746554771656122532972639414248565300835010881208733690317975825283717056444554763316279849402612931689513790553913814829224657863376765661796202264396345600888403461230631203348607241016471422573987581
n= 44146216754179716722914989774179545609003622919133954513612183365882143185648106448428976865616794364028711539848793072635268083809473736628189721636749099362357309849620541871571763282347330516151877113940331967499040686592378429548637013317457534594446645795078740141793093671629367727580553491215650337659527664705853572883730490883606327292351189552684783556726745519069083076011853815506574017326892680398272431716287020908845624185560350752642219469508595239978684428357590946555321280480160960814914981382127666519241796268901712746927364456562374629908387801426574825886691891613827829901620362221716562729181
c= 42849954097468071726084946569343866748913580243693005484016477540655859876131867406160328063659045626546696925974783645320154966183202087150055162449812095144585221589345118079815257465944358288811363045125860701872706943518864751664960009957542024032708923424342364685385744625812611804391908032187252468394391715156637995783612091781280489452909027099099798074134765334858069523070373919122908726611177406605539137633787078228935029969970499482879713485023528914042281734061900906000317898016866589414229957899882390267865157996173644571590488588106926533461407231265146431839909395332178222814838553730197295527269
M = 2^400
A = [[1,0,M*E],[0,1,M*(1-n)],[0,0,M*E^2]]
A = Matrix(ZZ,A)
x,y,z = A.LLL()[0]
u = y
v = z/M + 1
#p.<kp> = ZZ[]
#p.<kp> = Zmod()[] 
p.<kp> = PolynomialRing(ZZ)
f = kp^2-v*kp+u
k = ZZ(f.roots()[0][0])

g,a,b = xgcd(E,k)
p = gcd(-b+E+1,n)
print(p)
q = n/p
phi = (p-1)*(q-1)
d = inverse_mod(65537,phi)
m = pow(c,d,n)
print(bytes.fromhex(hex(m)[2:]))
posted @ 2022-12-11 20:52  ZimaB1ue  阅读(257)  评论(0编辑  收藏  举报