703 字
4 分钟
能源大赛2025
前言
最近期中考试没怎么刷题来着,复现复现没参加的比赛吧~
题目
simpleSignin
task.py
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 * re = 0x10001print(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
n =c =gift1 = 513gift2 =e=65537from 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
from Crypto.Util.number import *import hint
flag=b'xxx'e=65537p=getPrime(512)q=getPrime(512)n=p*qm=bytes_to_long(flag)c=pow(m,e,n)k=getPrime(1024)assert hint + 233 * k == 233 * k * pprint(n)print(c)print(hint)
经典数论题
exp.py
from Crypto.Util.number import *
n=c=hint=e = 65537p = GCD(pow(2,hint,n)-1,n)q = n//pphi = (p-1)*(q-1)d = inverse(e,phi)m = pow(c,d,n)flag = long_to_bytes(m)print(flag)
easy_lwe
task.py
from Crypto.Util.number import *from secrets import flagassert 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
from Crypto.Util.number import *p =aa =enc =K = 2 ** 400P = identity_matrix(30) * pRC = 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 % pprint(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
from secret import flagfrom 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 = 0for i in range(len(flag)): c += int(str(flag)[i])*public_key[i]print(c)
前面先套了个lcg,直接求出seed,后面就是背包
exp.py
from Crypto.Util.number import *#我是取的最后两组y =x =public_key =c =b = 2*x - ya = 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)%bflag = ''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)))
总结
质量还好吧,感觉格还是不太熟,得多练练