首先给出题目坏蛋是雷宾,来自BUUCTF:
这道题之前写过,雷宾加密算法,但忘记的差不多了,当时也没怎么学,今天深入学习并记录一下。
加密过程
Rabin加密是非对称加密,和RSA相似,感觉是RSA里的一个特例。在Rabin加密中e = 2,根据RSA加密过程,可以知道加密公式为:c = mod n。
解密过程
就不推导了,剽取大佬的成果,学习学习
= mod p
= mod q
* p + * q = 1
以及4个明文公式:
m1 = ( * p * + * q * ) mod n
m2 = n - r
m3 = ( * p * - * q * ) mod n
m4 = n - s
通过扩展欧几里得算法解 * p + * q = 1,得到和,其它的都能直接解了。
对于此题给了Pk = 523798549,即公钥n = 523798549,密文c = 162853095,以及二进制校验码110001,应该是用于在最后4个明文中筛选用的。
解题过程
首先分解n得到p、q,然后依次计算 、 、、 、m1、m2、m3、m4,打印4个明文的二进制形式,查看后6位,与二进制校验码对应,选择正确的,去掉后6位,得到正确的明文m,最后md5加密就得到了最终的flag,整体代码如下:
from gmpy2 import *
from Crypto.Util.number import *
import hashlib
n = 523798549
c = 162853095
jy = 110001
p = 10663
q = 49123
mp = pow(c,(p+1)//4,p)
mq = pow(c,(q+1)//4,q)
yp = gcdext(p,q)[1]
yq = gcdext(p,q)[2]
m1 = (yp*p*mq + yq*q*mp) % n
m2 = n - m1
m3 = (yp*p*mq - yq*q*mp) % n
m4 = n - m3
print(bin(m1),bin(m2),bin(m3),bin(m4))
m = int('0b10010011100100100101010',2)
#m = 4835626
print(hashlib.md5(str(m).encode()).hexdigest())