You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RSA密码挑战:如何通过n、e、c、r提取素因子p和q

RSA破解:从交替掩码的r中恢复p和q

首先,你当前的pa/qa计算逻辑存在错误,这是导致后续无法推进的核心问题。先修正这一步,再用格基还原方法(Coppersmith)补全未知位。

1. 修正pa和qa的计算

生成r的逻辑是:

  • mask = 0x555...555(1024位,二进制010101...01),保留p的偶数位(从0开始数,最低位是位0)
  • mask << 1 = 0xAAAA...AAAA(1024位,二进制101010...10),保留q的奇数位
  • r = (p & mask) + (q & mask<<1):r的二进制位从高位到低位,依次是q的奇数位、p的偶数位交替排列(比如r的最高位是q的第1023位,次高位是p的第1022位,以此类推)

你的原代码把r的偶数索引位(高位到低位)分配给pa,这搞反了对应关系。修正后的代码如下:

# 转换为1024位二进制字符串,高位在前,不足补0
r_bin = bin(r)[2:].zfill(1024)
pa_bits = []
qa_bits = []

for idx, bit in enumerate(r_bin):
    if idx % 2 == 1:
        # 奇数索引位对应p的偶数位(位1022、1020...0)
        pa_bits.append(bit)
        qa_bits.append('0')
    else:
        # 偶数索引位对应q的奇数位(位1023、1021...1)
        qa_bits.append(bit)
        pa_bits.append('0')

pa = int(''.join(pa_bits), 2)
qa = int(''.join(qa_bits), 2)

2. 用Coppersmith算法补全未知位

修正后,pa是p的已知位(偶数位),未知位(奇数位)全为0;qa是q的已知位(奇数位),未知位(偶数位)全为0。我们需要找到x(p的未知位组成的数),使得p = pa + x是n的素因子,且x仅在pa的0位上有值(即x是512位的数,对应p的1023、1021...1位)。

Coppersmith算法可以在模数n下找到多项式的小根,这里我们构造多项式f(x) = pa + x,寻找x使得f(x)整除n。

方法1:使用SageMath(推荐)

SageMath内置了Coppersmith算法的实现,直接调用即可:

# 替换为题目给定的n、pa
n = 0x...
pa = 0x...

# 定义多项式环,模数为n
PR.<x> = PolynomialRing(Zmod(n))
f = pa + x

# 寻找x < 2^512的小根(x是512位)
roots = f.small_roots(X=2^512, beta=0.5)

for root in roots:
    p_candidate = pa + int(root)
    if n % p_candidate == 0:
        q_candidate = n // p_candidate
        # 验证是否为素数
        if is_prime(p_candidate) and is_prime(q_candidate):
            print(f"p = {p_candidate}")
            print(f"q = {q_candidate}")
            break

方法2:使用Python的coppersmith库

如果用纯Python,安装coppersmith库后执行:

import coppersmith

# 替换为题目给定的n、pa
n = 0x...
pa = 0x...

# 寻找小根,x的上限是2^512
root = coppersmith.small_roots(pa + coppersmith.X, n, X=2**512, beta=0.5)[0]
p_candidate = pa + int(root)
q_candidate = n // p_candidate

print(f"p = {p_candidate}")
print(f"q = {q_candidate}")

3. 破解明文

得到p和q后,计算私钥d并解密:

# 替换为题目给定的e、c
e = 0x...
c = 0x...

phi = (p_candidate - 1) * (q_candidate - 1)
d = pow(e, -1, phi)
m_int = pow(c, d, n)
# 转换为bytes得到flag
flag = m_int.to_bytes((m_int.bit_length() + 7) // 8, byteorder='big')
print(flag.decode())

内容的提问来源于stack exchange,提问作者user25421456

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 22:12:03