题目
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{...}
!