记VNCTF2025的两道密码题目
VNCTFeasymath
题目:
from Crypto.Util.number import *
from secret import flag
flag=bytes_to_long(flag)
l=flag.bit_length()//3 + 1
n=[]
N=1
while len(n) < 3:
p = 4*getPrime(l)-1
if isPrime(p):
n.append(p)
N *= p
print(f'c={flag*flag%N}')
from sympy import symbols, expand
x = symbols('x')
polynomial = expand((x - n[0]) * (x - n[1]) * (x - n[2]))
print(f'{polynomial=}')
# c=24884251313604275189259571459005374365204772270250725590014651519125317134307160341658199551661333326703566996431067426138627332156507267671028553934664652787411834581708944
# polynomial=x**3 - 15264966144147258587171776703005926730518438603688487721465*x**2 + 76513250180666948190254989703768338299723386154619468700730085586057638716434556720233473454400881002065319569292923*x - 125440939526343949494022113552414275560444252378483072729156599143746741258532431664938677330319449789665352104352620658550544887807433866999963624320909981994018431526620619
我拆开括号,利用数学关系得到n0,n1,n2,N=n0n1n2,然后卡住了。

我一直以为是模平方二次剩余问题,但是解不出。然后问了一下ai,用crt解决问题。
from sympy.ntheory.residue_ntheory import sqrt_mod
# Given values
c = 24884251313604275189259571459005374365204772270250725590014651519125317134307160341658199551661333326703566996431067426138627332156507267671028553934664652787411834581708944
n0 = 3868765709106144154703556118635822400623994075212553582411
n1 = 5487564316951417093934647798659941512646442958127439071827
n2 = 5908636118089697338533572785710162817248001570348495067227
N = n0 * n1 * n2
# Compute square roots modulo each prime
sqrt_n0 = sqrt_mod(c, n0, all_roots=True)
sqrt_n1 = sqrt_mod(c, n1, all_roots=True)
sqrt_n2 = sqrt_mod(c, n2, all_roots=True)
# Combine using CRT
from sympy.ntheory.modular import crt
# Iterate over all combinations of roots
for r0 in sqrt_n0:
for r1 in sqrt_n1:
for r2 in sqrt_n2:
flag_squared, _ = crt([n0, n1, n2], [r0, r1, r2])
flag = int(flag_squared).to_bytes((flag_squared.bit_length() + 7) // 8, 'big')
if b'VNCTF{' in flag:
print(flag.decode())
break
#VNCTF{90dcfb2dfb21a21e0c8715cbf3643f4a47d3e2e4b3f7b7975954e6d9701d9648}
VNCTFss0Hurt!
题目:
from Crypto.Util.number import *
from flag import flag
class DaMie:
def __init__(self, flag , n = None):
self.m = ZZ(bytes_to_long(flag))
self.n = n if n else getPrime(1024)
self.P = Zmod(self.n)
print(f'n = {self.n}')
def process(self, x, y, z):
return vector([5 * x + y - 5 * z, 5 * y - z, 5 * z])
def Mat(self, m):
PR = self.P['x,y,z']
x,y,z = PR.gens()
if m != 0:
plana = self.Mat(m//2)
planb = plana(*plana)
if m % 2 == 0:
return planb
else:
return self.process(*planb)
else:
return self.process(*PR.gens())
def hash(self, A, B, C):
return self.Mat(self.m)(A, B, C)
if __name__ == '__main__':
Ouch = DaMie(flag)
result = Ouch.hash(2025,208,209)
print(f'hash(A,B,C) = {result}') n = 106743081253087007974132382690669187409167641660258665859915640694456867788135702053312073228376307091325146727550371538313884850638568106223326195447798997814912891375244381751926653858549419946547894675646011818800255999071070352934719005006228971056393128007601573916373180007524930454138943896336817929823
hash(A,B,C) = (17199707718762989481733793569240992776243099972784327196212023936622130204798694753865087501654381623876011128783229020278210160383185417670794284015692458326761011808048967854332413536183785458993128524881447529380387804712214305034841856237045463243243451585619997751904403447841431924053651568039257094910, 62503976674384744837417986781499538335164333679603320998241675970253762411134672614307594505442798271581593168080110727738181755339828909879977419645331630791420448736959554172731899301884779691119177400457640826361914359964889995618273843955820050051136401731342998940859792560938931787155426766034754760036, 93840121740656543170616546027906623588891573113673113077637257131079221429328035796416874995388795184080636312185908173422461254266536066991205933270191964776577196573147847000446118311985331680378772920169894541350064423243733498672684875039906829095473677927238488927923581806647297338935716890606987700071)
分析:
哈希函数是通过一个矩阵变换实现的,输入是 (A, B, C),输出是 (h1, h2, h3)。
这个矩阵变换是基于一个线性变换矩阵 M,其形式为:
5,1,-5
M=0,5,-1
0,0,5
由于矩阵 MM 是上三角矩阵,它的幂次 M^m 也是上三角矩阵,且对角线元素是 5^m。
因此,输出向量的第三个分量 h3 只与输入向量的第三个分量 C 有关,且满足:
h3=5^m ⋅C mod n
通过这个关系,我们可以直接解出 5^m mod n。
从 h3=5^m⋅Cmod n 中,我们可以解出:
5m=h3⋅C−1mod n
其中 C^−1是 C 在模 n下的乘法逆元。
计算 k 的逆元,即 k^−1mod n,用于后续计算。
根据矩阵变换的性质,输出向量的第二个分量 h2 满足:
h2=5m⋅B−m⋅5(m−1) ⋅C mod n
通过代入 k=5m mod n 和 k^−1 mod n,可以解出 m:
m=(B−h2⋅k−1)⋅5−1⋅C^−1 mod n
exp:
from Crypto.Util.number import *
n = 106743081253087007974132382690669187409167641660258665859915640694456867788135702053312073228376307091325146727550371538313884850638568106223326195447798997814912891375244381751926653858549419946547894675646011818800255999071070352934719005006228971056393128007601573916373180007524930454138943896336817929823
h1, h2, h3 = (17199707718762989481733793569240992776243099972784327196212023936622130204798694753865087501654381623876011128783229020278210160383185417670794284015692458326761011808048967854332413536183785458993128524881447529380387804712214305034841856237045463243243451585619997751904403447841431924053651568039257094910, 62503976674384744837417986781499538335164333679603320998241675970253762411134672614307594505442798271581593168080110727738181755339828909879977419645331630791420448736959554172731899301884779691119177400457640826361914359964889995618273843955820050051136401731342998940859792560938931787155426766034754760036, 93840121740656543170616546027906623588891573113673113077637257131079221429328035796416874995388795184080636312185908173422461254266536066991205933270191964776577196573147847000446118311985331680378772920169894541350064423243733498672684875039906829095473677927238488927923581806647297338935716890606987700071)
inv_209 = pow(209, n-2, n)
k = (h3 * inv_209) % n
k_inv = pow(k, n-2, n)
term = (208 - (h2 * k_inv) % n) % n
m = (term * 5 * inv_209) % n
flag = long_to_bytes(m)
print(flag)
#b'\xd6NCTF{WWhy_diagonalization_1s_s0_brRRRrRrrRrrrRrRRrRRrrrRrRrRuUuUUUTTTtte3333?????ouch!ouch!Th3t_is_S0_Crazy!!!!}'
不知道为什么开头有乱码,反正改了前缀是正确提交了。

浙公网安备 33010602011771号