题目
python
import gmpy2
from Crypto.Util.number import *
from binascii import a2b_hex,b2a_hex
flag = "*****************"
p = 262248800182277040650192055439906580479
q = 262854994239322828547925595487519915551
e = 65533
n = p*q
c = pow(int(b2a_hex(flag),16),e,n)
print c
# 27565231154623519221597938803435789010285480123476977081867877272451638645710
这段代码是一个 RSA 加密脚本,它的作用是:
- 把
flag(比如"flag{...}")转换成一个大整数; - 用 RSA 公钥
(e, n)对它加密; - 输出密文
c。
而你看到的这些 import 语句,就是为了让 Python 能完成这些数学和编码操作而引入的"工具包"。
🔧 第一行:import gmpy2
✅ 是什么?
gmpy2 是一个 高性能的 Python 数学库,专门用于处理:
- 大整数(比如几百位的数字)
- 高精度浮点数
- 快速的数论运算(比如求逆元、模幂、判断质数等)
✅ 有什么用?(在本题中)
虽然这段加密代码没有直接使用 gmpy2(它只用了 pow),但在解密时(也就是你作为 CTF 选手要做的事),你会用到它,比如:
Python
编辑
d = gmpy2.invert(e, phi) # 求 e 在模 phi 下的逆元(即私钥 d)
或者:
Python
编辑
root = gmpy2.iroot(c, e) # 尝试开 e 次方根(当 n 很大但 e 很小时)
💡 所以:出题人提前导入了
gmpy2,暗示你解题时可能需要用到它(即使加密过程没用)。
🔧 第二行:from Crypto.Util.number import *
✅ 是什么?
这是从 PyCryptodome (一个流行的密码学库)中导入一系列和数字、RSA 相关的实用函数。
import * 的意思是:把 Crypto.Util.number 里的所有常用函数都直接拿来用,不用加前缀。
✅ 常见导入的函数包括(你可能用到的):
| 函数 | 作用 |
|---|---|
getPrime(bits) |
生成一个指定位数的质数(比如 getPrime(1024)) |
inverse(a, n) |
计算 a 在模 n 下的逆元(类似 gmpy2.invert) |
long_to_bytes(x) |
把大整数 x 转成字节(比如把解密出的数字变回 "flag{...}") |
bytes_to_long(b) |
把字节(如 b"hello")转成大整数 |
isPrime(n) |
判断 n 是否为质数 |
✅ 在本题中的作用?
虽然加密代码没显式调用这些函数,但:
flag被转成十六进制再转整数,其实可以用bytes_to_long(flag.encode())更直接;- 你解密时一定会用
long_to_bytes(m)把解出的数字m变回字符串!
🌰 举例:
如果你算出明文整数
m = 123456...,用
long_to_bytes(m)就能得到b'flag{...}'。
🔧 第三行:from binascii import a2b_hex, b2a_hex
✅ 是什么?
binascii 是 Python 内置模块,用于在 二进制数据 和 ASCII 编码的十六进制字符串 之间转换。
b2a_hex(data):把字节(bytes)转成十六进制字符串(bytes to ASCII hex )- 例如:
b2a_hex(b"AB")→b'4142'(因为 'A'=0x41, 'B'=0x42)
- 例如:
a2b_hex(hexstr):把十六进制字符串转回字节(ASCII hex to bytes )- 例如:
a2b_hex(b'4142')→b'AB'
- 例如:
⚠️ 注意:它们的输入输出都是 bytes 类型,不是普通字符串。
✅ 在本题中怎么用?
看这行关键代码:
Python
编辑
c = pow(int(b2a_hex(flag), 16), e, n)
我们一步步拆解:
flag是字符串,比如"flag{test}"- 但
b2a_hex需要 bytes ,所以实际应为flag.encode()(但题目没写,可能是简化或假设flag已是 bytes)- 正确写法通常是:
b2a_hex(flag.encode())
- 正确写法通常是:
b2a_hex(flag)→ 得到十六进制的 bytes,比如b'666c61677b746573747d'int(..., 16)→ 把这个十六进制字符串当作 16 进制数 ,转成一个大整数- 例如:
int('666c...', 16)→ 一个很大的整数m
- 例如:
pow(m, e, n)→ 计算m^e mod n,得到密文c
✅ 所以:
b2a_hex的作用是 把 flag 字符串变成一个可以用于 RSA 加密的大整数。
🧩 总结:每个 import 的作用
| 代码 | 作用 | 为什么需要? |
|---|---|---|
import gmpy2 |
高性能大数运算 | 解密时求逆元、开根等(虽然加密没用,但暗示解题方向) |
from Crypto.Util.number import * |
密码学常用数字工具 | 解密后把整数转回字符串(long_to_bytes),或处理大数 |
from binascii import a2b_hex, b2a_hex |
字节 ↔ 十六进制转换 | 把 flag 字符串编码成整数 m,以便 RSA 加密 |
💡 给初学者的建议
- 不要怕
import:它们只是"借工具",就像做饭前先拿锅、刀、铲。 gmpy2和Crypto.Util.number是 CTF RSA 题的标配,一定要会用。- 字符串 → 整数 → 加密 → 解密 → 整数 → 字符串 是标准流程,
b2a_hex/long_to_bytes就是桥梁。
✅ 举个完整例子(你解密时会写的代码):
Python
编辑
from Crypto.Util.number import long_to_bytes
import gmpy2
# 已知 p, q, e, c
phi = (p-1)*(q-1)
d = int(gmpy2.invert(e, phi)) # 求私钥
m = pow(c, d, n) # 解密
flag = long_to_bytes(m) # 变回字符串!
print(flag)
这样你就把密文 c 变回了 flag{...}!