GHCTF2025_Crypto_Ink部分

GHCTF2025-Crypto_Ink部分

baby_signin

e与phi不互素

_litctf 2023]e的学问-CSDN博客

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)
posted @ 2025-03-09 17:54  ink599  阅读(266)  评论(0)    收藏  举报