*代表赛中未解出的题目
lift
题目:
1 | import os |
首先要弄清楚gen()函数返回的几个参数究竟是什么:
其中,p、q参数生成方式如下:
即表明phi与g不互素,接下来进入题目分析:
首先有:
所以hint一定是g的整数倍,而251本身就是素数,因此得到g=251。
而由于题目是多素数n且d为256比特,因此可以考虑采用coppersmith找到d,原理如下(此处的e为gen内部的小写e,而非大写E),由于:
所以由同余性质:
因此把d看作未知小量,使用coppersmith即可求解模n的参数p^4下的小根。求解出d后,求解gcd(ed-1,n)即可得到p^4,进而还原出p、q。
还原出p、q后,由于密文c是由以下方式得到:
而由于g与phi不互素,因此只能先用d求解出:
然后继续使用同余性质,将问题转化到模p、q下:
使用AMM算法可以得到:
但是由于题目将flag填充到了512比特,因此直接做中国剩余定理,只能得出模 p*q 下的解,位数是不够的。
可能这个时候会想,为什么刚才AMM算法不直接转到模p^5下开根,而只能转到模p下开根?事实上是因为AMM算法一般只适用于模数为素数时的有限域开根,因此这里只能得到模p下的解,而无法直接得到模p^5下的解。
那么该怎么办呢?有一种专门用于将模p^k下的解提升至模p^(k+i)下的解的方法,称作Hensel Lifting。而这正好与题目名字相对应。这里有一篇比较好理解的文章:
Hensel’s lemma (1) - 知乎 (zhihu.com)
大概了解到,Hensel Lifting一般用于解高次多项式同余方程,而在本题中,我们恰好有一个高次多项式同余方程如下(c1如何得来见前方推导):
仍然使用同余定理把他转到模p^5下:
显然,明文m就是这个高次多项式的根,而模p^5下的根m已经满足了512比特的要求,因此我们只需要使用Hensel Lifting,将刚才AMM求得的模p下的所有可能根提升到模p^5下,并根据flag头进行判别即可。
exp:
1 | from Crypto.Util.number import * |
但是呢,sage在实现这个自己写的Hensel Lifting时一直报错,脑子也不太清醒,暂时没找出原因。所以最后还需要手动把AMM求出的所有可能根粘贴出来,用python实现Hensel Lifting。
因此最终exp如下:
1 | from Crypto.Util.number import * |
*strange_hash
题目:
1 | from os import urandom |
题目的大致要求如下:
- 通过proof
- 提供一组输入(x,y,0),要求该输入通过自定义哈希函数Rescue_Prime后,生成的输出是(x’,y’,0)。也就是说,要求哈希函数的输入输出的最后一位均为0
其中,自定义的哈希函数Rescue_Prime生成过程如下(其中三次方意义是三元组的每一个数字进行三次方,是为了方便而这样表示):
看上去似乎很复杂,不过仔细一看,这怎么会是个哈希函数呢?因为哈希函数具有单向性,而他进行的每一步都是可逆的。比如如果加Con向量,逆操作就是对应减回去;如果是右乘M,逆操作就是对应解一个矩阵方程;如果是乘3次方或者-3次方,逆操作就是对应乘指数逆元。
因此,我们完全可以自定义一个输出,就定为(1,1,0),然后就可以按如下操作反解出对应的哈希函数的输入,步骤如下:
1 | def minus(x, y): |
其中,每个矩阵是由sage解矩阵方程解的,如下:
1 | from Crypto.Util.number import * |
所以我们可以得到如下关系:
1 | Input = [5329202944861711021, 10075872277090249537, 6598944197421011167] |
但是题目要求需要传入一个末尾为0的输入才行,这怎么办呢?比赛中也就停在这里了,不知道如何解决这个问题。
然后赛后有师傅告诉了我思路,问题出在这里(估计不是预期解):
1 | self.send_line(b'Send your input:') |
这是题目的交互部分,非常仔细的看的话,可以看出,他没有限制输入长度,而只对输入输出的-1项进行是否为0的检查,也就是说,我们可以把刚才反解(1,1,0)得到的输入:
1 | [5329202944861711021, 10075872277090249537, 6598944197421011167] |
写成这种形式传给服务器:
1 | (5329202944861711021, 10075872277090249537, 6598944197421011167,0) |
这样就能满足最后一项为0的检查,算出来的输出自然也是(1,1,0),就能得到flag了。
exp(比赛结束没环境了,可能会出错):
1 | from Crypto.Util.number import * |
………………
确实有一点无语,不过确实也怪自己不够细心。这个赛题提供的宝贵经验就是:一定要先检查交互部分本身有没有漏洞,有可能就能直接跳过一个很复杂的问题!