import libnum
from Crypto.Util import number
from functools import reduce
from secret import flag
n = 5
size = 64
while True:
ps = [number.getPrime(size) for _ in range(n)]
if len(set(ps)) == n:
break
e = 65537
n = reduce(lambda x, y: x*y, ps)
m = libnum.s2n(flag)
c = pow(m, e, n)
print('n = %d' % n)
print('c = %d' % c)
1、ps = [number.getPrime(size) for _ in range(n)]
number.getPrime(size)
number是从Crypto.Util导入的模块(实际是from Crypto.Util import number)getPrime(size)是该模块的一个函数作用:生成一个随机的
size比特的素数这里的
size = 64,所以每个素数都是 64 比特的
for _ in range(n)
n = 5(在程序开头定义)range(5)生成序列[0, 1, 2, 3, 4]_是一个惯用变量名,表示我们不需要在循环中使用这个值(只是用来重复执行 5 次)
列表推导式 [... for ...]
整个结构表示:执行括号内的代码 5 次,每次生成一个 64 比特的素数,并将所有结果收集到一个列表中
if len(set(ps)) == n:
这个检查确保所有 5 个素数都是不同的:
set(ps)将列表转换为集合(自动去重)如果去重后的元素个数仍然是 5,说明没有重复的素数
如果有重复,就重新生成(因为
while True循环会继续)
reduce() 函数
来自
from functools import reduce作用:对一个序列的所有元素累积应用某个函数
格式:
reduce(函数, 序列, 初始值)(初始值可选)
lambda x, y: x*y
这是一个匿名函数(lambda 函数)
接受两个参数
x和y,返回它们的乘积x*y
整个表达式的作用
reduce(lambda x, y: x*y, ps) 对列表 ps 中的 5 个素数执行连乘运算。
执行过程(假设 ps = [p1, p2, p3, p4, p5]):
取前两个元素:
x = p1, y = p2→p1 * p2结果作为新的
x,下一个元素p3作为y→(p1*p2) * p3继续:
((p1*p2)*p3) * p4最后:
(((p1*p2)*p3)*p4) * p5
最终得到:n = p1 × p2 × p3 × p4 × p5
libnum.s2n()
libnum是一个密码学常用的 Python 库s2n代表 "string to number"(字符串转数字)
pow() 函数
Python 内置的 pow() 函数有三种形式:
pow(x, y):计算x的y次方pow(x, y, z):计算x的y次方 对 z 取模
这里使用的是第三种形式,即模幂运算,非常适合 RSA 加密。
解题:
a. 首先获取n的质因数的乘积,程序如下:
sympy.factorint(n)
sympy是一个 Python 数学符号计算库factorint()是 SymPy 的整数分解函数作用:将整数
n分解为质因数的乘积
函数特性:
返回一个字典,键是质因数,值是该质因数的指数
例如:
factorint(60)返回{2: 2, 3: 1, 5: 1},表示60 = 2² × 3 × 5
b.然后根据质因子,获取欧拉函数phi,进而通过gmpy2.invert(e,phi),获取私钥d,最终通过power(c,d,n)获取明文。程序如下:

