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 等,避免信息泄露。

相关推荐
smj2302_796826522 小时前
解决leetcode第3791题.给定范围内平衡整数的数目
python·算法·leetcode
不能只会打代码2 小时前
力扣--1970. 你能穿过矩阵的最后一天(Java)
java·算法·leetcode·二分查找·力扣·bfs·最后可行时间
m0_738120722 小时前
渗透测试——靶机DC-6详细横向过程(Wordpress渗透)
服务器·网络·python·web安全·ssh·php
AndrewHZ2 小时前
【图像处理基石】如何高质量地生成一张庆祝元旦的图片?
图像处理·人工智能·opencv·算法·计算机视觉·生成式模型·genai
CryptoPP2 小时前
对接BSE交易所获取数据。
python·金融·数据挖掘·数据分析·区块链
光明西道45号2 小时前
Leetcode 15. 三数之和
数据结构·算法·leetcode
老歌老听老掉牙2 小时前
PyQt5中RadioButton互斥选择的实现方法
开发语言·python·qt
Pyeako2 小时前
Opencv计算机视觉
人工智能·python·深度学习·opencv·计算机视觉
还不秃顶的计科生2 小时前
LeetCode 热题 100第一题:两数之和python版本
python·算法·leetcode