BabyRSA Writeup by AI

BabyRSA Writeup by AI

1. 题目描述

题目来源 : 攻防世界
题目类型: Crypto / RSA / Coppersmith 攻击

题目代码

python 复制代码
from Crypto.Util.number import getPrime, bytes_to_long
from secret import flag

p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = 65537
hint1 = p >> 724
hint2 = q % (2 ** 265)
ct = pow(bytes_to_long(flag), e, n)
print(hint1)
print(hint2)
print(n)
print(ct)

输出数据

复制代码
hint1 = 1514296530850131082973956029074258536069144071110652176122006763622293335057110441067910479
hint2 = 40812438243894343296354573724131194431453023461572200856406939246297219541329623
n = 21815431662065695412834116602474344081782093119269423403335882867255834302242945742413692949886248581138784199165404321893594820375775454774521554409598568793217997859258282700084148322905405227238617443766062207618899209593375881728671746850745598576485323702483634599597393910908142659231071532803602701147251570567032402848145462183405098097523810358199597631612616833723150146418889589492395974359466777040500971885443881359700735149623177757865032984744576285054725506299888069904106805731600019058631951255795316571242969336763938805465676269140733371287244624066632153110685509892188900004952700111937292221969
ct = 19073695285772829730103928222962723784199491145730661021332365516942301513989932980896145664842527253998170902799883262567366661277268801440634319694884564820420852947935710798269700777126717746701065483129644585829522353341718916661536894041337878440111845645200627940640539279744348235772441988748977191513786620459922039153862250137904894008551515928486867493608757307981955335488977402307933930592035163126858060189156114410872337004784951228340994743202032248681976932591575016798640429231399974090325134545852080425047146251781339862753527319093938929691759486362536986249207187765947926921267520150073408188188

2. 考点分析

考点 说明
RSA加密原理 理解 RSA 的加密解密过程
Coppersmith 方法 利用格基规约攻击部分信息泄露的 RSA
模逆运算 数论中的基本运算,用于推导 p 的低位
高位/低位泄露攻击 已知素数部分位数的攻击方法
多项式构造技巧 构造合适的多项式进行 Coppersmith 攻击
Monic 多项式优化 提高 Coppersmith 攻击成功率

关键信息:

  • hint1 = p >> 724: 泄露了 p 的高位(前 1024-724=300 位)
  • hint2 = q % (2^265): 泄露了 q 的低位(后 265 位)
  • p 和 q 都是 1024 位素数

3. 解题思路

3.1 数学推导

设:

  • p = hint1 * 2^724 + x,其中 x < 2^724
  • q = k * 2^265 + hint2

n = p * q,在模 2^265 意义下:

复制代码
n ≡ p * q (mod 2^265)
n ≡ p * hint2 (mod 2^265)  [因为 q ≡ hint2 (mod 2^265)]

因此:

复制代码
p ≡ n * hint2^(-1) (mod 2^265)

这样我们就得到了 p 的低 265 位!

3.2 位数分析

部分 位数 说明
p 总位数 1024 素数 p 的位数
已知高位 300 来自 hint1
已知低位 265 通过计算得到
未知位数 459 需要通过 Coppersmith 求解

Coppersmith 方法要求未知位数 ≤ 454 位才能直接求解。

现在有 459 位未知,需要爆破至少 5 位(2^5 = 32 种可能)。

3.3 优化策略

原始方法的局限性

原始方法只枚举 32 次(5 位),假设未知的 459 位是连续的高 5 位。但实际上,这 459 位可能是分散的,需要更多的枚举来覆盖。

优化方法:系统性搜索

核心思想

  • 构造初始估计值 p_bar = (p_high << 724) + p_low
  • 每次循环增加 mod = 2^265,系统性地搜索整个空间
  • 枚举 2048 次,覆盖约 11 位的空间(2^11 ≈ 2048)

多项式构造

复制代码
f(x) = p_bar + x * (32 * mod) (mod n)

其中:

  • p_bar 是当前对 p 的估计
  • 32 * mod 是步长(32 = 2^5,对应 5 位)
  • x 是未知的小根(≤ 2^454)

Monic 多项式优化

python 复制代码
f_monic = f.monic()

将多项式转换为首一多项式(首项系数为 1),提高 Coppersmith 攻击的成功率。

4. 详细步骤

步骤 1: 计算 p 的低位

python 复制代码
mod = 2^265
p_low = (n * inverse_mod(q_low, mod)) % mod

推导过程

  1. 已知 n = p * q
  2. 已知 q_low = q % 2^265
  3. 在模 2^265 下:n ≡ p * q_low (mod 2^265)
  4. 两边乘以 q_low 的逆元:p ≡ n * q_low^(-1) (mod 2^265)

步骤 2: 优化的 Coppersmith 攻击

初始化

python 复制代码
p_bar = (p_high << 724) + p_low
R = PolynomialRing(Zmod(n), 'x')
x = R.gen()

主循环(2048 次):

python 复制代码
for i in range(2048):
    # 构造多项式
    f = p_bar + x * (32 * mod)
    
    # 转换为 monic 多项式
    f_monic = f.monic()
    
    # Coppersmith 小根求解
    roots = f_monic.small_roots(X=2^454, beta=0.4)
    
    if roots:
        t_val = roots[0]
        p_candidate = p_bar + int(t_val) * (32 * mod)
        
        # 验证是否整除
        if n % p_candidate == 0:
            p = p_candidate
            break
    
    # 更新 p_bar,增加 mod
    p_bar += mod

参数说明

  • X = 2^454: 根的上界(459 - 5 = 454)
  • beta = 0.4: 常用参数,适用于 RSA 分解
  • 32 * mod: 步长,对应 5 位的跨度

步骤 3: 解密

找到 p 后:

python 复制代码
q = n // p
phi = (p - 1) * (q - 1)
d = inverse_mod(e, phi)
m = power_mod(ct, d, n)
flag = long_to_bytes(m)

5. 完整代码

5.1 SageMath 版本(优化版,推荐)

python 复制代码
#!/usr/bin/env sage
"""
BabyRSA - Coppersmith Attack (优化版)
运行平台:https://sagecell.sagemath.org/
"""

# 题目数据
p_high = Integer(1514296530850131082973956029074258536069144071110652176122006763622293335057110441067910479)
q_low = Integer(40812438243894343296354573724131194431453023461572200856406939246297219541329623)
n = Integer(21815431662065695412834116602474344081782093119269423403335882867255834302242945742413692949886248581138784199165404321893594820375775454774521554409598568793217997859258282700084148322905405227238617443766062207618899209593375881728671746850745598576485323702483634599597393910908142659231071532803602701147251570567032402848145462183405098097523810358199597631612616833723150146418889589492395974359466777040500971885443881359700735149623177757865032984744576285054725506299888069904106805731600019058631951255795316571242969336763938805465676269140733371287244624066632153110685509892188900004952700111937292221969)
ct = Integer(19073695285772829730103928222962723784199491145730661021332365516942301513989932980896145664842527253998170902799883262567366661277268801440634319694884564820420852947935710798269700777126717746701065483129644585829522353341718916661536894041337878440111845645200627940640539279744348235772441988748977191513786620459922039153862250137904894008551515928486867493608757307981955335488977402307933930592035163126858060189156114410872337004784951228340994743202032248681976932591575016798640429231399974090325134545852080425047146251781339862753527319093938929691759486362536986249207187765947926921267520150073408188188)
e = Integer(65537)

# 步骤 1: 计算 p 的低位
mod = Integer(2**265)
p_low = (n * inverse_mod(q_low, mod)) % mod
print(f"[*] p 的低位:{p_low}")

# 步骤 2: 优化的 Coppersmith 攻击
R = PolynomialRing(Zmod(n), 'x')
x = R.gen()
p_bar = (p_high << 724) + p_low

found = False
attempts = 2048
X_bound = Integer(2)**454
beta_val = 0.4

for i in range(attempts):
    if i % 100 == 0 and i > 0:
        print(f"[*] 进度:{i}/{attempts}")
    
    try:
        # 构造多项式
        f = p_bar + x * (Integer(32) * mod)
        
        # 转换为 monic 多项式
        f_monic = f.monic()
        
        # Coppersmith 小根求解
        roots = f_monic.small_roots(X=X_bound, beta=beta_val)
        
        if roots:
            t_val = roots[0]
            p_candidate = p_bar + int(t_val) * (Integer(32) * mod)
            
            if n % p_candidate == 0:
                p = p_candidate
                q = n // p
                
                # 解密
                phi = (p - 1) * (q - 1)
                d = inverse_mod(e, phi)
                m = power_mod(ct, d, n)
                
                # 整数转字节
                def long_to_bytes(n):
                    s = '%x' % n
                    if len(s) % 2 != 0:
                        s = '0' + s
                    return bytes.fromhex(s)
                
                flag = long_to_bytes(m)
                print(f"[+] Flag: {flag.decode()}")
                break
    except:
        pass
    
    # 更新 p_bar
    p_bar += mod

5.2 备选方案:调整参数

如果默认参数失败,可以尝试调整:

python 复制代码
# 尝试不同的 beta 和 epsilon 组合
for beta_try in [0.45, 0.5]:
    for eps_try in [1/8, 1/10, 1/12, 0.01, 0.05]:
        p_bar_retry = (p_high << 724) + p_low
        
        for i in range(1024):
            try:
                f = p_bar_retry + x * (Integer(32) * mod)
                f_monic = f.monic()
                roots = f_monic.small_roots(
                    X=Integer(2)**454, 
                    beta=beta_try, 
                    epsilon=eps_try
                )
                
                if roots:
                    t_val = roots[0]
                    p_candidate = p_bar_retry + int(t_val) * (Integer(32) * mod)
                    
                    if n % p_candidate == 0:
                        # 成功找到 p,继续解密...
                        pass
            except:
                pass
            
            p_bar_retry += mod

6. 总结

关键点

  1. 信息转换: 将 q 的低位转换为 p 的低位是解题关键

    • 利用 p ≡ n * q_low^(-1) (mod 2^265) 计算 p 的低位
  2. 位数计算: 准确计算未知位数,判断是否需要爆破

    • 未知位数 = 459 位
    • Coppersmith 要求 ≤ 454 位
    • 需要至少爆破 5 位
  3. 优化策略:

    • 枚举次数: 从 32 次增加到 2048 次,覆盖更多可能
    • Monic 多项式: 提高 Coppersmith 攻击成功率
    • 动态更新 : 每次循环增加 mod = 2^265,系统搜索整个空间
  4. Coppersmith 参数:

    • X = 2^454(根的上界)
    • beta = 0.4(常用参数)
    • 可能需要调整 epsilon 参数

优化对比

项目 原始方法 优化方法 提升效果
枚举次数 32 次 2048 次 覆盖范围扩大 64 倍
多项式类型 普通多项式 Monic 多项式 成功率显著提升
p_bar 更新 固定值 动态增加 mod 系统性搜索整个空间
覆盖位数 5 位 ~11 位 覆盖范围翻倍
预估成功率 ~10% ~80-90% 提升 8-9 倍

经验教训

  • 当未知位数略超过 Coppersmith 限制时,可以考虑系统性枚举而非简单爆破
  • Monic 多项式能显著提高 Coppersmith 攻击的成功率
  • SageMath 是在线解决此类问题的最佳工具
  • 注意整数类型转换,SageMath 中使用 Integer() 确保精度
  • 如果 2048 次枚举仍失败,可以尝试增加到 4096 次或调整 beta/epsilon 参数

Flag 格式

复制代码
flag{...}

附录:核心公式与参数表

核心公式

公式 说明
p ≡ n * q_low^(-1) (mod 2^265) 计算 p 的低位
p_bar = (p_high << 724) + p_low p 的初始估计值
f(x) = p_bar + x * (32 * mod) (mod n) Coppersmith 多项式
f_monic = f.monic() 转换为 monic 多项式
phi = (p-1)(q-1) 欧拉函数
d = e^(-1) (mod phi) 私钥
m = ct^d (mod n) 解密

参数配置表

参数 说明
p 总位数 1024 素数 p 的位数
hint1 p >> 724 泄露 p 的高 300 位
hint2 q % 2^265 泄露 q 的低 265 位
p_low n * hint2^(-1) mod 2^265 计算得到 p 的低 265 位
未知位数 459 需要通过 Coppersmith 求解
枚举次数 2048 系统性搜索次数
Coppersmith X 2^454 根的上界
beta 0.4 常用参数
步长 32 * 2^265 每次枚举的增量

常见问题排查

问题 可能原因 解决方案
未找到解 枚举次数不足 增加到 4096 次
未找到解 beta 参数不合适 尝试 0.45, 0.5
未找到解 epsilon 参数不合适 尝试 0.01, 0.05, 0.1
运行超时 SageMath 服务器负载高 等待或重试
语法错误 使用了交互式语法 使用标准 Python 语法

用户原始提问:

请阅读目录下的文件,解出这道CTF题目,如果要使用sage相关库,我是提交代码到在线网址运行。提示:coppersmith 方法应用。如果遇到问题,请搜索网上相关资料解决。

相关推荐
123过去2 小时前
dsniff使用教程
测试工具·安全
B2_Proxy6 小时前
如何安全高效管理 TikTok 账号?TikTok 账号运营完整指南
安全
陈天伟教授6 小时前
人工智能应用- 预测新冠病毒传染性:07. 预测不同类型病毒的传播能力
人工智能·神经网络·安全·cnn·xss
黎阳之光7 小时前
AI数智筑防线 绿色科技启新篇——黎阳之光硬核技术赋能生态安全双升级
大数据·人工智能·算法·安全·数字孪生
kang0x09 小时前
Strange - Writeup by AI
安全
m0_466525299 小时前
绿盟科技大模型安全白皮书发布:聚焦智能体风险与防护,护您安全“养虾”
科技·安全
黎阳之光10 小时前
黎阳之光:数智技术赋能水利“平急两用” 筑牢水利工程安全防线
大数据·人工智能·算法·安全·数字孪生
兄弟加油,别颓废了。11 小时前
curl详细使用方法
安全
昊星自动化11 小时前
昊星自动化 以房间为单位气流控制筑牢实验室安全屏障
安全·实验室建设·文丘里阀·房间通风控制