gmpy2和libnum库核心函数解析
TOPIC SOURCE
Crypto中RSA常用工具及python库说明
在密码学脚本和CTF挑战中,处理大整数的效率直接决定了解题的节奏。gmpy2与libnum分别站在底层多精度运算与实用工具的两侧,熟悉它们的核心函数往往能把“穷举三天”压缩成“一杯咖啡”。下面从实现原理、调用方式以及性能特征三个维度,对两库常用接口进行剖析。
gmpy2核心函数概览
gmpy2 基于 GMP、MPFR、MPC 三大库的 C 实现,所有整数在内部被包装为 mpz 类型,运算几乎等同于原生 C 速度。常用函数可以归为四类:
- gcd(a, b):返回最大公约数,内部调用 GMP 的
mpz_gcd,对 1024 位以上的整数仍在毫秒级完成。 - invert(a, m):求模逆,等价于扩展欧几里得算法的
mpz_invert,在 RSA 私钥恢复时尤为常见。 - gcdext(a, b):返回 (g, x, y) 满足 g = ax + by,一次性提供逆元与最大公约数,省去二次调用的开销。
- iroot(k, n):计算整数 k 次方根并返回 (root, exact),在攻击 RSA 的低指数加密时可以直接验证根是否整数。
import gmpy2
a = gmpy2.mpz('0xDEADBEEFDEADBEEF')
b = gmpy2.mpz(65537)
print(gmpy2.gcd(a, b)) # 输出 1
print(gmpy2.invert(b, a)) # 求 b 在 a 模下的逆元
root, exact = gmpy2.iroot(3, a) # 计算立方根
值得注意的是,gmpy2 的 mpz 对象在 Python 循环中保持引用计数,避免了临时对象的频繁创建;而在需要大量随机大数时,配合 gmpy2.random_state() 能让种子管理更为统一。
libnum核心函数对比
libnum 则是纯 Python 实现的轻量库,目标是提供“一站式”数论工具,适合快速原型和教学。它的函数大多是对 gmpy2 逻辑的包装,但在异常处理和返回值形式上更贴合 Pythonic 风格。
- libnum.gcd(a, b):直接返回整数,内部调用 Python 的
math.gcd,对 64 位以内的整数极快。 - libnum.invmod(a, m):利用扩展欧几里得实现模逆,若不存在会抛出
ValueError,便于错误捕获。 - libnum.xgcd(a, b):返回 (x, y, g) 三元组,等价于 gmpy2.gcdext,常用于求解线性同余方程组。
- libnum.s2n(s) / libnum.n2s(n):字符串↔整数的双向转换,内部使用大端字节序,便于在 RSA 加解密前后切换表示。
import libnum
msg = "CTF{demo}"
n = libnum.s2n(msg) # 文字转整数
print(n)
rev = libnum.n2s(n) # 整数转文字
print(rev) # 恢复原始字符串
在实际攻防中,常见的做法是先用 libnum 快速完成数据格式的搬运,再在关键的模运算阶段切换到 gmpy2 提升速度。两者的 API 设计虽不同,却可以无缝衔接;掌握它们的细微差别,往往是从“卡在 10^6 位”到“一口气算完 10^7 位”的关键。

参与讨论
这个库之前搞CTF时用过,确实能省不少时间