Loading

RSA dp泄漏攻击

dp泄漏攻击

给 n, e, d p, c

\[\begin{array}{l} &&&&&&&&&&&&&\\ d p \equiv d(\bmod (p-1)) \\ \because d p \cdot e \equiv d \cdot e \equiv 1(\bmod (p-1)) \\ \therefore d p \cdot e-1=k \cdot(p-1) \\ \therefore(d p \cdot e-1) \cdot d \cdot e=k^{\prime} \cdot(p-1), \quad k^{\prime}=k \cdot d \cdot e \\ \Leftrightarrow d \cdot e=-k^{\prime} \cdot(p-1)+d p \cdot e \cdot d \cdot e \equiv 1(\bmod \varphi(n)) \\ \Leftrightarrow-k^{\prime} \cdot(p-1)+d p \cdot e \equiv 1(\bmod \varphi(n)) \\ \therefore k_{1} \cdot(p-1)+d p \cdot e-1=k_{2} \cdot(p-1) \cdot(q-1) \\ \Leftrightarrow(p-1) \cdot\left(k_{2} \cdot(q-1)-k_{1}\right)+1=d p \cdot e \\ \because d p<p-1 \quad \therefore\left(k_{2} \cdot(q-1)-k_{1}\right) \in(0, e) \\ \therefore \text { 惼历 }(1, e), \text { 当同时满足 }(d p \cdot e-1) \bmod i==0 \text { 和 } \\ n \bmod ((d p \cdot e-1) / / i+1)==0 \text { 时, } N \text { 成功分解。 } \end{array} \]

import gmpy2 as gp

e = 
n = 
dp = 
c = 

for x in range(1, e):
	if(e*dp%x==1):
		p=(e*dp-1)//x+1
		if(n%p!=0):
			continue
		q=n//p
		phin=(p-1)*(q-1)
		d=gp.invert(e, phin)
		m=gp.powmod(c, d, n)
		if(len(hex(m)[2:])%2==1):
			continue
		print('--------------')
		print(m)
		print(hex(m)[2:])
		print(bytes.fromhex(hex(m)[2:]))

变种1

image

from Crypto.Util.number import *
import gmpy2
p = 
dp = 
c = 
b = 
e = 
mp1 = pow(c, dp, p)
mp = pow(c, dp - 1, p)
for i in range(1, b - 2):
	x = pow(c - pow(mp1, e), 1, p**(i + 1))
	y = pow(x * mp * (gmpy2.invert(e, p)), 1, p**(i + 1))
	mp1 = mp1 + y
print(long_to_bytes(mp1))

变种2

  • $变种 2 : 给 n, e, d p_{0}, c, k , 其中 d p_{0} 为 d p 高 (n bits -k) 位, 即 d p_{0}=d p>>k_{\text {。 }} $
    (Coppersmith攻击, 已知dp高位攻击)

\[\begin{array}{l} &&&&&&&&&&&&&&&&&\\ e \cdot d p \equiv e \cdot d \equiv 1(\bmod (p-1)) \\ \Leftrightarrow e \cdot d p=k(p-1)+1=k p-k+1 \\ \Leftrightarrow e \cdot d p+k-1 \equiv 0(\bmod p) \\ \because d p<p-1, \therefore k<e \\ \therefore e \cdot\left(d p_{0}<<k+x\right)+k-1 \equiv 0(\bmod p) \end{array} \]

#Sage
dp0 = 
e = 
n = 

F.<x> = PolynomialRing(Zmod(n))
d = inverse_mod(e, n)
for k in range(1, e):
	f = (secret << 200) + x + (k - 1) * d
	x0 = f.small_roots(X=2 ** (200 + 1), beta=0.44, epsilon=1/32)
	if len(x0) != 0:
		dp = x0[0] + (secret << 200)
		for i in range(2, e):
			p = (e * Integer(dp) - 1 + i) // i
			if n % p == 0:
				break
		if p < 0:
			continue
		else:
			print('k = ',k)
			print('p = ',p)
			print('dp = ',dp)
			break

变种3

  • 变种 3 : 给 n, e, d p, c , 其中 d p 很小, e 很大。

    \(枚举 d p , 因 e \cdot d p \equiv 1(\bmod (p-1)) , 又由费马小定理, 对任意 r , 有 \\ m^{e \cdot d p} \equiv m(\bmod p) , 即 p \mid\left(m^{e \cdot d p}-m\right) ;\\ 又 p \mid n , 很大概率 p=\operatorname{gcd}\left(m^{e \cdot d p}-m, n\right) 。\)

变种4

  • 变种4 : 给 N, e, c , 其中 d p 过小。

情形1: $q<N^{0.382} $

\(参数 \beta=\frac{q_{\text {bit }}}{N_{\text {bit }}}, \delta=\frac{d p_{\text {bit }}}{N_{\text {bit }}} ,满足 3 \beta<1+\beta^{2}+2 \delta , 可确定 \beta 和 \delta 的值。\\ 构造格子维度为 n , 格子中模数 N 的最大次幂为 m , 应满足关系\)

\(\frac{m(m+1)}{2}+\frac{n(n-1)(2 \delta+\beta)}{2}-(1-\beta) n m<0\)

确定 $ \beta $和 $\delta $之后,可枚举确定 n 和 m 的取值 (最小值) , $$ m=(1-\beta) n $$ 是 一个较优的取值。

beta = 
delta = 
n = round((1-2*beta-2*delta)/((1-beta)^2-2*delta-beta),6)
m = (1-beta)*n
print(m,n)

构造多项式,分解多项式为\((ax+by)\)的项,其中\(a=k\)\(b=dp\)

# 脚本1
# Sage
def getC(Scale):
    C = [[0 for __ in range(Scale)] for _ in range(Scale)]
    for i in range(Scale):
        for j in range(Scale):
            if i == j or j == 0:
                C[i][j] = 1
            else:
                C[i][j] = C[i-1][j-1] + C[i-1][j]
    return C

def getMatrix(Scale, Mvalue, N, E, Del, Bet):
    M = [[0 for __ in range(Scale)] for _ in range(Scale)]
    C = getC(Scale)
    X, Y = int(pow(N,Del)*(Scale+1)//2), int(pow(N,(Del+Bet))*(Scale+1)//2)
    for i in range(Scale):
        for j in range(Scale):
            M[i][j] = N**max(Mvalue-i,0)*E**(max(i-j,0))*X**(Scale-1-j)*Y**j*C[i][j]*(-1)**j
    return M

N =
E =
delta = 0.01
beta = 0.37
Scale = 35
Mvalue = 22
M = getMatrix(Scale,Mvalue,N,E,delta,beta)
M = matrix(ZZ,M)
A = M.LLL()[0]
p = []
X = int(pow(N,delta)*(Scale+1)//2)
Y = int(pow(N,(delta+beta))*(Scale+1)//2)
for i in range(Scale):
    p.append(A[i]//(X**(Scale-1-i)*Y**i))
PR.<x,y> = PolynomialRing(ZZ)
f = 0
for i in range(Scale):
    f += p[i]*x^(Scale-1-i)*y^i
print(f.factor())
# 脚本2
# Sage
N =
e =

n = 12
beta = 0.36
delta = 0.02

X = int(N ** delta*(n+1)/2)
Y = int(N ** (delta + beta)*(n+1)/2)

def C(a,b):
    ret=1
    for i in range(b):
        ret *= (a-i)
        ret /= (b-i)
    return ret
def get_Matrix(n,m):
    MM=[[0 for __ in range(n)] for _ in range(n)]
    for j in range(n): 
        pN = max(0,m-j)
        for i in range(j+1):
            MM[j][i] = pow(N,pN)*pow(X,n-i-1)*pow(Y,i)*pow(e,j-i)*C(j,i)*pow(-1,i)
    MM = Matrix(ZZ,MM)
    return MM

M = get_Matrix(n,n//2+1)
L = M.LLL()[0]

x,y = var('x'),var('y')
f = 0
for i in range(n):
    f += x**(n-i-1) * y**i * (L[i] // pow(X,n-i-1) // pow(Y,i))

print(f.factor())

参考:

Cryptanalysis of Unbalanced RSA with Small CRT-Exponent

https://hash-hash.github.io/2022/05/14/Unbalanced-RSA-with-Small-CRT-Exponent/#An-Approach-Modulo-e

NSSCTF Round#3 - Secure_in_N

情形2 : $q<N^{0.468} $

\(参数 \beta=\frac{q_{\text {bit }}}{N_{\text {bit }}}, \delta=\frac{d p_{\text {bit }}}{N_{\text {bit }}}, \alpha=\frac{e_{\text {bit }}}{N_{\text {bit }}} , \\变量上界 X=2 N^{\alpha+\beta+\delta-1}, Y=N^{\beta}, Z=2 N^{1-\beta} , 对于变量 m 需充分 大。\)

\(\tau=\frac{(1-\beta)^{2}-\delta}{2 \beta(1-\beta)}, \sigma=\frac{1-\beta-\delta}{2(1-\beta)}, t=\tau m, s=\sigma m\)

\(整数域上有根 (x, y, z)=\left(x_{0}, p, q\right) 。\)

from copy import deepcopy
# https://www.iacr.org/archive/pkc2006/39580001/39580001.pdf
# Author: ZM__________J, To1in
N = 
e = 
alpha = log(e, N)
beta = 
delta = 
P.<x,y,z>=PolynomialRing(ZZ)
 
X = ceil(2 * N^(alpha + beta + delta - 1))
Y = ceil(2 * N^beta)
Z = ceil(2 * N^(1 - beta))
 
def f(x,y):
    return x*(N-y)+N
def trans(f):
    my_tuples = f.exponents(as_ETuples=False)
    g = 0
    for my_tuple in my_tuples:
        exponent = list(my_tuple)
        mon = x ^ exponent[0] * y ^ exponent[1] * z ^ exponent[2]
        tmp = f.monomial_coefficient(mon)
        
        my_minus = min(exponent[1], exponent[2])
        exponent[1] -= my_minus
        exponent[2] -= my_minus
        tmp *= N^my_minus
        tmp *= x ^ exponent[0] * y ^ exponent[1] * z ^ exponent[2]
        
        g += tmp
    return g
  
m = 5 # need to be adjusted according to different situations
tau = ((1 - beta)^2 - delta) / (2 * beta * (1 - beta))
sigma = (1 - beta - delta) / (2 * (1 - beta))
 
print(sigma * m)
print(tau * m)
 
s = ceil(sigma * m)
t = ceil(tau * m)
my_polynomials = []
for i in range(m+1):
    for j in range(m-i+1):
        g_ij = trans(e^(m-i) * x^j * z^s * f(x, y)^i)
        my_polynomials.append(g_ij)
 
for i in range(m+1):
    for j in range(1, t+1):
        h_ij = trans(e^(m-i) * y^j * z^s * f(x, y)^i)
        my_polynomials.append(h_ij)
        
known_set = set()
new_polynomials = []
my_monomials = []
 
# construct partial order
while len(my_polynomials) > 0:
    for i in range(len(my_polynomials)):
        f = my_polynomials[i]
        current_monomial_set = set(x^tx * y^ty * z^tz for tx, ty, tz in f.exponents(as_ETuples=False))
        delta_set = current_monomial_set - known_set
        if len(delta_set) == 1:
            new_monomial = list(delta_set)[0]
            my_monomials.append(new_monomial)
            known_set |= current_monomial_set
            new_polynomials.append(f)            
            my_polynomials.pop(i)
            break
    else:
        raise Exception('GG')
        
my_polynomials = deepcopy(new_polynomials)
 
nrows = len(my_polynomials)
ncols = len(my_monomials)
L = [[0 for j in range(ncols)] for i in range(nrows)]
 
for i in range(nrows):
    g_scale = my_polynomials[i](X * x, Y * y, Z * z)
    for j in range(ncols):
        L[i][j] = g_scale.monomial_coefficient(my_monomials[j])
        
# remove N^j
for i in range(nrows):
    Lii = L[i][i]
    N_Power = 1
    while (Lii % N == 0):
        N_Power *= N
        Lii //= N
    L[i][i] = Lii
    for j in range(ncols):
        if (j != i):
            L[i][j] = (L[i][j] * inverse_mod(N_Power, e^m))
 
L = Matrix(ZZ, L)
nrows = L.nrows()
 
L = L.LLL()
# Recover poly
reduced_polynomials = []
for i in range(nrows):
    g_l = 0
    for j in range(ncols):
        g_l += L[i][j] // my_monomials[j](X, Y, Z) * my_monomials[j]
    reduced_polynomials.append(g_l)
 
# eliminate z
my_ideal_list = [y * z - N] + reduced_polynomials
 
# Variety
my_ideal_list = [Hi.change_ring(QQ) for Hi in my_ideal_list]
for i in range(len(my_ideal_list),3,-1):
    print(i)
    V = Ideal(my_ideal_list[:i]).variety(ring=ZZ)
    print(V)

参考:

New Attacks on RSA with Small Secret CRT-Exponents

NCTF 2022 - dp_promax

posted @ 2023-01-24 22:51  vconlln  阅读(1148)  评论(0编辑  收藏  举报