特征
此类题目一般会给pub.key和flag.enc。pub.key是公钥文件,可以用txt打开;flag.enc是加密后的二进制文件,用txt打开会是乱码。
公钥一般长这样:
-----BEGIN PUBLIC KEY-----
MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAMAzLFxkrkcYL2wch21CM2kQVFpY9+7+
/AvKr1rzQczdAgMBAAE=
-----END PUBLIC KEY-----
可以用在线网站去解析获得e和n:SSL在线工具-公钥解析 (hiencode.com)
当然也可以用python来解
获得n之后可以尝试利用工具分解n,分解n的在线网站:factordb.com
字节流转换为数字
int.from_bytes()函数
由于二进制文件读取之后是字节流,所以需要将其转换成十进制的数字,才能进行运算,这里就需要用到一个int.from_bytes()函数
函数格式: int.from_bytes(bytes, byteorder, *, signed=False)
简单demo:
s1 = b'\xf1\xff'
print(int.from_bytes(s1, byteorder='big', signed=False))
print(int.from_bytes(s1, byteorder='little', signed=True))
输出:
61951
-15
参数解释:
- bytes是要转换的十六进制
- byteorder:选’big’或’little’,以上例为例,其中big代表正常顺序,即f1ff;little反之,代表反序fff1
- signed:选True、False表示是否要区分二进制的正负数含义。即是否要对原二进制数进行原码反码 补码操作
hex()和fromhex()函数
另外,还有一种方法可以将字节对象进行转换:
bytes对象的hex函数,用来将bytes对象的值转换成hexstr;而fromhex函数,用来将hexstr导入bytes对象,相当于用hexstr来创建bytes对象。bytes对象的这两个函数,有的时候非常好用!
>>> bytes([0,1,2,3,4,5]).hex()
'000102030405'
>>> bytes.fromhex('000102030405')
b'\x00\x01\x02\x03\x04\x05'
>>> b'abcde'.hex()
'6162636465'
>>> a = bytes.fromhex('6162636465')
>>> a
b'abcde'
通过hex将字节流转换为16进制字符串之后,就可以利用int函数将其转换为10进制数字:
class int(x, base=10)
参数:
(1)x – 字符串或数字
(2)base – 进制数,默认十进制
脚本
from gmpy2 import *
from Crypto.Util.number import *
from Crypto.PublicKey import RSA
# 公钥提取
with open("pub.key","r",encoding="utf-8") as file:
text=file.read()
key=RSA.import_key(text)
e=key.e
n=key.n
print(e)
print(n)
#然后利用yafu分解n得到p和q或者在线网站也能分解
p=285960468890451637935629440372639283459
q=304008741604601924494328155975272418463
with open("flag.enc","rb") as file:
c=file.read()
d=invert(e,(p-1)*(q-1))
flag=pow(int.from_bytes(c,byteorder="big"),d,n)
print(long_to_bytes(flag))