from Crypto.Util.number import * from secret import flag
bit_length = len(flag) * 8
p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab K = GF(p) E = EllipticCurve(K, (0, 4)) o = 793479390729215512516507951283169066088130679960393952059283337873017453583023682367384822284289 n1, n2 = 859267, 52437899
while(1): G1, G2 = E.random_element(), E.random_element() if(G1.order() == o and G2.order() == o): P1, P2 = (o//n1)*G1, (o//n2)*G2 break
cs = [(randrange(0, o) * P1 + randrange(0, o) * G2).xy() if i == "1"else (randrange(0, o) * G1 + randrange(0, o) * P2).xy() for i inbin(bytes_to_long(flag))[2:].zfill(bit_length)] print(cs)
p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab K = GF(p) E = EllipticCurve(K, (0, 4)) o = 793479390729215512516507951283169066088130679960393952059283337873017453583023682367384822284289 n1, n2 = 859267, 52437899 Cxy = [......] C = [E(xi,yi) for xi,yi in Cxy]
H=C[0]*n2 s=0 for i inrange(0,len(C)): k=(H.weil_pairing(C[i]*n2,o)) s<<=1 s|=bool(k-1) from Crypto.Util.number import * print(long_to_bytes(s)) #SUCTF{We1come__T0__SUCTF__2025}
2.[SUCTF2025]SU_RSA
题面很简单,给出了 $d$ 的高 $512$ 位,要求分解 $n$。
1 2 3 4 5 6 7 8 9 10 11 12 13
from Crypto.Util.number import * from hashlib import sha256 flag = open("flag.txt").read() p = getPrime(512) q = getPrime(512) e = getPrime(256) n = p*q d = inverse(e,(p-1)*(q-1)) d_m = ((d >> 512) << 512) print("d_m = ",d_m) print("n = ",n) print("e = ",e) assert flag[6:-1] == sha256(str(p).encode()).hexdigest()[:32]
from Crypto.Util.number import * dm = 54846367460362174332079522877510670032871200032162046677317492493462931044216323394426650814743565762481796045534803612751698364585822047676578654787832771646295054609274740117061370718708622855577527177104905114099420613343527343145928755498638387667064228376160623881856439218281811203793522182599504560128 n = 102371500687797342407596664857291734254917985018214775746292433509077140372871717687125679767929573899320192533126974567980143105445007878861163511159294802350697707435107548927953839625147773016776671583898492755338444338394630801056367836711191009369960379855825277626760709076218114602209903833128735441623 e = 112238903025225752449505695131644979150784442753977451850362059850426421356123
from subprocess import check_output from re import findall from sage.allimport *
defflatter(M): # flatter z = "[[" + "]\n[".join(" ".join(map(str, row)) for row in M) + "]]" ret = check_output(["flatter"], input=z.encode()) return matrix(M.nrows(), M.ncols(), map(int, findall(b"-?\\d+", ret)))
defmatrix_overview(BB): # see the shape of matrix for ii inrange(BB.dimensions()[0]): a = ('%02d ' % ii) for jj inrange(BB.dimensions()[1]): a += '0'if BB[ii, jj] == 0else'X' if BB.dimensions()[0] < 60: a += ' ' print(a)
delta = f.degree() # 度delta N = f.parent().characteristic() # 模数N PR = PolynomialRing(ZZ, 'x') x = PR.gen()
Zm = f.base_ring() # Zmod(N) f = f.change_ring(ZZ) # ZZ下f(x) ifnot f.is_monic(): # 首一 f = f.monic() # f = f * f[delta].inverse_mod(N)
m = ceil(max(beta * beta / (delta * epsilon), 7 * beta / delta)) # m t = floor(delta * m * (1 / beta - 1)) # t #print('m={}, t={}'.format(m, t))
f_ij = [] for i inrange(m): for j inrange(delta): f_ij.append(x ** j * N ** (m - i) * f ** i) # shift g_ij(x) for i inrange(t): f_ij.append(x ** i * f ** m) # shift h_i(x)
monomials = [] for g in f_ij: monomials += g.monomials() # 统计所有出现的单项 x^i monomials = sorted(set(monomials)) # 去重并排序
M = Matrix(ZZ, len(f_ij), len(monomials)) # 行数为多项式个数,列数为所有单项可能个数 for i inrange(M.nrows()): for j, monomial inenumerate(monomials): M[i, j] = f_ij[i].monomial_coefficient(monomial) * monomial.subs(x=X) # g_ij(xX)和h_i(xX) #matrix_overview(M) # see assert M.nrows() == M.ncols() # 方阵 nrows()=ncols() B = flatter(M) # flater加速 #print('end LLL') for j inrange(M.nrows()): # 得到f(xX),构建f(x),求根检验 Cx = sum(ZZ(B[j, i] // monomials[i](X)) * monomials[i] for i inrange(M.ncols())) # construct polynomial, R = Cx.roots() # get roots roots = [Zm(r[0]) for r in R ifabs(r[0]) <= X] # check x0<=X roots = [r for r in roots if gcd(N, ZZ(f(r))) >= ZZ(floor(N ** beta))] # check gcd(f(x_0),N)>N^beta if roots: return roots # 返回root
from Crypto.Util.number import * N=102371500687797342407596664857291734254917985018214775746292433509077140372871717687125679767929573899320192533126974567980143105445007878861163511159294802350697707435107548927953839625147773016776671583898492755338444338394630801056367836711191009369960379855825277626760709076218114602209903833128735441623 h=56220299912083199824680953877514275031991586299490111910943821482768735249418 PR=PolynomialRing(Zmod(N),'x') x=PR.gen() e=112238903025225752449505695131644979150784442753977451850362059850426421356123 from tqdm import * for i in tqdm_notebook(range(64)): f=(2**6*x*e+i*e+h).monic() roots=Small_Roots_Univariate(f,e>>6,0.49,0.0085) if(roots): print(roots,i) break #[1579733723890583379944346027928995285091232963803321176752930674794829848032] 13
n = 32261421478213846055712670966502489204755328170115455046538351164751104619671102517649635534043658087736634695616391757439732095084483689790126957681118278054587893972547230081514687941476504846573346232349396528794022902849402462140720882761797608629678538971832857107919821058604542569600500431547986211951 e = 334450817132213889699916301332076676907807495738301743367532551341259554597455532787632746522806063413194057583998858669641413549469205803510032623432057274574904024415310727712701532706683404590321555542304471243731711502894688623443411522742837178384157350652336133957839779184278283984964616921311020965540513988059163842300284809747927188585982778365798558959611785248767075169464495691092816641600277394649073668575637386621433598176627864284154484501969887686377152288296838258930293614942020655916701799531971307171423974651394156780269830631029915305188230547099840604668445612429756706738202411074392821840 cf=continued_fraction(e/n**2) for i inrange(4,20000): k,d=cf.numerator(i),cf.denominator(i) if(e*d%k==1): print(d) break g=(e*d-1)//k print(g)
# The ship crashed into the sun, causing a massive magnetic storm #part of script msg = bytes_to_long(FLAG) n = p^5*q^2 phi = p^4*(p-1)*q*(q-1) e = 65537 d = inverse(d,phi) c = pow(m,e,n) print(c)
deffn(msg, n0): h = myhash(n0) ret = bytes([0] * 16) for b in msg: h.update(bytes([b])) print('{:032x}'.format(h.n%(2**128)),end=',') ret = xor(ret,h.digest()) return ret fn(b'\x00'*128,666).hex()
#python 3.12.1 from Crypto.Util.number import * from os import urandom from random import * from sage.allimport * flag = b'SUCTF{??????????????????????????????}'
classmyhash: def__init__(self,n): self.g = 91289086035117540959154051117940771730039965839291520308840839624996039016929 self.n = n
defxor(x, y): x = b'\x00'*(16-len(x)) + x y = b'\x00'*(16-len(y)) + y return long_to_bytes(bytes_to_long(bytes([a ^ b for a, b inzip(x, y)])))
deffn(msg, n0): h = myhash(n0) ret = bytes([0] * 16) for b in msg: h.update(bytes([b])) #print('{:032x}'.format(h.n%(2**128)),end=',') ret = xor(ret,h.digest()) return ret
n0=getrandbits(128) print('n0={:032x}'.format(n0)) msgarr=[bytes([1+i]+[0]*128) for i inrange(128)] resarr=[bytes_to_long(fn(msg1,0)) for msg1 in msgarr] M=[[bool(i&(1<<j)) for j inrange(128)]for i in resarr] val0=bytes_to_long(fn(bytes(128),n0)) target=bytes_to_long(b'justjusthashhash') target=val0^target y=[bool((target)&(1<<i)) for i inrange(128)] M=matrix(GF(2),M) y=vector(GF(2),y) ans=M.solve_left(y) msga=bytes(128) for i inrange(len(ans)): if(ans[i]): msga+=bytes([1+i]+[0]*128) print(fn(msga,n0)) #b'justjusthashhash' print(len(msga)*2) #16000+
为了方便调试,给他增加了一个函数,返回两个值:一个是 ret 的数值,还有一个是 $h.n$ 内部的值。
1 2 3 4 5 6 7 8
deffnTest(msg, n0): h = myhash(n0) ret = bytes([0] * 16) for b in msg: h.update(bytes([b])) d = h.digest() ret = xor(ret, d) return bytes_to_long(ret),h.n%(2**128)
n0=0xf3ad24a59d00d329a56273d2154d51f3 g=60836803250181415307496727382007595489 n=64 M=[[i==j for j inrange(n+1)]for i inrange(n+1)] M[-1][-1]=2**128 for i inrange(n): M[i][-1]=2**(n-i)*Integer(pow(g,n-i,2**128))%(2**128) M=matrix(ZZ,M)#*diagonal_matrix([1]*(n+1)+[2**2000]) M3L=M.LLL() for v in M3L: if(v[-1]==0): break s1=[110]*64 s2=[110+v[i] for i inrange(64)] print(bytes(s1)) print(bytes(s2)) d1,h1=fnTest(bytes(s1),n0) print(d1.hex(),h1%(2**128)) d2,h2=fnTest(bytes(s2),n0) print(d2.hex(),h2%(2**128)) """ b'nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn' b'kooopjknnmoomnnoopklnmnmhnlronpqnmlnmopnnnnnnnnnnnnnnnnnnnnnnnnn' af3bb53e332f1723690e9b8631f69e76 228056009380557728235158378943134817746 188ae78e8e8cf3752e5b3a3493c21909 228056009380557728235158378943134817746 """
defCheckVec(v): s1=[80]*(len(v)-1) s2=[80+v[i] for i inrange(len(v)-1)] for _ inrange(25): tmp=getrandbits(128) if(fnTest(bytes(s1),tmp)[1]!=fnTest(bytes(s2),tmp)[1]): returnFalse returnTrue defgetcollision(n): g=60836803250181415307496727382007595489 M=[[i==j for j inrange(n+1)]for i inrange(n+1)] M[-1][-1]=2**128 for i inrange(n): M[i][-1]=2**(n-i)*Integer(pow(g,n-i,2**128))%(2**128) M=matrix(ZZ,M) M3L=M.LLL() vec=[] for v in M3L: if(v[-1]==0): vec.append(v) ret=[] for v in vec: if(CheckVec(v)): ret.append(v[:-1]) return ret
#python 3.12.1 from random import * from Crypto.Util.number import * from sage.allimport * #------原题文件-------# classmyhash: def__init__(self, n): self.g = 91289086035117540959154051117940771730039965839291520308840839624996039016929 self.n = n
defxor(x, y): x = b'\x00' * (16 - len(x)) + x y = b'\x00' * (16 - len(y)) + y return long_to_bytes(bytes_to_long(bytes([a ^ b for a, b inzip(x, y)])))
deffn(msg, n0): h = myhash(n0) ret = bytes([0] * 16) for b in msg: h.update(bytes([b])) d = h.digest() ret = xor(ret, d) return ret #------测试函数-------# deffnTest(msg, n0): h = myhash(n0) ret = bytes([0] * 16) for b in msg: h.update(bytes([b])) d = h.digest() ret = xor(ret, d) return bytes_to_long(ret),h.n%(2**128) #------寻找碰撞-------# defCheckVec(v): #检查是否满足Test通过 s1=[80]*(len(v)-1) s2=[80+v[i] for i inrange(len(v)-1)] for _ inrange(25): tmp=getrandbits(128) if(fnTest(bytes(s1),tmp)[1]!=fnTest(bytes(s2),tmp)[1]): returnFalse returnTrue defgetcollision(n): g=60836803250181415307496727382007595489 M=[[i==j for j inrange(n+1)]for i inrange(n+1)] M[-1][-1]=2**128 for i inrange(n): M[i][-1]=2**(n-i)*Integer(pow(g,n-i,2**128))%(2**128) M=matrix(ZZ,M) M3L=M.LLL() vec=[] for v in M3L: if(v[-1]==0): vec.append(v) #return vec ret=[] for v in vec: if(CheckVec(v)): ret.append(v[:-1]) return ret #------产生测试数据-------# s=[] lens=35 while(len(s)<128): s+=getcollision(lens) lens+=1 s=s[:128] n0=getrandbits(128) print('0x{:032x}'.format(n0)) #------寻找128组碰撞并构建随机字符串-------# msG,msH=[],[]s Gall=b'' defmyRandString(lens): ret='' Table=('456GHIJKLMNOPQRSTghijklmnopqrst') for i inrange(lens): ret+=choice(Table) return ret for i inrange(128): v=s[i] si=myRandString(len(v)).encode() msG.append(si) Gall+=si msH.append(bytes([si[i]+v[i] for i inrange(len(v))]))
#------计算全G的hash结果,并和目标异或得到差分值-------# HashGall=bytes_to_long(fn(Gall,n0)) D=bytes_to_long(b'justjusthashhash') D=D^HashGall diffGH=[] curstat=n0 #------构建每一步g和h的差分-------# for i inrange(128): tG,tH=msG[i],msH[i] tgf,nxtstat,thf,nxtstatChk=fnTest(tG,curstat)+fnTest(tH,curstat) assert nxtstat==nxtstatChk diffGH.append(tgf^thf) curstat=nxtstat #------构建矩阵求解方程,判断每一步异或msg还是异或msh-------# M=[[bool(diffGH[i]&(1<<j)) for j inrange(128)]for i inrange(128)] y=[bool(D&(1<<j)) for j inrange(128)] M=Matrix(GF(2),M) y=vector(GF(2),y) ans=M.solve_left(y) #------构造最后字符串-------# finalMsg=b'' for i inrange(128): if(ans[i]): finalMsg+=msH[i] else: finalMsg+=msG[i] print(fn(finalMsg,n0)) print(len(finalMsg)) print(finalMsg) #可能的输出结果: #n0=0x0c4db02b41aa032cf28ac84dc7908f1e #b'justjusthashhash' #5432 #均为可见字符