题目:
from Crypto.Util.number import *
from gmpy2 import *
from secret import flag
p = getPrime(25)
e = # Hidden
q = getPrime(25)
n = p * q
m = bytes_to_long(flag.strip(b"npuctf{").strip(b"}"))
c = pow(m, e, n)
print(c)
print(pow(2, e, n))
print(pow(4, e, n))
print(pow(8, e, n))
'''
169169912654178
128509160179202
518818742414340
358553002064450
'''
首先,审计题目,我们已知c,c1,c2,c3三个条件,其中,这四个数有以下关系:
c = m^e mod n
c1 = 2^e mod n
c2 = 4^e mod n
c3 = 8^e mod n
=>c1**2-c2= k1*n and c1*c2-c3 = k2*n
于是,我们找到这两个数的最大公因数,这个数中一定包含我们想要的n这个值
import gmpy2
import sympy
print(gmpy2.gcd(c1*c1-c2,c1*c2-c3))
于是我们得到了我们想要的n值1054494004042394,这个数很小,我们可以将其分解得到
sage: factor(1054494004042394)
2 * 18195301 * 28977097
由于我们知道p、q都是质数,所以,在得到的分解中只需取其大质数即可。接下来,我们需要考虑求解e值的大小
已知的条件为:
2^e = c1 mod n 在这其中,除了e其余条件我们都已知,在这里,我们需要使用离散对数求解的思路:
Shanks’s Babystep-Giantstep Algorithm算法:
1、n=[ √n ]+1
2、构造两个列表
list1=[1,g,g^2,g^3,......,g^n]
list2=[h,hg^(-n),hg^(-2n),......,hg^(-n**2)]
3、在两个列表中,找到两个相同的数 g^i=hg^(-jn)
=>g^(i+jn)=h mod n
4、我们所求的e=i+jn
在python中,有两个可以很简单的实现关于幂的求解:
1、求解a^x = 1 mod n
sagemath:order=Zmod(n)(a).multiplicative_order()
2、求解g^x = a mod n
python(sympy库) x=sympy.discrete_log(n,a,g)
于是,根据以上条件,我们可以求解出e值,并对其进行rsa解密:
p = 18195301
q = 28977097
n=p*q
phi=(p-1)*(q-1)
e=sympy.discrete_log(n,c1,2)
d=gmpy2.invert(e,phi)
from Crypto.Util.number import *
print(long_to_bytes(gmpy2.powmod(c,d,n)))
exp:
c = 169169912654178
c1 = 128509160179202
c2 = 518818742414340
c3 = 358553002064450
import gmpy2
import sympy
print(gmpy2.gcd(c1*c1-c2,c1*c2-c3))
p = 18195301
q = 28977097
n=p*q
phi=(p-1)*(q-1)
e=sympy.discrete_log(n,c1,2)
d=gmpy2.invert(e,phi)
from Crypto.Util.number import *
print(long_to_bytes(gmpy2.powmod(c,d,n)))
得到:
b'345y!'