from Crypto.Util.number import *
import gmpy2
flag=b'BaseCTF{}'
m=bytes_to_long(flag)
p=getPrime(128)
q=getPrime(128)
n=p*q
e=65537
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
assert d<phi
c=pow(m,e,n)
print("c =",c)
print("e =",e)
print("d =",d)
这题没有给出n,注意到d<phi,我们等式e*d=1+k*phi
如果d<phi,那么k<e,我们可以通过暴破的方法求e,d的组合找到phi,phi的位数可以推测是256
然后我们分解phi,对它的因数排列组合,求得它的p和q,需要一定的代码能力
from Crypto.Util.number import *
import itertools
c = 78919950899709764543039048006935881842075789773495004639436106636461009323420
e = 65537
d = 13002488326322253055272696035053386340217207134816593767440035447757509399233
p_bits=128
q_bits=128
def get_phi(e, d):
k_phi = e*d -1
result = []
for k in range(e,2,-1):
if k_phi % k == 0:
tmp = k_phi // k
if int(tmp).bit_length()==p_bits+q_bits:
result.append(tmp)
return result
def main():
phi_list = get_phi(e,d) #获得可能的phi_n列表
count = len(phi_list)
print(f'一共有{count}个可能的phi')
count = 0
for phi in phi_list:
count += 1
print(f'{count} 正在尝试爆破 {phi}')
factors = factor(phi) # 分解phi_n得到质因子列表
result = []
for i in factors:
num, times = int(i[0]), i[1]
result += [num] * times
if len(factors)>1:
s = set()
for r in range(1, len(result) + 1):
combination = list(itertools.combinations(result, r))
for i in combination:
s.add(i)
ans=[]
for i in s:
tmp=1
for j in i:
tmp=tmp*j
ans.append(tmp)
for num in ans:
if int(num+1).bit_length()==p_bits and is_prime(num+1):
p = num+1
q = phi // num + 1
if is_prime(q):
n = p * q
flag=long_to_bytes(int(pow(c,d,n)))
if b'BaseCTF' in flag:
print(flag)
return
if name == '__main__':
main()
#b'BaseCTF{3e226a94-babb27696416}'
排列组合方法就是把因数每个因数的组合都求出来,并计算乘积,然后代入比较是不是符合条件