首页
社区
课程
招聘
[原创]GDGAlgiersCTF2022密码学复盘
发表于: 2022-10-28 10:45 10339

[原创]GDGAlgiersCTF2022密码学复盘

2022-10-28 10:45
10339

两道矩阵相关的题,在这里整理一下。

首先选定一个大素数ppp,生成(,p)(1,p-1)(1,p1)内的随机值privprivpriv

privprivpriv经过SHA256的处理得到key,再用AES通过key加密明文。

题目给定了两个12x12矩阵D,PD, PD,P,满足Dpriv=PD^{priv}=PDpriv=P

AES的初始向量已知,因此需要求privprivpriv

D=TdiaTD=Tdiag_DT^{-1}D=TdiagDT1,有

diagDpriv=TPTdiag_D^{priv}=T^{-1}PTdiagDpriv=T1PT

dia=diag(,,...,),TPT=diag(,,...,)diag_D=diag(\lambda_1,\lambda_2,...,\lambda_{12}),\ T^{-1}PT=diag(\alpha_1,\alpha_2,...,\alpha_{12})diagD=diag(λ1,λ2,...,λ12), T1PT=diag(α1,α2,...,α12),则

privmod,i=,,...priv\equiv\log_{\lambda_i}\alpha_i\mod \delta_i,i=1,2,...12privlogλiαimodδi,i=1,2,...12

其中\delta_iδi\lambda_iλippp的阶。

先求离散对数,然后求解同余方程组即可。

由于privp1\leq{priv}\leq{p-1}1privp1,猜测可以唯一确定privprivpriv

计算之后发现,dia=diag(,,,,,...,)diag_D=diag(37,31,29,23,19,...,2)diagD=diag(37,31,29,23,19,...,2)\delta_iδi不是pp-1p1就是\frac{p-1}{2}2p1

于是我选取λ=\lambda=37λ=37,此时 δ=p,priv=(p)\delta=p-1,\ priv=\log_{37}{(p-1)}δ=p1, priv=log37(p1)直接唯一确定。

python sln.py

CyberErudites{Di4g0n4l1zabl3_M4tric3s_d4_b3st}

选取大质数p,q,N=pqp,q,N=pqp,q,N=pq和一个大随机数RRR,公钥eeegcd(e,(p)(q))=\gcd(e,(p-1)(q-1))=1gcd(e,(p1)(q1))=1,加密

c=(R+m)emodNc=(R+m^3)^e\mod{N}c=(R+m3)emodN

e,Ree,R^ee,Re和密文都已知,但难以求出Re,...,RR^{e-1},...,RRe1,...,R

注意到题中所给e=e=3e=3太小,如果知道至少2个明文密文对,猜测可以构造出其他的多项式值(flag以CyberErudites开头)。

考虑明文,m_1,m_2m1,m2和矩阵D=[]D=\begin{bmatrix}3m_1^3&3m_1^6\\3m_2^3&3m_2^6\\\end{bmatrix}D=[3m133m233m163m26]与方程

[]D=[]\begin{bmatrix}\lambda_1&\lambda_2\end{bmatrix}D=\begin{bmatrix}3m^3&3m^6\end{bmatrix}[λ1λ2]D=[3m33m6]

其中mmm是构造明文。

如果DDD有模NNN意义的逆DD^{-1}D1,就可以求出,\lambda_1,\lambda_2λ1,λ2

f(m,R)=mR+mRf(m,R)=3m^3R^2+3m^6R^3f(m,R)=3m3R2+3m6R3,从而

\begin{aligned} f(m,R)&=3m^3R^2+3m^6R\\ &=(3\lambda_1m_1^3+3\lambda_2m_2^3)R^2+(3\lambda_1m_1^6+3\lambda_2m_2^6)R\\ &=\lambda_1(3m_1^3R^2+3m_1^6R)+\lambda_2(3m_2^3R^2+3m_2^6R)\\ &=\lambda_1f(m_1,R)+\lambda_2f(m_2,R)\\ f(m_i,R)&=(R+m_i^3)^3-R^3-m_i^9=c_i-R^3-m_i^9,i=1,2 \end{aligned}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)3R3mi9=ciR3mi9,i=1,2

所以 c=f(m,R)+R+m=(Rm)+(Rm)+R+mc=f(m,R)+R^3+m^9=\lambda_1(c_1-R^3-m_1^9)+\lambda_2(c_2-R^3-m_2^9)+R^3+m^9c=f(m,R)+R3+m9=λ1(c1R3m19)+λ2(c2R3m29)+R3+m9

由于p,qp,qp,q都很大,detD\det{D}detD较小(明文是ASCII),于是detD\det{D}detD应当总是有模NNN逆元,可以大胆求DD^{-1}D1

我选取明文即为'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直播授课

最后于 2024-1-29 19:18 被狗敦子编辑 ,原因: 更新了公式
上传的附件:
收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//