-
-
[原创]GDGAlgiersCTF2022密码学复盘
-
发表于: 2022-10-28 10:45 10339
-
两道矩阵相关的题,在这里整理一下。
首先选定一个大素数p,生成(1,p−1)内的随机值priv。
priv经过SHA256的处理得到key,再用AES通过key加密明文。
题目给定了两个12x12矩阵D,P,满足Dpriv=P。
AES的初始向量已知,因此需要求priv。
令D=TdiagDT−1,有
diagDpriv=T−1PT
设diagD=diag(λ1,λ2,...,λ12), T−1PT=diag(α1,α2,...,α12),则
priv≡logλiαimodδi,i=1,2,...12
其中δi是λi对p的阶。
先求离散对数,然后求解同余方程组即可。
由于1≤priv≤p−1,猜测可以唯一确定priv。
计算之后发现,diagD=diag(37,31,29,23,19,...,2),δi不是p−1就是2p−1。
于是我选取λ=37,此时 δ=p−1, priv=log37(p−1)直接唯一确定。
python sln.py
CyberErudites{Di4g0n4l1zabl3_M4tric3s_d4_b3st}
选取大质数p,q,N=pq和一个大随机数R,公钥e,gcd(e,(p−1)(q−1))=1,加密
c=(R+m3)emodN
e,Re和密文都已知,但难以求出Re−1,...,R。
注意到题中所给e=3太小,如果知道至少2个明文密文对,猜测可以构造出其他的多项式值(flag以CyberErudites开头)。
考虑明文m1,m2和矩阵D=[3m133m233m163m26]与方程
[λ1λ2]D=[3m33m6]
其中m是构造明文。
如果D有模N意义的逆D−1,就可以求出λ1,λ2。
令f(m,R)=3m3R2+3m6R3,从而
f(m,R)f(mi,R)=3m3R2+3m6R=(3λ1m13+3λ2m23)R2+(3λ1m16+3λ2m26)R=λ1(3m13R2+3m16R)+λ2(3m23R2+3m26R)=λ1f(m1,R)+λ2f(m2,R)=(R+mi3)3−R3−mi9=ci−R3−mi9,i=1,2
所以 c=f(m,R)+R3+m9=λ1(c1−R3−m19)+λ2(c2−R3−m29)+R3+m9
由于p,q都很大,detD较小(明文是ASCII),于是detD应当总是有模N逆元,可以大胆求D−1。
我选取明文即为'C','y',然后打表对照输出解密。
python sln.py
CyberErudites{Fr4nkl1n_W3_n33d_an0th3R_S3450N_A54P}
# from sage.all import *
import
json
from
Crypto.
Hash
import
SHA256
from
Crypto.Cipher
import
AES
from
Crypto.Util.Padding
import
pad
p
=
12143520799543738643
# def read_matrix(file_name):
# data = open(file_name, 'r').read().strip()
# rows = [list(eval(row)) for row in data.splitlines()]
# return Matrix(GF(p), rows)
#
#
# D = read_matrix('matrix.txt')
# P = read_matrix('public_key.txt')
# digD ,A = D.diagonalization()
# digP = A.inverse() * P * A
# vD = [digD[i][i] for i in range(12)]
# vP = [digP[i][i] for i in range(12)]
# print(f"vD = {vD}")
vD
=
[
37
,
31
,
29
,
23
,
19
,
17
,
13
,
11
,
7
,
5
,
3
,
2
]
# print(f"vP = {vP}")
vP
=
[
6751925379844785295
,
11256715989719283883
,
4551561838026472495
,
11383130904596697638
,
8534299476177021992
,
11184828239802784209
,
7103104085280766875
,
1622643043767580331
,
11104789109564474465
,
1502559189506368871
,
522368022672629021
,
1590703325067650792
]
# G = GF(p)
# K = discrete_log(G(vP[11]), G(vD[11]))
# print(f"K = {K}")
K
=
7619698002081645976
# now we can decipher
key
=
SHA256.new(data
=
str
(K).encode()).digest()[:
2
*
*
8
]
with
open
(
"encrypted_flag.txt"
,
"r"
) as ff:
data_dict
=
json.load(ff)
iv
=
bytes.fromhex(data_dict[
"iv"
])
ciphertext
=
bytes.fromhex(data_dict[
"ciphertext"
])
cipher
=
AES.new(key, AES.MODE_CBC, iv)
flag
=
cipher.decrypt(ciphertext).decode()[:
46
]
print
(flag)
# CyberErudites{Di4g0n4l1zabl3_M4tric3s_d4_b3st}
# from sage.all import *
import
json
from
Crypto.
Hash
import
SHA256
from
Crypto.Cipher
import
AES
from
Crypto.Util.Padding
import
pad
p
=
12143520799543738643
# def read_matrix(file_name):
# data = open(file_name, 'r').read().strip()
# rows = [list(eval(row)) for row in data.splitlines()]
# return Matrix(GF(p), rows)
#
#
# D = read_matrix('matrix.txt')
# P = read_matrix('public_key.txt')
# digD ,A = D.diagonalization()
# digP = A.inverse() * P * A
# vD = [digD[i][i] for i in range(12)]
# vP = [digP[i][i] for i in range(12)]
# print(f"vD = {vD}")
vD
=
[
37
,
31
,
29
,
23
,
19
,
17
,
13
,
11
,
7
,
5
,
3
,
2
]
# print(f"vP = {vP}")
vP
=
[
6751925379844785295
,
11256715989719283883
,
4551561838026472495
,
11383130904596697638
,
8534299476177021992
,
11184828239802784209
,
7103104085280766875
,
1622643043767580331
,
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
- [原创]DASCTF复盘之密码学(2023.07) 3574
- [原创]WinRAR623的破解小记 5322
- [原创]DASCTF复盘之逆向(2023.07) 11952
- [原创]AmateursCTF2023逆向题复盘 15275