前言
做了两题密码,也是学了一些东西吧。
binary(V1)
题目:
1 | from Crypto.Util.number import * |
这题我参考了【zer0pts CTF 2022】 Anti-Fermat的解法,求出近似值。
首先我们发现我们知道q是p ^ (1 << 512) - 1 ^ 3
的下一个素数,而我们知道p ^ (1 << 512) - 1
实际上就是2**1024-1
,作用就是给p取反,所以p^2**1024-1
的结果x是把p的每一位取反,所以x+p=2**1024-1
。由于q是x的下一个素数所以q=x+r,带进去p+q=2**1024-1+r
,所以p+q就约等于2**1024
。
之后就是带入n=((p+q)/2)**2 - ((p-q)/2)**2
,得到p的近似值,再爆破p即可。由于异或的值为3,实际上只影响到了最后两位,因此对这个方法不影响。
exp:
1 | from Crypto.Util.number import * |
binary(V2)
题目:
1 | from Crypto.Util.number import * |
这题我参考的题目是【*CTF】ezRSA 这题。它的原题长这样:
1 | from Crypto.Util.number import getStrongPrime |
两题的区别在于移位不一样以及异或的位数不一样。*ctf中的题目由于只移位了900位,所以前124位是不变的,采用开根号的方式可以解出高124位。接下来因为300-900位是相反的,中间600位通过爆破可以得到一个大概值,最后300位coppersmith解出。
爆破过程就是p * q < n
所以可以从高位开始,让p,q同位置的比特同时亦或1,若p * q < n
则保留当前的p,q,一直循环600次,即遍历900~301比特。
而这道题由于没有留下高位不异或,所以没有开方这个过程,我们直接爆破p高位:
1 | n=30922990347456222917444539556680823943887227159919972225540984336960832339775501069487618715102061181838518715208122786885229224735713077740655704542042089733020521332143961366919882134247596845707777520653357831207540764924471585714534980480437755533066407887622784022020839396643521892154136823395518763847 |
有了p的高位后,我们只要恢复p的低60位了:
1 | PR.<x> = PolynomialRing(Zmod(n)) |
得出了p的结果,就可以计算密文了:
1 | import gmpy2 |