arrow-left

All pages
gitbookPowered by GitBook
1 of 3

Loading...

Loading...

Loading...

Low Private Component Attacks

Boneh-Durfee Attack

hashtag
What is Boneh-Durfee Attack

Boneh-Durfee attack is an extension of Wiener's attack. That is, it also attacks on low private component dddwith a further relaxed condition. If dddsatisfies:

d<N0.292d < N^{0.292} d<N0.292

Then we can use Boneh-Durfee attack to retrive ddd

this, using a graphical directed point of view, can be seen as:

{E,n}→d<N0.292P{d}\{E, n\} \xrightarrow[d < N^{0.292}]{P} \{d\} {E,n}Pd<N0.292​{d}

Consider for first, see that

As stated above, the RSA's totient function can be espressed as:

continuing with the equation, we see that

and if we decide to consider and , we will have:

At this point, finding is equivalent to find the 2 small solutions and to the congruence

now let and this will preserve the scomposed subtraction

consider (with any ), we deduct that must be really closed to because is in the same order of the length of (so ), we will get

hashtag
Sage Implementation

Wiener's Attack

Wiener's attack is an attack on RSA that uses continued fractions to find the private exponent ddd when it's small (less than 13n4\frac{1}{3}\sqrt[4]{n}31​4n​, where nnn is the modulus). We know that when we pick the public exponent eee to be a small number and calcute its inverse d≡e−1mod  ϕ(n)d \equiv e^{-1} \mod \phi(n)d≡e−1modϕ(n)

hashtag
Wiener's theorem

Wiener's attack is based on the following theorem:

Let , with . Let . Given and with , the attacker can efficiently recover .

hashtag
Some observations on RSA

In order to better understand Wiener's Attack, it may be useful to take note of certain properties of RSA:

We may start by noting that the congruence can be written as the equality for some value , we may additionally note that , since both and are much shorter than , we can say that .

Dividing the former equation by gives us , and using the latter approximation, we can write this as . Notice how the left-hand side of this equation is composed entirely of public information, this will become important later.

It is possible to quickly factor by knowing and . Consider the quadratic polynomial , this polynomial will have the roots and . Expanding it gives us , and substituting for the variables we know we can write this as . Applying the quadratic formula gives us and : , where , , and .

Wiener's attack works by expanding to a continued fraction and iterating through the terms to check various approximations of . In order to make this checking process more efficient, we can make a few observations (this part is optional):

  • Since is even, and and are both by definition coprime to , we know that is odd.

  • Given the above equations and the values of , , , and , we can solve for with the equation , thus we know that has to be divisible by .

hashtag
The Attack

Suppose we have the public key , this attack will determine

  1. Convert the fraction into a continued fraction

  2. Iterate over each convergent in the continued fraction:

  3. Check if the convergent is by doing the following:

Here's a sage implementation to play around with:

//TODO: Proof of Wiener's theorem

hashtag
Automation

The Python module owiener simplifies the scripting process of Wiener's attack:

Here is a Wiener's attack template:

If our ϕ(n)\phi(n)ϕ(n) is correct, the polynomial x2−(n−ϕ(n)+1)x+nx^2 - (n - \phi(n) + 1)x + nx2−(n−ϕ(n)+1)x+n will have roots ppp and qqq, which we can verify by checking if pq=npq = npq=n.

Set the numerator to be kkk and denominator to be ddd

  • Check if ddd is odd, if not, move on to the next convergent

  • Check if ed≡1mod  ked \equiv 1 \mod ked≡1modk, if not, move on to the next convergent

  • Set Ï•(n)=ed−1k\phi(n) = \frac{ed-1}{k}Ï•(n)=ked−1​ and find the roots of the polynomial x2−(n−ϕ(n)+1)x+nx^2 - (n - \phi(n) + 1)x + nx2−(n−ϕ(n)+1)x+n

  • If the roots of the polynomial are integers, then we've found ddd. (If not, move on to the next convergent)

  • If all convergents have been tried, and none of them work, then the given RSA parameters are not vulnerable to Wiener's attack.

  • n=pqn = pqn=pq
    q<p<2qq < p < 2qq<p<2q
    d<13n4d < \frac{1}{3}\sqrt[4]{n}d<31​4n​
    nnn
    eee
    ed≡1mod  ϕ(n)ed \equiv 1 \mod \phi(n)ed≡1modϕ(n)
    ddd
    ed≡1mod  ϕ(n)ed \equiv 1 \mod \phi(n)ed≡1modϕ(n)
    ed=kϕ(n)+1ed = k\phi(n)+1ed=kϕ(n)+1
    kkk
    ϕ(n)=(p−1)(q−1)=pq−p−q+1\phi(n) = (p-1)(q-1) = pq - p - q + 1ϕ(n)=(p−1)(q−1)=pq−p−q+1
    ppp
    qqq
    pq=npq = npq=n
    ϕ(n)≈n\phi(n) \approx nϕ(n)≈n
    dϕ(n)d\phi(n)dϕ(n)
    eϕ(n)=k+1d\frac{e}{\phi(n)} = \frac{k+1}{d}ϕ(n)e​=dk+1​
    en≈kd\frac{e}{n} \approx \frac{k}{d}ne​≈dk​
    nnn
    nnn
    Ï•(n)\phi(n)Ï•(n)
    (x−q)(x−p)(x-q)(x-p)(x−q)(x−p)
    ppp
    qqq
    x2−(p+q)x+pqx^2 - (p + q)x + pqx2−(p+q)x+pq
    x2−(n−ϕ(n)+1)x+nx^2 - (n - \phi(n) + 1)x + nx2−(n−ϕ(n)+1)x+n
    ppp
    qqq
    p∧q=−b±b2−4ac2ap \wedge q = \frac{-b \pm \sqrt{b^2-4ac}}{2a}p∧q=2a−b±b2−4ac​​
    a=1a = 1a=1
    b=n−ϕ(n)+1b = n - \phi(n) + 1b=n−ϕ(n)+1
    c=nc = nc=n
    en\frac{e}{n}ne​
    kd\frac{k}{d}dk​
    Ï•(n)\phi(n)Ï•(n)
    eee
    ddd
    Ï•(n)\phi(n)Ï•(n)
    ddd
    eee
    nnn
    ddd
    kkk
    Ï•(n)\phi(n)Ï•(n)
    ϕ(n)=ed−1k\phi(n) = \frac{ed-1}{k}ϕ(n)=ked−1​
    ed−1ed-1ed−1
    kkk
    (n,e)(n, e)(n,e)
    ddd
    en\frac{e}{n}ne​
    [a0;a1,a2,…,ak−2,ak−1,ak][a_0;a_1,a_2, \ldots , a_{k-2},a_{k-1}, a_k][a0​;a1​,a2​,…,ak−2​,ak−1​,ak​]
    a01,a0+1a1,a0+1a1+1a2, …,a0+1a1+⋱ak−2+1ak−1,\frac{a_{0}}{1},a_{0} + \frac{1}{a_{1}},a_{0} + \frac{1}{a_{1} + \frac{1}{a_{2}}}, \ \ldots, a_{0} + \frac{1}{a_{1} + \frac{\ddots} {a_{k-2} + \frac{1}{a_{k-1}}}},1a0​​,a0​+a1​1​,a0​+a1​+a2​1​1​, …,a0​+a1​+ak−2​+ak−1​1​⋱​1​,
    kd\frac{k}{d}dk​
    d<Nid < N^{i}d<Ni
    1=ed+kϕ(N)21=ed + \frac{k \phi(N)}{2}\\ 1=ed+2kϕ(N)​
    ϕ(N)=(p−1)(q−1)=N−q−p+1 \phi(N) = (p-1)(q-1) = N-q-p+1ϕ(N)=(p−1)(q−1)=N−q−p+1
    1=ed+k(N+12−p+q2)1 = ed + k(\frac{N+1}{2}-\frac{p+q}{2} )1=ed+k(2N+1​−2p+q​)
    x=N+12x = \frac{N+1}{2} x=2N+1​
    y=p+q2y = \frac{p+q}{2} y=2p+q​
    1=ed+k(x+y)1 = ed + k(x+y)1=ed+k(x+y)
    ddd
    xxx
    yyy
    f(x,y)≡k(x+y)≡1 (mod e)k(x+y)≡1( mod e)f(x,y) \equiv k(x+y) \equiv 1 \space (mod \space e) \\ k(x + y) \equiv 1 (\space mod \space e)f(x,y)≡k(x+y)≡1 (mod e)k(x+y)≡1( mod e)
    s=−p+q2s = -\frac{p+q}{2}s=−2p+q​
    A=N+12A = \frac{N+1}{2}A=2N+1​
    Ï•(N)\phi(N) Ï•(N)
    k(A+s)≡1( mod e)k(A+s) \equiv 1 (\space mod \space e)k(A+s)≡1( mod e)
    e=Nαe=N^{\alpha}e=Nα
    α\alphaα
    α\alphaα
    111
    eee
    NNN
    e=N∼1−e=N^{\sim 1^{-}}e=N∼1−
    ∣s∣<2N=p+q2<2N=2e12α∼e∣k∣<2edϕ(N)≤3edN<3e1+α+1α<ei| s | < 2\sqrt{N} = \\ \frac{p+q}{2} < 2\sqrt{N} =2e^{\frac{1}{2\alpha}} \sim \sqrt{e} \\ |k| < \frac{2ed}{\phi{(N)}} \leq\frac{3ed}{N}< 3e^{1+\frac{\alpha+1}{\alpha}} < e^{i}∣s∣<2N​=2p+q​<2N​=2e2α1​∼e​∣k∣<ϕ(N)2ed​≤N3ed​<3e1+αα+1​<ei
    from Crypto.Util.number import long_to_bytes
    
    def wiener(e, n):
        # Convert e/n into a continued fraction
        cf = continued_fraction(e/n)
        convergents = cf.convergents()
        for kd in convergents:
            k = kd.numerator()
            d = kd.denominator()
            # Check if k and d meet the requirements
            if k == 0 or d%2 == 0 or e*d % k != 1:
                continue
            phi = (e*d - 1)/k
            # Create the polynomial
            x = PolynomialRing(RationalField(), 'x').gen()
            f = x^2 - (n-phi+1)*x + n
            roots = f.roots()
            # Check if polynomial as two roots
            if len(roots) != 2:
                continue
            # Check if roots of the polynomial are p and q
            p,q = int(roots[0][0]), int(roots[1][0])
            if p*q == n:
                return d
        return None
    # Test to see if our attack works
    if __name__ == '__main__':
        n = 6727075990400738687345725133831068548505159909089226909308151105405617384093373931141833301653602476784414065504536979164089581789354173719785815972324079
        e = 4805054278857670490961232238450763248932257077920876363791536503861155274352289134505009741863918247921515546177391127175463544741368225721957798416107743
        c = 5928120944877154092488159606792758283490469364444892167942345801713373962617628757053412232636219967675256510422984948872954949616521392542703915478027634
        d = wiener(e,n)
        assert not d is None, "Wiener's attack failed :("
        print(long_to_bytes(int(pow(c,d,n))).decode())
    #!/usr/bin/env python3
    import owiener
    from Crypto.Util.number import long_to_bytes
    
    #--------Data--------#
    
    N = <N>
    e = <e>
    c = <c>
    
    #--------Wiener's attack--------#
    
    d = owiener.attack(e, N)
    
    if d:
        m = pow(c, d, N)
        flag = long_to_bytes(m).decode()
        print(flag)
    else:
        print("Wiener's Attack failed.")
    GitHub - orisano/owiener: A Python3 implementation of the Wiener attack on RSAGitHubchevron-right
    owiener
    Logo
    RSA-and-LLL-attacks/boneh_durfee.sage at master · mimoo/RSA-and-LLL-attacksGitHubchevron-right
    Boneh-Durfee attack Sage implementation
    Logo