Wiener Attack¶
Continued Fraction¶
for example, \(\frac{13}{17}\)’s continued fraction is \([c_0,c_1,c_2,c_3]\), and
\(c_0 = \lfloor \frac{13}{17} \rfloor = 0\)
\(c_1 = 0 + \frac{1}{\lfloor \frac{17}{13} \rfloor} = 0 + \frac{1}{1} = 1\)
\(c_2 = 0 + \frac{1}{1 + \frac{1}{\lfloor \frac{13}{4} \rfloor}} = 0 + \frac{1}{1 + \frac{1}{3}} = \frac{3}{4}\)
\(c_3 = 0 + \frac{1}{1 + \frac{1}{3 + \frac{1}{\lfloor 4 \rfloor}}} = 0 + \frac{1}{1 + \frac{1}{3 + \frac{1}{4}}} = \frac{13}{17}\)
Legendre’s Theorem in Diophantine Approximations¶
for \(\alpha \in \mathbb R\), \(\frac{a}{b} \in \mathbb Q\), and satisfy \(| \alpha - \frac{a}{b}| \lt \frac{1}{2b^2}\), then \(\frac{a}{b}\) will be in \(\alpha\)’s continued fraction
Wiener Attack¶
if \(d \lt \frac{1}{3}n^{\frac{1}{4}}\), \(|p - q| \lt \operatorname{min}(p,q)\), and \(ed = k\varphi(n) + 1\), we can proof that \(\frac{k}{d}\) will be in \(\frac{e}{n}\)’s continued fraction. because \(\operatorname{gcd}(k,d) = 1\), so we can try all \(\frac{e}{n}\)’s continued fraction and because
so
we can test if \(p \in \mathbb N\) and if \(p\) is \(n\)’s factor to check if \(k\) and \(d\) is correct
Proof¶
we know that \(|p-q| \lt \operatorname{min}(p,q)\), we can set \(p \gt q\), then \(2q \gt p \gt q\), set \(p = q + a\) and \(a \lt q\), so
and
so \(3\sqrt{n} \gt (n - \varphi(n))\)
then
we also know \(d \lt \frac{1}{3}n^{\frac{1}{4}}\)
so
and \(d \lt \frac{1}{3}n^{\frac{1}{4}} \quad\Rightarrow\quad 2d \lt 3d \lt n^{\frac{1}{4}} \quad\Rightarrow\quad \frac{1}{2d} \gt \frac{1}{n^{\frac{1}{4}}}\), so
because \(ed - k\varphi(n) = 1\), so \(\operatorname{gcd}(k,d) = 1\), and because Legendre’s Theorem in Diophantine Approximations
so \(\frac{k}{d}\) will be in \(\frac{e}{n}\)’s continued fraction
Code¶
def wiener_attack(n: int, e: int):
"""
- input : `n (int)`, `e (int)`
- output : `(p, q, d) (int, int, int)`
"""
continued_fraction_list = (Integer(e) / Integer(n)).continued_fraction()
for i in range(2, len(continued_fraction_list)):
cf = continued_fraction_list.convergent(i)
k = cf.numerator()
d = cf.denominator()
if ((e * d - 1) % k) != 0:
continue
b = (e * d - 1) // k - n - 1
if (b ** 2 - 4 * n) <= 0:
continue
D = iroot(int(b ** 2 - 4 * n), 2)
if not D[1]:
continue
p, q = ((-int(b) + int(D[0])) // 2), ((-int(b) - int(D[0])) // 2)
if p * q == n:
return p, q, int(d)