GHCTF2025_Crypto_Ink部分
GHCTF2025-Crypto_Ink部分
baby_signin
e与phi不互素
from sympy.ntheory.residue_ntheory import sqrt_mod
from sympy.ntheory.modular import crt
p = 182756071972245688517047475576147877841
q = 305364532854935080710443995362714630091
n = p * q
c = 14745090428909283741632702934793176175157287000845660394920203837824364163635
c_p = c % p
c_q = c % q
def find_quartic_roots(c_val, p_val):
roots = set()
y_roots = sqrt_mod(c_val, p_val, all_roots=True)
for y in y_roots:
x_roots = sqrt_mod(y, p_val, all_roots=True)
roots.update(x_roots)
return roots
roots_p = find_quartic_roots(c_p, p)
roots_q = find_quartic_roots(c_q, q)
possible_ms = []
for xp in roots_p:
for xq in roots_q:
m, _ = crt([p, q], [xp, xq])
possible_ms.append(m)
for m in possible_ms:
try:
flag = bytes.fromhex(hex(m)[2:]).decode('utf-8')
if flag.startswith('NSSCTF{'):
print("Flag found:", flag)
break
except:
continue
baby_factor_revenge
出baby_factor不小心出错了,导致那题就rsa模板了,上个revenge。已知phi,相当于d泄露,分解n。
私钥 d 相关攻击 - CTF WikiWiki上面有相关原理
from math import gcd
from math import isqrt
from random import randrange
from gmpy2 import is_prime
import gmpy2
# from sage.all import is_prime
import libnum
def factorize_multi_prime(N, phi):
prime_factors = set()
factors = [N]
while len(factors) > 0:
# Element to factorize.
N = factors[0]
w = randrange(2, N - 1)
i = 1
while phi % (2 ** i) == 0:
sqrt_1 = pow(w, phi // (2 ** i), N)
if sqrt_1 > 1 and sqrt_1 != N - 1:
# We can remove the element to factorize now, because we have a factorization.
factors = factors[1:]
p = gcd(N, sqrt_1 + 1)
q = N // p
if is_prime(p):
prime_factors.add(p)
elif p > 1:
factors.append(p)
if is_prime(q):
prime_factors.add(q)
elif q > 1:
factors.append(q)
break
i += 1
return tuple(prime_factors)
if __name__ =='__main__':
n=...
phi=...
c=...
fac = factorize_multi_prime(n, phi)
print(fac)
e=65537
prime_list = sorted(fac)
p, q, r= prime_list[0], prime_list[2], prime_list[1]
d1 = gmpy2.invert(e, phi)
m1 = int(pow(c, d1, p * q))
flag= libnum.n2s(m1)
print(flag)
baby_lattice
其实是一个HNP问题
\[\left\{
\begin{aligned}
g_1 &= t_1 \cdot key + z_1 \\
g_2 &= t_2 \cdot key + z_2 \\
&\vdots \\
g_n &= r_t \cdot key + z_t
\end{aligned}
\right.
\pmod{p}
\]
转化为\(z_i=g_i-t_i*key+k_ip\)
K是z的上界key为常系数,进行LLL算法求出最短向量。
\[M = \begin{bmatrix}
p & & & & \\
& p & & & \\
& & \ddots & & \\
& & & p & \\
-t_1 & -t_2 & \cdots & -t_n & K/p \\
g_1 & g_2 & \cdots & g_n & &K
\end{bmatrix}
\]
\[(k_1, k_2, \cdots, k_t, key, 1) M = (z_1, z_2, \cdots, z_t, K*key/p, K)
\]
exp
from Crypto.Cipher import AES
p = ...
rs = [...]
cs = [...]
iv=b'\x88\x0c\x7f\x92\xd7\xb7\xaf4\xe4\xfb\xd1_\xab\xff)\xb8'
ciphertext=b'\x94\x198\xd6\xa2mK\x00\x06\x7f\xad\xa0M\xf7\xadV;EO$\xee\xcdB0)\xfb!&8%,M'
t = len(rs)
kbits = 400
K = 2 ** kbits
P = identity_matrix(t) * p
RC = matrix([[-1, 0], [0, 1]]) * matrix([rs, cs])
KP = matrix([[K / p, 0], [0, K]])
M = block_matrix([[P, 0], [RC, KP]], subdivide=False)
shortest_vector = M.LLL()
x = shortest_vector[1, -2] / K * p % p
print(x)
cipher = AES.new(str(x).encode()[:16], AES.MODE_CBC,iv)
flag=cipher.decrypt(ciphertext)
print(flag)
RSA_and_DSA?
就是个维纳攻击和DSA线性关系的推导
\[x \equiv (s_1 s_2 i n k + (s_2 - s_1) h) * (s_1 r_2 - s_2 r_1)^{-1} \mod q
\]
exp1
import gmpy2
import libnum
from Crypto.Util.number import*
from hashlib import sha1
cink= ...
e= ...
N= ...
def transform(x,y):
res=[]
while y:
res.append(x//y)
x,y=y,x%y
return res
def continued_fraction(sub_res):
numerator,denominator=1,0
for i in sub_res[::-1]:
denominator,numerator=numerator,i*numerator+denominator
return denominator,numerator
def sub_fraction(x,y):
res=transform(x,y)
res=list(map(continued_fraction,(res[0:i] for i in range(1,len(res))))) #将连分数的结果逐一截取以求渐进分数
return res
def get_pq(a,b,c):
par=gmpy2.isqrt(b*b-4*a*c)
x1,x2=(-b+par)//(2*a),(-b-par)//(2*a)
return x1,x2
def wienerAttack(e,n):
for (d,k) in sub_fraction(e,n): #用一个for循环来注意试探e/n的连续函数的渐进分数,直到找到一个满足条件的渐进分数
if k==0: #可能会出现连分数的第一个为0的情况,排除
continue
if (e*d-1)%k!=0: #ed=1 (mod φ(n)) 因此如果找到了d的话,(ed-1)会整除φ(n),也就是存在k使得(e*d-1)//k=φ(n)
continue
phi=(e*d-1)//k #这个结果就是 φ(n)
px,qy=get_pq(1,n-phi+1,n)
if px*qy==n:
p,q=abs(int(px)),abs(int(qy)) #可能会得到两个负数,负负得正未尝不会出现
d=gmpy2.invert(e,(p-1)*(q-1)) #求ed=1 (mod φ(n))的结果,也就是e关于 φ(n)的乘法逆元d
return d
print("该方法不适用")
d1=wienerAttack(e,N)
k=pow(ck,d1,N)
print(k)
exp2
import hashlib
import gmpy2
from Crypto.Cipher import AES
(r1,s1)= (..., ...)
(r2,s2)= (..., ...)
g= ...
q= ...
p= ...
y= ...
ciphertext = ...
msg = b'GHCTF-2025'
h = int(hashlib.sha256(msg).digest().hex(),16)
a = 1
b =...
k = ((h*(r2 - r1) + b*r1*s2)*gmpy2.invert((r2*s1-a*r1*s2),q)) % q
x1 = (k*s1 - h)*gmpy2.invert(r1,q) % q
print(x1)
key = hashlib.sha1(str(x1).encode()).digest()[:16]
cipher = AES.new(key, AES.MODE_ECB)
ptext=cipher.decrypt(ciphertext)
print(ptext)

浙公网安备 33010602011771号