偶然看到交流群里有人问这题会么,就有了这篇
一、题目
#!/usr/bin/env python3
import gmpy2
from Crypto.Util.number import getPrime
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from base64 import b64encode
flag = open('flag', 'r').read().strip() * 23
def encrypt(p, q, e, msg):
while True:
n = p * q
try:
phi = (p - 1)*(q - 1)
pubkey = RSA.construct((int(n), int(e)))
key = PKCS1_v1_5.new(pubkey)
enc = b64encode(key.encrypt(msg))
return enc
except:
p = gmpy2.next_prime(p**2 + q**2)
q = gmpy2.next_prime(2*p*q)
e = gmpy2.next_prime(e**2)
p = getPrime(128)
q = getPrime(128)
n = p*q
e = getPrime(64)
pubkey = RSA.construct((n, e))
with open('pubkey.pem', 'wb') as f:
f.write(pubkey.exportKey())
with open('flag.enc', 'wb') as g:
g.write(encrypt(p, q, e, flag.encode()))
给了加密脚本还有两个附件
二、题解
读代码,保存pubkey.pem文件中的n、e为初始值,p,q为随机128位,可以读n的值去分解得p,q
观察 encrypt 函数,发现存在 try ... except 结构,而且flag.enc 中的数据很大,说明初始的 n 并不能作为最后加密的 n 值(因为RSA加密需要公钥n的长度至少是大于消息的长度的, 否则加密出来的密文会无法解密)
import gmpy2
import binascii
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from base64 import *
m=b64decode(open('flag.enc','r').read())
pub=RSA.importKey(open('pubkey.pem','r').read())
n=pub.n
e=pub.e
# print(n)
#n = 62078208638445817213739226854534031566665495569130972218813975279479576033261
#sage 分解n得pq
q=184333227921154992916659782580114145999
p=336771668019607304680919844592337860739
i=1
while 1:
print(i)
i+=1
n=q*p
if n >= int(binascii.b2a_hex(m),16):
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
prikey=RSA.construct((int(n),int(e),int(d)))
key=PKCS1_v1_5.new(prikey)
flag=key.decrypt(m,None)
break
else:
p = gmpy2.next_prime(p ** 2 + q ** 2)
q = gmpy2.next_prime(2 * p * q)
e = gmpy2.next_prime(e ** 2)
print(flag)
#1
#2
#3
#4
#b'flag{f@cToR__N_bY_!teratlnG!}'