Hitcon 2022 Crypto 方向题解,这次纯crypto方向六道题,剩一道chimera没有解出来。和去年一样,Hitcon又出了NTRU格密码相关的攻击,去年是选择密文攻击,这次是广播攻击。该题解不包含两道NTRU题的题解,之后有空会单独写一篇NTRU相关攻击的博客。以下是BabySSS,Secret,Superprime的题解。
BabySSS
源代码
I implemented a toy Shamir’s Secret Sharing for fun. Can you help me check is there any issues with this?
1 | from random import SystemRandom |
分析
SSS密钥共享算法,用于构建密钥分享的多项式是 ,其中 都是64比特的随机数,个人持有的子密钥 是 16 比特。我们有8个子密钥即 ,借此恢复整个多项式。下面介绍两种算法,一种基于格的算法;一个基于中国剩余定理的恢复算法。
格基规约-最短向量
相比较于 (2048比特), 的长度64比特就很小,因此可以考虑基于多项式的等式构建下面的基本格:
由于 是上述矩阵M行空间的上的短向量,因此可以应用LLL算法,大概率就能得到上面得到目标向量,但是仅仅靠上面的格解不出来目标解,因为目标解模长在各维度上分布不均匀,所以我们修改上面矩阵 (1) ,使得目标解各个维度的模长都约等于1即可。
此时目标向量为 ,各个维度都为1比特左右。对上述矩阵LLL之后,即可得到 ,从而恢复出参数 。
CRT解法
注意到 ,我们有8组 ,得到8组 ,从而恢复出 。更一般的,推导任意 , 在恢复出 后,,则 也就和 的情况一样,同理恢复出 。
EXP
格方法:
1 | from ast import literal_eval |
CRT 解法
1 | from ast import literal_eval |
Secret
源代码
1 | import random, os |
分析
已知64组 ,我们需要恢复m。这题有些类似之前n1ctf的一道题,详情参考我之前的博客ezdlp。难点在于恢复n,这题的不同点在于我们不知道基底m,因此这里我们需要找很小的 使得:
解空间,即上面两个方程的核空间,是一个线性空间。因此我们可以取一组核空间的基构成的矩阵,在这个矩阵上进行LLL算法即可得到符合条件的小系数 。因为我们不能求逆,把正负号分两边进行计算,即可得到n的整数倍 , 利用多组这样的倍数求一个最大公倍数即可恢复n。
得到n之后,利用求逆,消去未知参数p的影响: ,在新的集合 里,根据指数计算扩展欧几里得算法得到一组: ,即可恢复得到 。
EXP
1 | # sage |
Superprime
源代码
1 | from Crypto.Util.number import getPrime, isPrime, bytes_to_long |
分析
可以拆分为三个小问题,题目中SuperPrime
得到的两个素数的形式如下:
下面分布讨论题目中的三种情况,我们把bytes_to_long(str(p).encode())
定义为: ,显然 是单调递增函数。
- 情况一: ,即 ,显然右边是一个单调递增函数,因此可以通过二分搜索,快速分解n。
- 情况二: ,这种情况下我们注意到: 由式(1) (2)给出的关系,我们可以通过 模10的结果和 模256的结果,去推导出 的低位,以此类推,从低位到高位搜索,每次可以得到若干可能的结果,剪枝掉不符合条件的值,进行深度优先搜索即可。
- 情况三: ,这里写一下官方题解里的思想,考虑到 ,在 的长度保持不变的情况下, 上述函数也是单调递增的,因此也可以使用二分搜索分解 。比赛时候巨神写的从高位开始的搜索算法,类似二维的二分搜索。官方的脚本可以参考这里solve.py。
EXP
1 | from Crypto.Util.number import * |