SHCTF2024-week3-Crypto
博客做题法,除了最简单那题,其他都是偷的,lock等以后有机会再补把
太难了(哭
Crypto
babyLCG
from Crypto.Util.number import *
from enc import flag
seed = bytes_to_long(flag)
a = getPrime(400)
b = getPrime(400)
p = getPrime(400)
c = []
for i in range(3):
seed = (seed*a+b)%p
c.append(seed>>80)
print(f'a = {a}')
print(f'b = {b}')
print(f'p = {p}')
print(f'c = {c}')
想不出来,使劲偷。
(这已经不是参考了,原原又版版啊)
我们有:
\[H_2+L_2=a(H_1+L_1)+b\mod p\\
L_2=aL_1+(aH_1+b-H_2)\mod p\\
\]
记\(A_1=a,B_1=(aH_1+b-H_2)\mod p\)
继续推导有:
\[H_3+L_3=a(H_2+L_2)+b\mod p\\
L_3=aL_2+(aH_2+b-H_3)\mod p\\
将上面L_2,带入得:\\
L_3=a^2L_1+a(aH_1+b-H_2)+(aH_2+b-H_3)\\
\]
记\(A_2=a^2,B_2=(aB_1+(aH_2+b-H_3))\mod p\)
所以我们有一般式
\[L_{i+1}=A_iL_1+B_i\mod p\\
A_i=a^i\mod p\\
B_i=aB_{i-1}+(aH_i+b-H_{i+1})\mod p
\]
我们构造格
\[L=\left(
\begin{matrix}
p & 0 & 0 & 0\\
0 & p & 0 & 0\\
A_1 & A_2 & 1 & 0\\
B_1 & B_2 & 0 & 1\\
\end{matrix}
\right)\\
(k_1,k_2,L_1,1)L=(L_2,L_3,L_1,1)\\
最后为了使目标向量得所有元素大小相同,需要进行配平\\
让L得最后一行最后一个元素乘上一个K=2^{80}(seed缺失的位数)\\
最后L=\left(
\begin{matrix}
p & 0 & 0 & 0\\
0 & p & 0 & 0\\
A_1 & A_2 & 1 & 0\\
B_1 & B_2 & 0 & K\\
\end{matrix}
\right)\\
(k_1,k_2,L_1,1)L=(L_2,L_3,L_1,K)\\
\]
(代码直接抄了)
from Crypto.Util.number import long_to_bytes
a = 2441165060340363548034817419913152429437367671051257983130193376968866003652656064753193540692576823353722522219951236377
b = 2536384599388118977308934726385759683875116193910292140931807458602198040481977699550435249496535909362102559820360131151
p = 1898350626517014951217210423867648293636462375574846448952061608918022029275967066566474923728317050045578381447025802447
c = [1206170611286987749822509820930522025955557233442828617888124729629984583540215838639710785581993, 852222709497386792919622853438477061105763652894458161025475550177341850861286444913870176145661, 1304945544687728464084706289648969970911515894526834307083141183941320491375891396365871606911311]
h = [0] + c
length = len(h)
for i in range(length):
h[i] <<= 80
A = [1]
B = [0]
for i in range(1, len(h)-1):
A.append(a*A[i-1] % p)
B.append((a*B[i-1]+a*h[i]+b-h[i+1]) % p)
A = A[1:]
B = B[1:]
Ge = Matrix(ZZ,length,length)
for i in range(len(A)):
Ge[i,i] = p
Ge[-2,i] = A[i]
Ge[-1,i] = B[i]
K = 2**80
Ge[-2,-2] = 1
Ge[-1,-1] = K
for line in Ge.LLL():
if abs(line[-1]) == K:
L1 = line[-2]
seed1 = h[1] + L1
seed = (seed1 - b) * inverse_mod(a,p) % p
print(f"seed = {seed}")
print(long_to_bytes(seed))
Lattice
import gmpy2
from Crypto.Util.number import *
from enc import flag
m = bytes_to_long(flag)
n = getPrime(1024)
x = getPrime(200)
hint = (x*gmpy2.invert(m,n)) % n
print(f'n = {n}')
print(f'hint = {hint}')
\[h=x*m^{-1}\mod n\\
hm=x\mod n\\
m=x*h^{-1}+kn\\
构造格L=\left(
\begin{matrix}
1 & h^{-1}\\
0 & n\\
\end{matrix}
\right)\\
(x,k)L=(x,m)\\
最后直接输出m,发现不用配平,结束。
\]
说一句我认为构造格最重要的一点,就是让等式的一侧(一般为单个项)为未知的。
from Crypto.Util.number import long_to_bytes
n = 139375501266966354110560987602941579720343298682302380213629012399146702255224092464371860285892594606518682202746469996717869266755804902133065746523678610701447709661598475045236643942670878454454914242366823865911620343171523738762438337620932812380503714497659323917884890957898967721924886002184816388909
hint = 30111064015548195748229136433160596861378053894649564473559454623946601615359833481249637332444935789833334802877702902155500934637824299425212772699568531012251263573286943567743990513595674983034259871038496370389371165018799403318568607201602419538351281864014621535790322463730848699042720151828377672492
h_ni=inverse_mod(hint,n)
L=Matrix(ZZ,[[1,h_ni],
[0,n]])
L=L.LLL()
print(long_to_bytes(abs(int(L[0][1]))))
#b'SHCTF{1a7t1cE_lS_MADE_Of_LA_tt_1CE_O2}'q
大学×高中√
from Crypto.Util.number import *
from enc import flag
m = bytes_to_long(flag)
assert len(flag)==47
leak = cos(m).n(1000)
print(leak)
# -0.514023686073206542913652284141758854082245379077263654055666061096577058176030971969995601436755843124241044078251685287775109358081348663783038215543924400002063721828036115454284925587327024460032858795786136002614648983181900267223024426488593475898639044647928018383927532133726223655824966624723
之前比赛的题,当时不会,所以直接贴了。
\[leak=cos(m),我们知道三角函数每2k\pi是一个周期,所以我们有\\
m=arccos(leak)+2k\pi\\
构造格L=\left(
\begin{matrix}
1 & 0 & 1\\
0 & 1 & arccos(leak)\\
0 & 0 & 2\pi\\
\end{matrix}
\right)\\
有(m,-1,-k)L=(m,-1,0)\\
显然这个格出不了,需要配平,至于为什么这么配,这个我不知道,就慢慢试出来的。\\
L=\left(
\begin{matrix}
1 & 0 & 2^{750}\\
0 & 2^{375} & arccos(leak)*2^{750}\\
0 & 0 & 2\pi*2^{750}\\
\end{matrix}
\right)\\
有(m,-1,-k)L=(m,-2^{375},0)\\
\]
from Crypto.Util.number import *
#flag=b'SHCTF{'+b'\x00'*(47-6)
#print(len(bin(bytes_to_long(flag)))-2) # 375
leak = -0.514023686073206542913652284141758854082245379077263654055666061096577058176030971969995601436755843124241044078251685287775109358081348663783038215543924400002063721828036115454284925587327024460032858795786136002614648983181900267223024426488593475898639044647928018383927532133726223655824966624723
acos = arccos(leak)
RR = RealField(1000)
pi = RR(pi)
Ge = Matrix(QQ,[[1,0,2^750],[0,2^375,2^750*acos],[0,0,2^750*2*pi]])
Ge=Ge.LLL()[0]
m = abs(Ge[0])
print(long_to_bytes(int(m)))
#b'SHCTF{arcCo5_LE4RNED_1N_hIGh_5CHoO1_u5Ed_IatER}'
Approximate_n
from Crypto.Util.number import *
import gmpy2
from flag import flag
class gen_AGCD():
def __init__(self):
self.p = getPrime(512)
self.q = getPrime(512)
def enc_(self,M,e):
C = pow(M,e,self.p*self.q)
return C
def re_n(self):
n = self.p * self.q
return n
def re_approximate_n(self):
k = getPrime(512)
r = getPrime(247)
n_approx = k*self.p + r
return n_approx
if __name__ == '__main__':
e = 65537
m1 = flag[:len(flag)//2]
m2 = flag[len(flag)//2:]
Encrypt1,Encrypt2 = gen_AGCD(),gen_AGCD()
C1,C2 = Encrypt1.enc_(bytes_to_long(m1),e),Encrypt2.enc_(bytes_to_long(m2),e)
N1,N2 = Encrypt1.re_n(),Encrypt2.re_n()
N1_reveal = []
for i in range(3):
N1_reveal.append(Encrypt1.re_approximate_n())
N2_reveal = Encrypt2.re_approximate_n()
print('N1 = ',N1)
print('N1_reveal = ',N1_reveal)
print('N2 = ',N2)
print('N2_reveal = ',N2_reveal)
print('C1 = ',C1)
print('C2 = ',C2)
第一部分,根据论文https://eprint.iacr.org/2016/215.pdf的第三部分,具体原理我也不懂。(AGCD问题)
\[我们有x_i=k_ip+r_i\\
构造格L=\left(
\begin{matrix}
2^{248+1} & x_1 & x_2\\
0 & -x_0 & 0\\
0 & 0 & -x_0\\
\end{matrix}
\right)\\
得(k_0,k_1,k_2)L=(k_02^{248+1},k_0x_1-k_1x_0,k0x_2-k_2x_0)\\
取第一项除一下得到k_0,直接整除x_0得到p\\
\]
第二部分,偷的鸡块师傅的https://tangcuxiaojikuai.xyz/post/4a67318c.html 第一部分 1.12 12,具体原理还是参考上面那个论文的第五部分,但是这次我连看都看不懂。(ACD问题)
from Crypto.Util.number import *
N1 = 95220181639626796948143489111363011090242644821307671338154270835002234872743806643238045743730383147579107484367700436409496448813817802882720705692308647479031357497697641512864558224737946906678321719550292939790297201774030189554354483674392204774757404512862366152441023131093295296126511526758311787533
N1_reveal = [135155723555580971102472760772113547068449856046446854944834185144725761315605950196417754719294327893501350155917123418471539586751734839913060001278469803495357936187202804035231480363027024883649894394029336416980140164261450806845325519324810810467082188549167892975300709885928089524964332523979084819616, 108225506327736990488056174532377782531488789170481659195448002422578807037623697635657548142074567159473902317405281775338219092114459739427575748704020302366750567205951022768559028784623405841592241560555854170026194465021522071306555697601208669120660672533978751002577604163682049989736857050431577335988, 97902238601080686791205456188991250567366116257787701998068858649901314188048320624369804248648395722811017072099995983115879965009017127675781815863771820270952769969131391080759752609678760644627826776136946615977348372397823851983199152097271925548232778437840248637945701889965062651061992125582772864886]
N2 = 140467306170270103085247508412489910487748378129459335724515767186097064975754544045630037530915800592540391724032146546032522637400331469533944394808073412880910356816384584939641130518688696505047701134385883270706411370356446043518762317844784816655044013536852156232391544081389664919694551145695399468209
N2_reveal = 112361172352758758900704170210296813010289510849392179799708472107731966956610675285107363588332515564687781269380345968222030537131341680443039011164210540824825702663120697518389091670478368564009900422608869461335061183241377132579449529050747663021748003410091799048984189262111414502180481142308877537330
C1 = 31950452009658012741321403366243455956978705529042164534321777183203324554858632439237234885410149568398983557280801461287159709181598872210801564966331769742332023309821039892558563273355301616744286335388072082262778934580513252668404512993042262043925583364437774382631570617154342054943064279866085770928
C2 = 28043955361950149290736307328827214922496448239701009207491436374533557770205348310700271429655733973145555148184288870618672293135244638728814923159375304575547925591181048341809750424936159673404585158750785837663773658200516125280634048184681727065354159475141953332267189169344585136326725855832157455620
#https://eprint.iacr.org/2016/215.pdf
K=2^249
L=Matrix(ZZ,[[K,N1_reveal[1],N1_reveal[2]],
[0,-N1_reveal[0],0],
[0,0,-N1_reveal[0]]])
L=L.LLL()
p1=int(N1_reveal[0]//(abs(L[0][0])//K))
q1=N1//p1
flag1=long_to_bytes(int(pow(C1,inverse_mod(65537,(p1-1)*(q1-1)),N1)))
# https://tangcuxiaojikuai.xyz/post/4a67318c.html 第一部分 1.12 12
#15 [(-271336741980068587844448337263932213024816515815388263122784492996415507, 1)]
#14 [(13863439776247006048821931668679415913595054659189563401850065117344542701, 1)]
r=13863439776247006048821931668679415913595054659189563401850065117344542701
# print(int(r).bit_length()) #243
r=r+2^243*14
p2=GCD(N2,N2_reveal-r)
flag2=long_to_bytes(int(pow(C2,inverse_mod(65537,p2-1),p2)))
print(flag1+flag2)
#b'SHCTF{APPROxiMaTE_n_H4PpY_7hE_NEW_GGag_2_Da}'
"""from tqdm import *
from itertools import *
from multiprocessing import Pool
################################################ gen data
e = 65537
N = 140467306170270103085247508412489910487748378129459335724515767186097064975754544045630037530915800592540391724032146546032522637400331469533944394808073412880910356816384584939641130518688696505047701134385883270706411370356446043518762317844784816655044013536852156232391544081389664919694551145695399468209
m = 1
rho = 243
a = ["pad"] + [112361172352758758900704170210296813010289510849392179799708472107731966956610675285107363588332515564687781269380345968222030537131341680443039011164210540824825702663120697518389091670478368564009900422608869461335061183241377132579449529050747663021748003410091799048984189262111414502180481142308877537330]
def attack(ii):
a = ["pad"] + [112361172352758758900704170210296813010289510849392179799708472107731966956610675285107363588332515564687781269380345968222030537131341680443039011164210540824825702663120697518389091670478368564009900422608869461335061183241377132579449529050747663021748003410091799048984189262111414502180481142308877537330 - 2^243*ii]
################################################ params
t,k = 20,10
R = 2^rho
indices = []
for i in product([i for i in range(t+1)] , repeat=m):
if(sum(list(i)) <= t):
indices.append(["pad"] + list(i))
################################################ attack
PR = ZZ[tuple(f"X{i}" for i in range(m))]
X = ["pad"] + list(PR.gens())
poly = []
monomials=set()
for i in indices:
f = 1
for ij in range(1,len(i)):
f *= (X[ij] - a[ij])^i[ij]
l = max(k-sum(i[1:]),0)
f *= N^l
poly.append(f)
for mono in f.monomials():
monomials.add(mono)
################################################# LLL and resultant to find roots
L = Matrix(ZZ,len(poly),len(monomials))
monomials = sorted(monomials)
for row,shift in enumerate(poly):
for col,monomial in enumerate(monomials):
L[row,col] = shift.monomial_coefficient(monomial)*monomial(*([R]*m))
res = L.LLL()
vec1 = res[0]
h = 0
for idx,monomial in enumerate(monomials):
h += (vec1[idx] // monomial(*([R]*m))) * monomial
h = h.change_ring(ZZ)
res1 = h.monic().roots()
if(res1 != []):
print(ii,res1)
lists = [i for i in range(2^4)]
with Pool(64) as pool:
r = list(pool.imap(attack, lists[::-1]))
print(r)
"""
Shamir
from Crypto.Util.number import getPrime,bytes_to_long
import random
from os import getenv
BANNER = """
__ __ _ _______ _____ _ _
\ \ / / | | |__ __| / ____| | (_)
\ \ /\ / /__| | ___ ___ _ __ ___ ___ | | ___ | (___ | |__ __ _ _ __ ___ _ _ __
\ \/ \/ / _ \ |/ __/ _ \| '_ ` _ \ / _ \ | |/ _ \ \___ \| '_ \ / _` | '_ ` _ \| | '__|
\ /\ / __/ | (_| (_) | | | | | | __/ | | (_) | ____) | | | | (_| | | | | | | | |
\/ \/ \___|_|\___\___/|_| |_| |_|\___| |_|\___/ |_____/|_| |_|\__,_|_| |_| |_|_|_|
"""
print(BANNER)
flag = getenv("GZCTF_FLAG","GZCTF_NOT_DEFINE")
m = bytes_to_long(flag.encode())
n = getPrime(1024)
coefficients = [m] + [random.randrange(1,n-1) for i in range(100)]
print(f"n = {n}")
def f(x):
sum = 0
for i in range(len(coefficients)):
sum += coefficients[i]*pow(x,i,n) % n
sum %= n
return sum
while 1:
x = int(input("Please Input x: "))
if x == 0:
print("Not Allowed!!!")
exit()
res = (x,f(x))
print(res)
Shamir门限,我不懂,太难了(哭
直接抄了https://tangcuxiaojikuai.xyz/post/97bbcbc9.html
关键就是需要t个点,然后利用拉格朗日插值法(不懂)
from pwn import *
from Crypto.Util.number import *
r=remote("210.44.150.15",47511)
r.recvuntil(b'n = ')
n=eval(r.recvline().strip().decode())
m=[]
for i in range(1,101+1):
r.recvuntil(b'Please Input x: ')
r.sendline(str(i).encode())
tmp=eval(r.recvline().strip())
m.append(tmp)
#https://tangcuxiaojikuai.xyz/post/97bbcbc9.html
# 关键需要t个点 此题t=101
flag=0
for i in range(len(m)):
tmp1=1
tmp2=1
for j in range(len(m)):
if i==j:
continue
tmp1*=-m[j][0]
tmp2*=(m[i][0]-m[j][0])
flag=(flag+m[i][1]*tmp1*inverse(tmp2,n))%n
print(long_to_bytes(flag))
r.interactive()
#b'SHCTF{5H4miR_N07_sh3rL0CK_f1289fe81dc7}'