25年湾区杯网络安全竞赛--Crypto

AI-摘要
Aurorp1g GPT
AI初始化中...
介绍自己 🙈
生成本文简介 👋
推荐相关文章 📖
前往主页 🏠
前往爱发电购买
25年湾区杯网络安全竞赛--Crypto
Aurorp1g今天参加了25年湾区杯,我负责的是Crypto方向的题目,题目有两道,一道RSA加密、另一道结合了三种加密方式。博主只解出来了后者。来总结一下我的WriteUp。
题目内容
题目文件
task.py
加密脚本
1 | from hashlib import * |
目标
已知四元数 Q
、模数 p
和 R = Q^secret
,secret < 2⁵⁰,求出 secret 后解密 AES 密文。
题目分析
1. 题目的加密分析
- 在有限域
p = 115792089237316195423570985008687907853269984665640564039457584007913129639747
上定义四元数乘法 - 计算
R = Q^secret
- 取
key = MD5(str(secret)).hexdigest().encode()
(32 字节 → 16 字节) - AES-ECB 加密 flag
使用了四元数离散对数加密、MD5密钥派生、AES-ECB加密。
2. 解题思路
把「四元数」当做群元素,问题即 求离散对数 R = Q^secret
。
secret 上限 2⁵⁰,可直接用 Baby-Step Giant-Step:
- 令
m = 2^25 ≈ √2⁵⁰
- Baby-Step:预先计算并存储
{Q^j : j=0…m-1}
- Giant-Step:从
R
出发,每次乘Q^(-m)
,看是否命中表中某个j
一旦命中 ⇒secret = i*m + j
由于数值过大,相应的运算时间也会比较长。
3. 解题脚本要点
- 手写四元数类,乘法全部模
p
- 用
pow(norm, -1, p)
求逆,避免浮点 - 字典键用
tuple(int)
,速度远快于str(matrix)
- 最后按题目格式生成 32-字节 key:
key = md5(str(secret).encode()).hexdigest().encode()
4. 脚本代码
1 | from hashlib import md5 |
5. 运行结果
1 | [+] Baby-step … |
博主的脚本感觉还是差点意思,运行时间有点长,因此相对来说解密的成本就会很高。继续努力!!
附从其他文章看到的解密脚本:2025湾区杯网络安全竞赛WriteUP
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 from hashlib import md5
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import math
from collections import defaultdict
import time
# ---------------- Public parameters ----------------
p = 115792089237316195423570985008687907853269984665640564039457584007913129639747
Q_components = (123456789, 987654321, 135792468, 864297531)
R_components = (
53580504271939954579696282638160058429308301927753139543147605882574336327145,
79991318245209837622945719467562796951137605212294979976479199793453962090891,
53126869889181040587037210462276116096032594677560145306269148156034757160128,
97368024230306399859522783292246509699830254294649668434604971213496467857155
)
ciphertext = b'(\xe4IJ\xfd4%\xcf\xad\xb4\x7fi\xae\xdbZux6-\xf4\xd72\x14BB\x1e\xdc\xb7\xb7\xd1\xad#e@\x17\x1f\x12\xc4\xe5\xa6\x10\x91\x08\xd6\x87\x82H\x9e'
# ---------------- Quaternion arithmetic ----------------
class Quaternion:
__slots__=("a","b","c","d")
def __init__(self,a,b,c,d):
self.a=a%p;self.b=b%p;self.c=c%p;self.d=d%p
def __mul__(self,other):
a1,b1,c1,d1 = self.a,self.b,self.c,self.d
a2,b2,c2,d2 = other.a,other.b,other.c,other.d
return Quaternion(
(a1*a2 - b1*b2 - c1*c2 - d1*d2)%p,
(a1*b2 + b1*a2 + c1*d2 - d1*c2)%p,
(a1*c2 - b1*d2 + c1*a2 + d1*b2)%p,
(a1*d2 + b1*c2 - c1*b2 + d1*a2)%p
)
def __eq__(self,other): return (self.a,self.b,self.c,self.d)==(other.a,other.b,other.c,other.d)
def __hash__(self): return hash((self.a,self.b,self.c,self.d))
def conjugate(self):
return Quaternion(self.a,-self.b,-self.c,-self.d)
def norm(self):
return (self.a*self.a + self.b*self.b + self.c*self.c + self.d*self.d) % p
def inverse(self):
n=self.norm()
n_inv=pow(n,-1,p)
qc=self.conjugate()
return Quaternion(qc.a*n_inv, qc.b*n_inv, qc.c*n_inv, qc.d*n_inv)
def power(base,exp):
res = Quaternion(1,0,0,0)
while exp>0:
if exp&1: res=res*base
base=base*base
exp//=2
return res
Q=Quaternion(*Q_components)
R=Quaternion(*R_components)
# ---------------- Optimized BSGS ----------------
def bsgs(base, target, bound):
m=int(math.isqrt(bound))+1
baby={}
cur=Quaternion(1,0,0,0)
for j in range(m):
# 存储时只存 tuple,避免 Quaternion 对象占内存
baby[(cur.a,cur.b,cur.c,cur.d)]=j
cur=cur*base
if j%500000==0 and j>0:
print(f"[*] Baby step {j}/{m}")
# giant step
factor = power(base.inverse(), m)
cur=target
for i in range(m+1):
t=(cur.a,cur.b,cur.c,cur.d)
if t in baby:
return i*m+baby[t]
cur=cur*factor
if i%100000==0 and i>0:
print(f"[*] Giant step {i}/{m}")
return None
# ---------------- Run ----------------
t0 = time.time()
N=1<<50
secret=bsgs(Q,R,N)
print(f"[+] secret = {secret} ({time.time()-t0:.1f}s)")
# ---------------- Decrypt ----------------
key=md5(str(secret).encode()).hexdigest().encode()
cipher=AES.new(key,AES.MODE_ECB)
plaintext=unpad(cipher.decrypt(ciphertext),16)
print("[+] FLAG:",plaintext.decode())
评论
匿名评论隐私政策