NepCTF2025
QAQ
久违的更新,放假后杂七杂八的事情蛮多一直拖到现在
Nepsign
1 | from gmssl import sm3 |
唉被ai打爆的一题。
分析代码不难看出是一个基于哈希链上的签名,我们可以通过任意次输入明文得到对应签名,要求给出规定明文的签名来得到flag。
这道题的攻击方式基于哈希链的一个特点-“可追赶”性质。
由于哈希链是顺序累积的,有如下性质:
1 | SM3_n(SM3_n(sk[i], s), t) = SM3_n(sk[i], s + t) |
已知sigma_obs[i] = SM3_n(sk[i], MIN_STEP[i])
,想得到SM3_n(sk[i], target_step[i])
,只需再做target_step[i] - MIN_STEP[i]
次哈希
1 | SM3_n(sigma_obs[i], target_step[i] - MIN_STEP[i]) |
所以思路就很清晰了,我们输入随机生成的32字节的消息。然后得到对应签名。通过签名函数中计算step的部分计算该消息的step。这里我们把它单独提出来
1 | def steps_from_msg(msg: bytes): |
检查每个分量,如果这次新采集到的步数比历史最小步数还小,则更新最小步数和签名。如果所有分量的最小步数都≤目标消息的step[i]。因为只有拥有比目标步数小的签名,才能通过继续哈希“追赶”到目标步数。然后根据之前讲到的性质对每个分量进行(target_step[i] - MIN_STEP[i])次SM3哈希即可。(也可以利用相同位置产生相同签名来进行碰撞)
1 | from gmssl import sm3 |
ezRSA2
好耶,随缘师傅的题。
1 | from Crypto.Util.number import getStrongPrime, getRandomNBitInteger, GCD, inverse, long_to_bytes, bytes_to_long, sieve_base |
当时第一想法也是直接造格做,看了随缘师傅的wp才知道打二元copper也可行,两种方法都写一下吧。当然首先crt求出部分d还是不变的
根据
1 | hints = [] |
就能得到d的低位
1 | dl = CRT(hints, list(sieve_base)[1:len(hints)+1]) |
格
我们设
并令r=p+q
根据RSA可以列出等式$ed-1=k(N-r+1)$将d换为$dl+k_1M$,这里可以列出$e(dl+k_1M)-1=k_2(N-r+1)$然后展开移项$e\cdot dl-1+k_1e\cdot M+k_2(N+1)=k_2r$。那么我们就可以根据这个等式造格
$$
(k_1,1,k_2) \left(\begin{matrix} 1&&e\cdot tmp\ &1&e\cdot dl-1\ &&N+1\ \end{matrix}\right) =(k_1,1,k_2r)
$$
因为d=dl+k$_1$M,所以我们可以大致估计k1和k2的数量级分别为2$^{333}$和2$^{673}$,那么我们肯定要乘上大数进行配平,根据k_2r的数量级来判断下,分别乘一个2$^{1365}$和2$^{1698}$,然后直接造格打即可。
1 | from Crypto.Util.number import * |
二元copper
还是根据$e(dl+k_1M)-1=k_2(N-r+1)$这个式子,等式两边同时模eM,得到$1-edl+k(N+1-r)=0 mod eM$,直接对K和r打二元copper即可
(搬一手随缘师傅的脚本
1 | from Crypto.Util.number import sieve_base, long_to_bytes |
Lattice Bros
1 | #已知α的极小多项式为三次多项式f(x),即f(α)=0,且α≈54236.606188881754809671280151541781895183337725393 |
首先我们要恢复极小多项式的常数项,参考A Gentle Tutorial for Lattice-Based Cryptanalysis的3.6可以知道我们可以造如下格(截个原文的图,实际应该把8换成45,这与给出的精度有关)
直接规约就能得到目标向量啦。后来看Swizzer师傅的博客,才了解到sage有内置的函数直接求极小多项式Miscellaneous arithmetic functions - Standard Commutative Rings
恢复了之后这就是一个HNP问题了。
因为这里式子里是减法,所以r那一行的负号也就没必要加了。不过因为配平的原因,尝试发现多乘一个4能规约出结果。
1 | a = RealField(200)(54236.606188881754809671280151541781895183337725393) |