Contents

能源大赛2025

前言

最近期中考试没怎么刷题来着,复现复现没参加的比赛吧~

题目

simpleSignin

task.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from Crypto.Util.number import *
from gmpy2 import *
import os

flag = b'xxx'
p = next_prime(bytes_to_long(os.urandom(128)))
q = next_prime(bytes_to_long(os.urandom(128)))
r = next_prime(q)
n = p * q * r
e = 0x10001
print(f"n = {n}")
print(f"c = {pow(bytes_to_long(flag), e, n)}")
print(f"gift1 = {p % (2**10)}")
print(f"gift2 = {(p >> 20) % 2 ** 800}")

拿到题就知道这玩意是copper,好像比赛当天还有人在群里问来着,有点意思(,简单分析一下
gift1->低10位
gift2->右移20位后的低800位
我们可以认为已知了低820位,那10位可以爆破,那么前面直接copper求出

exp.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
n = 
c = 
gift1 = 513
gift2 = 
e=65537
from Crypto.Util.number import *

PR.<x> = PolynomialRing(Zmod(n))
for i in range(2**10):
    p_low = (gift2<<20)+(i<<10)+gift1
    f = x*2**820+p_low
    root = f.monic().small_roots(X=2^204,beta=0.33)
    if root:
        p = int(root[0]*2**820+p_low)
        if n%p==0:
            phi = p-1
            d = inverse(e,phi)
            m = pow(c,d,p)
            flag=long_to_bytes(m)
            print(flag)
            break

NumberTheory

task.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from Crypto.Util.number import *
import hint

flag=b'xxx'
e=65537
p=getPrime(512)
q=getPrime(512)
n=p*q
m=bytes_to_long(flag)
c=pow(m,e,n)
k=getPrime(1024)
assert hint + 233 * k == 233 * k * p
print(n)
print(c)
print(hint)

经典数论题

$$ hint=233k(p-1) \\ a^{hint}=a^{233k(p-1)} \mod p =1 \mod p \\ p=\gcd(a^{hint}-1,p) $$

exp.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from Crypto.Util.number import *

n=
c=
hint=
e = 65537
p = GCD(pow(2,hint,n)-1,n)
q = n//p
phi = (p-1)*(q-1)
d = inverse(e,phi)
m = pow(c,d,n)
flag = long_to_bytes(m)
print(flag)

easy_lwe

task.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from Crypto.Util.number import *
from secrets import flag
assert len(flag) == 38

p = getPrime(512)
m = getPrime(512)
while m > p:
    m = getPrime(512)

aa = []
cc = []
bb = []
for i in range(30):
    a = getPrime(512)
    b = getPrime(400)
    c = (a * m + b) % p
    aa.append(a)
    cc.append(c)
    bb.append(b)

enc = pow(m,flag,p)
print(f'p = {p}')
print(f'aa = {aa}')
print(f'cc = {cc}')
print(f'enc = {enc}')

part1是hnp问题,所以题目为什么叫lwe?直接用la佬的脚本就行了,微微改一下
part2是dlp问题,p-1是可分解的,经典Pohlig-Hellman,这里借鉴山石的思路,最后一个素数不用,而去爆破求解,效率更加快

exp.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from Crypto.Util.number import *
p = 
aa =
enc = 
K = 2 ** 400
P = identity_matrix(30) * p
RC = matrix([[-1, 0], [0, 1]]) * matrix([aa, cc])
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)

factors=[]#sage就能出来

dlogs = []
for fac in factors[:-1]:
    t = (p - 1) // fac
    dlog = discrete_log(G(pow(enc, t, p)), G(pow(x, t, p)))
    dlogs += [dlog]
s = (p - 1) // factors[-1]
print(s)
res = crt(dlogs, factors[:-1])
for i in range(100):
    if b'flag{'in long_to_bytes(res + i * s):
        print(long_to_bytes(res + i * s))
        break

easy_crypto

task.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from secret import flag
from Crypto.Util.number import getPrime

flag = bin(int.from_bytes(flag, 'big'))[2:]

private_key = []
g = getPrime(10)
private_key.append(g)
for i in range(len(flag) - 1):
    g = g * 2
    private_key.append(g)

a = getPrime(20)
b = getPrime(len(flag) + 20)
public_key = []
for i in private_key:
    public_key.append((a * i) % b)
print(public_key)

c = 0
for i in range(len(flag)):
    c += int(str(flag)[i])*public_key[i]
print(c)

前面先套了个lcg,直接求出seed,后面就是背包

exp.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from Crypto.Util.number import *
#我是取的最后两组
y = 
x = 
public_key =
c = 
b = 2*x - y
a = factor(public_key[0])[1][0]

private_key = []
for i in public_key:
    private_key.append(int(i*pow(a,-1,b)%b))

c = c*pow(a,-1,b)%b
flag = ''
for i in private_key[::-1]:
    if c >= i:
        c -= i
        flag = '1' + flag
    else:
        flag = '0' + flag

print(long_to_bytes(int(flag,2)))

总结

质量还好吧,感觉格还是不太熟,得多练练