比赛记录
[Week 3] EzECC
题目描述:
1 | 还在偷听小爱和小爆的通讯! |
题目:
1 | from Crypto.Util.number import * |
题目基于椭圆曲线加密方案。用给定的q、a、b三个参数,建立如下常见形式的椭圆曲线:
同时给出椭圆曲线上加法与倍点的计算实现。
题目加密过程如下:
- 将flag串拆成两半,分别转成整数后,作为M点的横纵坐标(需要注意的是M点并不是椭圆曲线上的点)
- 给出椭圆曲线上的点G,计算其k倍点K,给出G、K坐标
- 给出C1、C2点的坐标。两个点生成方式分别如下:
而注意到,r是一个16比特的数字,数量级很小。因此我们可以根据2式直接爆破出正确的r,然后计算C1-rK即可得到M点。
这里有一个细节需要注意,由于M不在椭圆曲线上,因此C1也不在椭圆曲线上,故无法直接用sagemath内置的椭圆曲线相关操作直接进行加减。因此可以通过计算出椭圆曲线的阶,从而计算出rK点逆元,然后用题目给定的加法函数计算出M。
exp:
1 | from Crypto.Util.number import * |
[Week 3] LLL-FirstBlood
题目描述:
1 | Hint 1: SageMath中的LLL算法该怎么用……?为啥这算法能解出想要的东西 |
题目:
1 | from random import randrange |
完成本题需要对格密码有最基础的了解。首先还是梳理一下加密过程:
- 将flag拆成四组并分别转为整数,作为一个4x4矩阵M的第一行
- 生成12个(1,p)之间的随机数,作为M的后三行
- 生成一个行列式为1的矩阵A,并计算C=AM
- 给出C矩阵以及生成有限域的素数p
其实只需要明白一点:格是对一些向量进行整系数线性组合得到的产物。而在本题中,明文flag与剩下三行noise分别是四组行向量,左乘A矩阵,实质上就是对四个行向量进行线性组合,而C就是这四个行向量组合后张成的格,对应的,四个行向量均为C的格基。
而很显然,flag组成的第一行行向量均较短,因此可以对格C用LLL算法解决SVP问题,得到的第一行向量就是flag的四部分。
exp:
1 | from Crypto.Util.number import * |
[Week 3] LLL-SecondBlood
题目描述:
1 | 前面的学习已经很累了!所以这道题的flag就直接送了!奇怪……怎么发送的时候受到了一些信号干扰,, |
题目:
1 | from Crypto.Util.number import * |
一个LWE问题,其一般会提供多组如下形式的等式:
其中,ai、ci均为已知,而bi是未知的量且较小,要求我们通过这些等式还原x。
这个问题一般写成矩阵形式:
那么如何用格进行求解呢?这里介绍两种方法:
方法一:CVP
把问题转化成一个CVP问题:
首先由模等式:
转化为等式如下:
所以可以构造如下格:
该格满足:
观察到由于b_i较小,所以右侧向量近似为:
因此可以求解CVP问题可以得到c_i-b_i组成的向量,进而还原flag。
exp:
1 | from Crypto.Util.number import * |
方法二:SVP
我们构造如下格:
那么由等式:
所以有如下线性关系:
然后配一下系数使得格最后规约出的数量级相当,即可还原m
exp:
1 | from Crypto.Util.number import * |
[Week 3] EzMatrix
题目描述:
1 | Hint 1: 相似矩阵相似吗?相似矩阵相似吗? |
题目:
1 | from Crypto.Util.number import getPrime |
enc.txt:
1 | [[11285847990515095003, 7585413350741918021, 11658254512436412666, 477577914899276103, 2941386515764607825, 11283325421744133699, 4096971712575507616, 8118672870538606033, 2377937081025778041, 6576171711896495163, 6152554374963853172, 5022013484610428974], [8354008012616001452, 7787447107046065118, 9504997911333967278, 1082773427768571094, 6015520658629219637, 11244285744740006951, 4493944053220750368, 3504246247470690014, 1738582001618280397, 2330057776906622572, 3043456814665571080, 2981613454022714952], [2508674373714509177, 3544963739532775937, 7952732753025175616, 11161786730565526285, 3397123486689639675, 6454135592624912854, 6613201018024296927, 9748485344986779929, 1819761609989340766, 1259944825407465767, 1596049024644778041, 7769939905324967788], [4200851163596876950, 11960539098651202761, 3303721151143544462, 2532304102428121556, 11083895221097319129, 1171933471304558017, 1549099593543874478, 6088238862927163233, 6459553630361959801, 947358195425767572, 2090533922210134578, 9023030120605201052], [2271102089902208138, 1614812525306266829, 1546249462332047661, 3168333397191737100, 7678980468150522028, 3128939172985153696, 1146041044751755224, 11870173227065140617, 8351303466095252790, 694704483676649448, 7944218023016968278, 583421745603756386], [10309472503110333289, 1100598261990718822, 10235859400888405310, 910925705831020921, 10771855884237562064, 9970830255165655653, 11678899608458971536, 4368822164222204233, 3104861419162339779, 4540709628196554222, 7851809145727500968, 12086896840826708824], [10973051751637593366, 5039073157846327641, 4855314857834773443, 4416954195828423951, 8243966437000815560, 8250554263390748131, 8093181066366682440, 1145520354143718292, 294729013023637045, 10115389386419597159, 2767140395261835843, 6724257139233017485], [6878768250003631244, 10834164422364241529, 6946589221005878489, 539734218479521833, 2691724062063066048, 3989403041446358401, 815244541494093987, 11168528286389981272, 2021358468726921955, 1123433019094267521, 524639025046508882, 5720273332497702547], [6688451244183880831, 10892730373179989558, 6987453292894341174, 5572212176769878684, 11332149024403380575, 3944612864568504791, 6768594304071589280, 10526434024562201079, 10241323610053039912, 1120473558410865753, 306153635148226248, 3606666063074222104], [7556871914690327290, 11353594909211427742, 747771112781361153, 1245068803956910299, 2831489557155431404, 1800035620948876551, 1050411779595241927, 5665981688041778089, 2028968510484240787, 4386552235402890530, 10334391443650474796, 3883841302951550608], [4485787817401669404, 184501191500952934, 3690661645276970957, 6263309802498749034, 6484490370652685031, 9743108369653588026, 3045941510087387269, 5870433915209047275, 4679598273992216016, 11839352681285251516, 4957980185504231911, 7925596893607015470], [1000449712878466719, 7022601702937838844, 1095849907482791166, 11989051568709522226, 6768031250066783733, 185945517026191241, 4280928696740160411, 5633542561098902406, 10176177574499086410, 5782837249861240943, 7406530879613861823, 1971858224839520916]] |
题目基于一个矩阵上的离散对数问题,已知矩阵A和M,满足:
要求求出secret。
矩阵乘法是很复杂的,因此直接做难以求解离散对数,要想办法转化成数域上的离散对数问题才行。因此需要用相似矩阵将矩阵对角化。
首先,可以用sage内置函数is_diagonalizable()
判断一个矩阵是否可以对角化:
1 | print(A.is_diagonalizable()) |
而A可以对角化,就代表A可以写成下面的形式:
其中,B是一个对角矩阵。而由于可逆矩阵可以两两相消,由此可以简化A的幂次的计算:
所以:
而由于B是一个对角矩阵的缘故,所以B的幂次其实就是对角线上各个元素的幂次,因此可以将矩阵的离散对数问题转化为对角线上某个元素的离散对数问题,问题得解。
exp:
1 | from Crypto.Util.number import * |
当然,如果你取的元素的阶小于secret,就得不到正确结果,不过多试几组就行了,并且本题中第一个元素就能满足要求。
[Week 3] EzOverflow
题目描述:
1 | 真正意义上的签“到”题 |
题目:
Elgamal.py:
1 | from Crypto.Util.number import getPrime,GCD,inverse,bytes_to_long |
task.py:
1 | from ElGamal import * |
其实是一个考察细心程度的题目。题目要求:
- 传入一个msg,并且msg不能是”0xGame”,靶机会返回对msg的Elgamal签名。
- 传入一个签名对,要求验签结果与”0xGame”相等。
而观察他的Elgamal,可以发现他省略了对msg取哈希的步骤,而直接用了m本身,也就是本身应该取:
1 | s = ((H(m)-d*r)*inverse(k,p-1)) % (p-1) |
而他却直接取了:
1 | s = (m-d*r)*inverse(k,p-1)) % (p-1) |
而m最终会模p-1,因此我们直接求p倍的”0xGame”转成的整数值,再转回字节串发送给靶机,然后直接将靶机返回的签名再传回去就能得到flag了。
exp:
1 | from Crypto.Util.number import * |