NSSCTF_crypto_[SWPUCTF 2023 秋季新生赛]dpdp

题目:

python 复制代码
from Crypto.Util.number import *
from libnum import *

flag = b'NSSCTF{******}' + b'1010101010101010101010101010101010101010100010101010101010101010101101'
p = getPrime(512)
q = getPrime(512)
n = p*q
e = 65537
d = inverse(e, (p-1)*(q-1))
dp = d % (p-1)
m = s2n(flag)
c = pow(m, e, n)
print(f'n = {n}')
print(f'c = {c}')
print(f'dp = {dp}')

'''
n = 62950660589752377241535942010457460675378335694404721223426371627802159493655570041534480026979837056215567303530448462076388942749116962945931432723672826148999814815864738069663127706046027850586024555861960247057288826014343547293035737544457656904257388300461848219257240252715837662741274235378360898441
c = 26392919777656338278184497106215581599692023606797351841011065350738534402079717897589592521000832026751736045905247050532819571969784687491977953157313304550096179520376626220816081159472339787295872214912587497324709488986746768994907107727184468228540635002062232484115731701648311946527233449512543132274
dp = 7088497034630351463006975624795947102639056977565074157092915907376477955247769847204254053775159112398217033648894620506901638351932922911273150932128973
'''

题目分析

题目提供了以下参数:

  • n: RSA 模数

  • c: 密文

  • dp: 私钥指数 d 对 (p-1) 取模的结果,即 dp = d mod (p-1)

  • e: 公钥指数,值为 65537

这是一个典型的 dp 泄露攻击,当我们知道 dp 时,可以恢复出私钥并解密密文。

数学原理

根据 RSA 定义:

  1. d * e ≡ 1 mod φ(n),其中 φ(n) = (p-1)(q-1)

  2. dp = d mod (p-1)

  3. 由 (2) 可得:d = dp + k*(p-1),其中 k 是一个整数

  4. 将 (3) 代入 (1):e * (dp + k*(p-1)) ≡ 1 mod (p-1)

  5. 化简得:e * dp ≡ 1 mod (p-1),即 e * dp - 1 ≡ 0 mod (p-1)

这意味着 e*dp - 1(p-1) 的倍数。我们可以通过遍历 k 来寻找 p 的值。

解题步骤

步骤 1:寻找 p

根据上述推导,我们有:

python 复制代码
e * dp = 1 + k * (p-1)

其中 k 是 1 到 e 之间的整数(因为 dp < p-1)。

我们可以遍历所有可能的 k,检查 (e*dp - 1) 是否能被 k 整除,从而得到候选的 p:

python 复制代码
p = (e*dp - 1)/k + 1

步骤 2:验证并计算 q

找到候选的 p 后,检查:

  1. p 是否为整数

  2. n 是否能被 p 整除

  3. p 是否为素数(这里简化检查:n % p == 0)

如果满足条件,则:

python 复制代码
q = n // p

步骤 3:计算私钥 d

使用公式:

python 复制代码
φ(n) = (p-1) * (q-1)
d = e^(-1) mod φ(n)  # 即 e 关于 φ(n) 的模逆元

步骤 4:解密密文

使用 RSA 解密公式:

python 复制代码
m = c^d mod n

完整代码

python 复制代码
from Crypto.Util.number import *

# 题目给出的参数
n = 62950660589752377241535942010457460675378335694404721223426371627802159493655570041534480026979837056215567303530448462076388942749116962945931432723672826148999814815864738069663127706046027850586024555861960247057288826014343547293035737544457656904257388300461848219257240252715837662741274235378360898441
c = 26392919777656338278184497106215581599692023606797351841011065350738534402079717897589592521000832026751736045905247050532819571969784687491977953157313304550096179520376626220816081159472339787295872214912587497324709488986746768994907107727184468228540635002062232484115731701648311946527233449512543132274
dp = 7088497034630351463006975624795947102639056977565074157092915907376477955247769847204254053775159112398217033648894620506901638351932922911273150932128973
e = 65537

# 步骤1:遍历 k 寻找 p
print("开始寻找素数 p...")
for k in range(2, e):  # k 从 2 开始,因为 k=1 时 p 可能太大
    # 检查 (e*dp - 1) 是否能被 k 整除
    if (e * dp - 1) % k == 0:
        # 计算候选的 p
        p = (e * dp - 1) // k + 1
        
        # 步骤2:验证 p
        # 检查1: p 是否能整除 n
        if n % p == 0:
            print(f"找到可能的 k = {k}")
            print(f"p = {p}")
            
            # 计算 q
            q = n // p
            print(f"q = {q}")
            
            # 验证 p 和 q 的乘积是否等于 n
            if p * q == n:
                print("验证成功: p * q == n")
                
                # 步骤3:计算私钥 d
                phi = (p - 1) * (q - 1)
                d = inverse(e, phi)  # 计算 e 关于 φ(n) 的模逆元
                print(f"d = {d}")
                
                # 步骤4:解密密文
                m = pow(c, d, n)
                print(f"解密得到的整数 m = {m}")
                
                # 转换为字节串
                flag = long_to_bytes(m)
                print(f"解密得到的 flag = {flag}")
                
                # 由于我们可能找到多个解,这里只取第一个有效的解
                break
            else:
                print("验证失败: p * q != n")
        else:
            continue  # 继续尝试下一个 k

print("\n解密完成!")

最后flag为

NSSCTF{CTFCTFNSSNSS}

总结

  1. 漏洞点:dp 泄露是 RSA 中常见的侧信道攻击,当攻击者知道 dp = d mod (p-1) 时,可以恢复私钥。

  2. 关键步骤 :利用关系式 e*dp ≡ 1 mod (p-1),通过遍历 k 来找到 p。

  3. 防御措施:在实际应用中,需要保护所有私钥参数,包括 d、dp、dq 等,避免信息泄露。

相关推荐
老鼠只爱大米3 分钟前
LeetCode经典算法面试题 #46:全排列(回溯、交换、剪枝等五种实现方案详细解析)
算法·leetcode·剪枝·回溯·全排列·stj算法
Pyeako11 分钟前
深度学习--卷积神经网络(下)
人工智能·python·深度学习·卷积神经网络·数据增强·保存最优模型·数据预处理dataset
OPEN-Source13 分钟前
大模型实战:搭建一张“看得懂”的大模型应用可观测看板
人工智能·python·langchain·rag·deepseek
廖圣平14 分钟前
从零开始,福袋直播间脚本研究【七】《添加分组和比特浏览器》
python
B站_计算机毕业设计之家14 分钟前
豆瓣电影数据可视化分析系统 | Python Flask框架 requests Echarts 大数据 人工智能 毕业设计源码(建议收藏)✅
大数据·python·机器学习·数据挖掘·flask·毕业设计·echarts
Dovis(誓平步青云)17 分钟前
《滑动窗口算法:从 “暴力遍历” 到 “线性高效” 的思维跃迁》
运维·服务器·数据库·算法
mr_LuoWei200930 分钟前
python工具:python代码知识库笔记
数据库·python
weixin_3954489130 分钟前
cursor日志
人工智能·python·机器学习
_OP_CHEN43 分钟前
【算法基础篇】(五十七)线性代数之矩阵乘法从入门到实战:手撕模板 + 真题详解
线性代数·算法·矩阵·蓝桥杯·c/c++·矩阵乘法·acm/icpc
天天爱吃肉82181 小时前
【跨界封神|周杰伦×王传福(陶晶莹主持):音乐创作与新能源NVH测试,底层逻辑竟完全同源!(新人必看入行指南)】
python·嵌入式硬件·算法·汽车