特征

此类题目一般会给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

参数解释:

  1. bytes是要转换的十六进制
  2. byteorder:选’big’或’little’,以上例为例,其中big代表正常顺序,即f1ff;little反之,代表反序fff1
  3. 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))