加载中
499 字
2 分钟
RSA-dp泄露
2023-10-08 10:38

RSA-dp泄露

原理

0x00 基本数学公式

a=kb+pa = k * b + pamodb=pa mod b = p

0x01 RSA的基本公式

c ≡ m ^ e mod n
m ≡ c ^ d mod n
ϕ(n) = (p − 1) * (q − 1)
d * e ≡ 1 mod ϕ(n) # 乘法逆元

0x02 dp是什么

dp ≡ d mod (p − 1)

0x03 推导过程

dp ≡ d mod (p − 1)
# 两边同时乘以 e
=> dp * e = d * e mod (p - 1)
=> dp * e = d * e - k * (p - 1)
=> d * e = dp * e + k * (p - 1)
# 与下面的公式结合
d * e ≡ 1 mod ϕ(n)
# 因为:
ϕ(n) = (p − 1) * (q − 1)
# 所以可以变形:
=> d * e = 1 mod (p − 1) * (q − 1)
# 变形:
dp * e + k * (p - 1) = 1 mod (p − 1) * (q − 1)
# 结合:
dp * e + k * (p - 1) = 1 + k * (p − 1) * (q − 1)
=> dp * e = 1 + k * (p − 1) * (q − 1) - k * (p - 1)
=> dp * e = 1 + [k * (q - 1) - k] * (p - 1)
# 设 i = [k * (q - 1) - k]
=> dp * e = 1 + i * (p - 1)
dp * e = 1 + i * (p - 1)
=> dp < p - 1
=> i < e
=> i ∈ (0, e)

0x04 求p

遍历 i(65537种可能),求出( p − 1 ) (p - 1) * (p − 1),得到 p 且能被 n 整除;接下来就是常规 RSA 的解法
for i in range(1, 65535):
p = (dp * e - 1) // i + 1
if n % p == 0:
q = n // p
phi_n = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi_n)
m = pow(c, d, n)
flag = libnum.n2s(int(m)).decode()
print(flag)
break

例题

[WUSTCTF2020] dp_leaking_1s_very_d@angerous

题目

e = 65537
n = 156808343598578774957375696815188980682166740609302831099696492068246337198792510898818496239166339015207305102101431634283168544492984586566799996471150252382144148257236707247267506165670877506370253127695314163987084076462560095456635833650720606337852199362362120808707925913897956527780930423574343287847
c = 108542078809057774666748066235473292495343753790443966020636060807418393737258696352569345621488958094856305865603100885838672591764072157183336139243588435583104423268921439473113244493821692560960443688048994557463526099985303667243623711454841573922233051289561865599722004107134302070301237345400354257869
dp = 734763139918837027274765680404546851353356952885439663987181004382601658386317353877499122276686150509151221546249750373865024485652349719427182780275825

解密脚本

import gmpy2
import libnum
from Crypto.Util.number import long_to_bytes
e = 65537
n = 156808343598578774957375696815188980682166740609302831099696492068246337198792510898818496239166339015207305102101431634283168544492984586566799996471150252382144148257236707247267506165670877506370253127695314163987084076462560095456635833650720606337852199362362120808707925913897956527780930423574343287847
c = 108542078809057774666748066235473292495343753790443966020636060807418393737258696352569345621488958094856305865603100885838672591764072157183336139243588435583104423268921439473113244493821692560960443688048994557463526099985303667243623711454841573922233051289561865599722004107134302070301237345400354257869
dp = 734763139918837027274765680404546851353356952885439663987181004382601658386317353877499122276686150509151221546249750373865024485652349719427182780275825
for i in range(1, e):
p = (dp * e - 1) // i + 1
if n % p == 0:
q = n // p
phi = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
# print(m)
print(long_to_bytes(m))
# print(libnum.n2s(int(m)))
break
RSA-dp泄露
/posts/2023/10/rsa-dp-leak/
作者
dacj4n
发布于
2023-10-08
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时