Preface
打羊城杯遇到了Extending Wiener’s attack,发现自己的知识面还是太浅了。因此写一篇博客来学习一下。
Wiener’s attack
Wiener’s attack 是根据连分数的性质以及定理,通过对e/N的连续逼近找到对应的k/d,从而分解N。接下来讲一下连分数的定义
Continued Fractions(连分数)
连分数就是一个数的连续分式展开,它的式子长这样:

(其中a_0 是整数,a_1,a_2,…,a_n都是正整数)
通常我们用更简单的数组方式来描述,对任何有理数 p / q p/q p/q来说: p q = [ a 0 ; a 1 , a 2 , . . . , a n ] \frac{p}{q}=[a_0;a_1,a_2,...,a_n] qp=[a0;a1,a2,...,an]
计算连分数我们可以使用欧几里得算法:

Convergent(收敛)
我们定义 c i c_i ci 为连分数每一次分式展开的收敛,即:
∀ i ∈ [ 0 , n ] , c i = [ a 0 ; a 1 , . . . , a i ] \forall i \in [0,n] ,\quad c_i = [a_0;a_1,...,a_i] ∀i∈[0,n],ci=[a0;a1,...,ai]
对于每一个 c i c_i ci的结果 p i q i \frac{p_i}{q_i} qipi来说,都是对 p q \frac{p}{q} qp不断进行逼近收敛的近似值。
Legendre’s theorem
这是Wiener’s attack 的一个比较重要的定理,定义如下:

也就是说,当满足 ∣ a − c d ∣ < 1 2 d 2 | a - \frac{c}{d}|<\frac{1}{2d^{2}} ∣a−dc∣<2d21时, c d \frac{c}{d} dc就是 a a a的连分数收敛。
根据这个定理,我们可以通过计算一个数(e/N)的连分数来找到与这个数近似的两个数的比值(k/d),这就是Wiener’s attack的攻击方法。
Applied to RSA
假设:
e d = 1 + k λ ( N ) ed = 1+k λ(N) ed=1+kλ(N)
λ ( N ) = L C M ( p − 1 , q − 1 ) λ(N)=LCM(p-1,q-1) λ(N)=LCM(p−1,q−1)
g = g c d ( p − 1 , q − 1 ) g=gcd(p-1,q-1) g=gcd(p−1,q−1)
当 d < N 0.25 d<N^{0.25} d<N0.25时,可算得:

因此可以通过 e N \frac{e}{N} Ne的连分数展开得到 k d g \frac{k}{dg} dgk。
那怎么通过 k d g \frac{k}{dg} dgk得到 p p p和 q q q呢?
我们已知: e d g = k ( p − 1 ) ( q − 1 ) + g , k > g edg = k(p-1)(q-1)+g ,\quad k>g edg=k(p−1)(q−1)+g,k>g
所以
⌊ e d g k ⌋ = ( p − 1 ) ( q − 1 ) \lfloor\frac{edg}{k}\rfloor = (p-1)(q-1) ⌊kedg⌋=(p−1)(q−1)
又因为
p q − ( p − 1 ) ( q − 1 ) + 1 2 = p + q 2 \frac{pq-(p-1)(q-1)+1}{2} = \frac{p+q}{2} 2pq−(p−1)(q−1)+1=2p+q
( p + q 2 ) 2 − p q = ( p − q 2 ) 2 (\frac{p+q}{2})^{2} - pq =(\frac{p-q}{2})^{2} (2p+q)2−pq=(2p−q)2
所以我们可以通过判断 ( p − q 2 ) 2 (\frac{p-q}{2})^{2} (2p−q)2是否为平方数来确定我们找的连分数是否正确,然后再算出p和q就行了。
Sagemath实现:
#wiener_attack
def possible(e,alist,N):
for x in alist:
if x==0:
continue
phi = floor(e*(1/x))
if (N-phi+1)%2==0 and sqrt(pow((N-phi+1)//2,2)-N).is_integer():
(p,q)=var('p,q')
x=solve([(p-1)*(q-1)==phi, p*q==N],p,q)
return int(str(x[0][0]).split('==')[1])
else:
continue
def wiener_attack(e,N):
c=continued_fraction(e/N)
alist=c.convergents()
return possible(e,alist,N)
n=
e=
t=wiener_attack(e,n)
print t
RRRRRRSA
其实这里我还想提一下 L e g e n d r e ′ s t h e o r e m Legendre's \ theorem Legendre′s theorem,因为这个定理我们可以当成一个工具,而不是仅仅用在Wiener ’ s attack 。 这个这个定理的关键在于可以将一个模糊近似的数具体地求出来,类似gmpy2.iroot()一样。可以作为一种尝试的工具。(只要你有办法构造出来)
这次2020羊城杯的RRRRRRSA
P1 = getPrime(1038)
P2 = sympy.nextprime(P1)
assert(P2 - P1 < 1000)
Q1 = getPrime(512)
Q2 = sympy.nextprime(Q1
N1 = P1 * P1 * Q1
N2 = P2 * P2 * Q2
已知N1,N2,其他都是未知的。tips里也说了需要用到连分数。那必然是要用到这个定理。
下图是对应的论文。

通过 N 2 N 1 \frac{N_2}{N_1}

本文围绕Wiener攻击及扩展攻击展开,先介绍Wiener攻击,基于连分数性质和定理,通过对e/N连续逼近找k/d分解N。还提及Legendre定理可作为工具。接着阐述扩展攻击,结合Wiener和Guo想法构造格用LLL化简解决问题,最后通过2020羊城杯真题展示应用。
最低0.47元/天 解锁文章
4289





