BugkuCTF RSA(wiener's attack)

首先这道题切入点很明显,e和n是同数量级的,也就说明d的范围会比较小。我们的攻击目标是就是d

1990年有人证明假如p大于 q而小于2q(这是一个很经常的情况)而 d < 1 3 × N 1 4 d < {\frac {1}{3}} \times N ^{{\frac{1}{4}}} d<31×N41,那么从 N和 e可以很有效地推算出 d。

参考自维基百科Wiener‘s attack

具体怎么做的呢,首先从RSA原理中我们知道了 e d = 1   m o d   ϕ ( N ) ed = 1 \ mod \ {\phi{(N)}} ed=1 mod ϕ(N),即 ϕ ( N ) = e d − 1 k \phi{(N)} = {\frac{ed - 1}{k}} ϕ(N)=ked1因此有
∣ e ϕ ( N ) − k d ∣ = 1 d ϕ ( N ) \left| {\frac{e}{\phi{(N)}} - {\frac{k}{d}}} \right| = {\frac{1}{d\phi{(N)}}} ϕ(N)edk=dϕ(N)1
然后我们可以使用连分数来逼近 k d {\frac{k}{d}} dk
通过连分数枚举k和d我们能计算出来 ϕ ( N ) \phi{(N)} ϕ(N),然后 ϕ ( N ) = ( p − 1 ) ( q − 1 ) = N − p − q + 1 \phi{(N)} = (p - 1)(q - 1)=N-p-q+1 ϕ(N)=(p1)(q1)=Npq+1
之后我们可以通过解方程 x 2 + ( N − ϕ ( N ) + 1 ) x + N = 0 x^2+(N-\phi(N)+1)x+N = 0 x2+(Nϕ(N)+1)x+N=0得到pq。

# -*- coding: utf-8 -*-
from __future__ import print_function
import libnum

def continued_fractions_expansion(numerator,denominator):#(e,N)
	result=[]
 
	divident = numerator % denominator
	quotient = numerator / denominator
	result.append(quotient)
 
	while divident != 0:
		numerator = numerator - quotient * denominator
 
		tmp = denominator
		denominator = numerator
		numerator = tmp
 
		divident = numerator % denominator
		quotient = numerator / denominator
		result.append(quotient)
 
	return result
 
def convergents(expansion):
	convergents=[(expansion[0], 1)]
	for i in range(1, len(expansion)):
		numerator = 1
		denominator = expansion[i]
		for j in range(i - 1, -1, -1):
			numerator += expansion[j] * denominator
			if j==0:
				break
			tmp = denominator
			denominator = numerator
			numerator = tmp
		convergents.append((numerator, denominator)) #(k,d)
	return convergents
 
def newtonSqrt(n):
	approx = n / 2
	better = (approx + n / approx) / 2
	while better != approx:
	    approx = better
	    better = (approx + n / approx) / 2
	return approx
 
def wiener_attack(cons, e, N):
	for cs in cons:
		k,d = cs
		if k == 0:
			continue
		phi_N = (e * d - 1) / k
		#x**2 - ((N - phi_N) + 1) * x + N = 0
		a = 1
		b = -((N - phi_N) + 1)
		c = N
		delta = b * b - 4 * a * c
		if delta <= 0:
			continue
		x1 = (newtonSqrt(delta) - b)/(2 * a)
		x2 = -(newtonSqrt(delta) + b)/(2 * a)
		if x1 * x2 == N:
			return [x1, x2, k, d]

if __name__ == "__main__":
    n = 460657813884289609896372056585544172485318117026246263899744329237492701820627219556007788200590119136173895989001382151536006853823326382892363143604314518686388786002989248800814861248595075326277099645338694977097459168530898776007293695728101976069423971696524237755227187061418202849911479124793990722597
    e = 354611102441307572056572181827925899198345350228753730931089393275463916544456626894245415096107834465778409532373187125318554614722599301791528916212839368121066035541008808261534500586023652767712271625785204280964688004680328300124849680477105302519377370092578107827116821391826210972320377614967547827619
    c = 38230991316229399651823567590692301060044620412191737764632384680546256228451518238842965221394711848337832459443844446889468362154188214840736744657885858943810177675871991111466653158257191139605699916347308294995664530280816850482740530602254559123759121106338359220242637775919026933563326069449424391192
    expansion = continued_fractions_expansion(e, n)
    cons = convergents(expansion)
    p, q, k, d = wiener_attack(cons, e, n)
    m = pow(c, d, n)
    print(libnum.n2s(m))

最后得到flag{Wien3r_4tt@ck_1s_3AsY}

你可能感兴趣的:(CTF)