arrow-left

All pages
gitbookPowered by GitBook
1 of 8

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Recovering the Modulus

When you want to recover N given some (plaintext, ciphertext) pairings

hashtag
Scenario

Consider the case that that you know a set of (plaintext, ciphertext) pairings - this may be that you are provided them, or that you have access to some functionality that returns ciphertexts for provided plaintexts. If you do not know the modulus, but know the exponent used (note: this may be prone to a brute-force regardless), then given these pairings you can recover the modulus used.

hashtag
What we know

Let the following be known:

  • plaintext && ciphertext pairings:

  • public exponent e (e.g. e = 65537 = 0x10001)

hashtag
Process

The idea behind this attack is effectively finding common factors between pairings. Recall that, under general RSA encryption, we have:

and recall what modular arithmetic tells us about the relation between these terms, namely that:

This, rearranged, tells us that

What this means for our known pairings is that, given we know and , we can form the relationship:

Thus we can calculate for the value , though don't know either value individually - we want to somehow derive .

Observe that any two pairings will equate to such a value, both with as a factor. We can take the gcd of these two values, and it is probable that the resulting value will be our value, such that:

However, this is only true for the case that

i.e., both and are coprime. In the case that they are not, i.e. , we have that

In such a case, we don't have sufficient information to completely recover the modulus, and require more plaintext-ciphertext pairs to be successful. In general, the more pairings you have, the more confident you can be the value you calculate is . More specifically:

Thus:

hashtag
Practical Notes

  • In reality, you're likely to only need two or three (plaintext, ciphertext) pairings (in the context of ctf challenges and exercises), and as such computations can be manual if needed, but shouldn't be too complex

  • As it's likely you'll be dealing with large numbers, overflows and precision errors may arise in code - using libraries like gmpy provide support for integers of (theoretically) infinite size, and some nice accompanying features too (like in-built gcd and efficient modular exponentiation)

hashtag
Code Example

These two statements are mathematically equivalent, but one is easier to implement in code:
(Mi,Ci)Β forΒ i∈[1,∞](M_i,C_i) \text{ for } i \in [1,\infty] (Mi​,Ci​)Β forΒ i∈[1,∞]
C=MeΒ (modΒ N)C = M^{e} \text{ } (mod\text{ }N)C=MeΒ (modΒ N)
a≑bΒ (modΒ N)a=b+kNΒ forΒ someΒ k∈Za \equiv b\text{ }(mod\text{ } N)\\ a = b + kN \text{ for some } k \in \mathbb{Z} a≑bΒ (modΒ N)a=b+kNΒ forΒ someΒ k∈Z
aβˆ’b≑0Β (modΒ N)aβˆ’b=kNa - b \equiv 0\text{ } (mod \text{ } N)\\ a - b = kNaβˆ’b≑0Β (modΒ N)aβˆ’b=kN
m,cm, cm,c
eee
Ciβˆ’Mie≑0Β (modΒ N)Ciβˆ’Mie=kiNC_i - M_i^e \equiv 0\text{ } (mod \text{ } N)\\ C_i - M_i^e = k_iNCiβ€‹βˆ’Mie​≑0Β (modΒ N)Ciβ€‹βˆ’Mie​=ki​N
kNkNkN
NNN
NNN
NNN
N=gcd(C1βˆ’M1e,C2βˆ’M2e)N = gcd(C_1 - M_1^e, C_2 - M_2^e)N=gcd(C1β€‹βˆ’M1e​,C2β€‹βˆ’M2e​)
gcd(k1,k2)=1gcd(k_1, k_2) = 1gcd(k1​,k2​)=1
k1k_1k1​
k2k_2k2​
gcd(k1,k2)β‰ 1gcd(k_1, k_2) \ne 1gcd(k1​,k2​)ξ€ =1
aN=gcd(C1βˆ’M1e,C2βˆ’M2e)Β s.t.Β 1β‰ a∈ZaN = gcd(C_1 - M_1^e, C_2 - M_2^e) \text{ s.t. } 1 \ne a \in \mathbb{Z}aN=gcd(C1β€‹βˆ’M1e​,C2β€‹βˆ’M2e​)Β s.t.Β 1ξ€ =a∈Z
NNN
Pr(aβ‰ 1)β†’0Β asΒ kβ†’βˆžPr(a \ne1) \rightarrow 0 \text{ as } k\rightarrow \inftyPr(aξ€ =1)β†’0Β asΒ kβ†’βˆž
N=lim⁑kβ†’βˆžgcd(C1βˆ’M1e,C2βˆ’M2e,...,Ckβˆ’Mke)N = \lim_{k \rightarrow \infty} gcd(C_1 - M_1^e, C_2 - M_2^e, ..., C_k - M_k^e)N=kβ†’βˆžlim​gcd(C1β€‹βˆ’M1e​,C2β€‹βˆ’M2e​,...,Ckβ€‹βˆ’Mke​)
gcd(a,b,c,d,...)=gcd(a,gcd(b,gcd(c,gcd(d,...))))gcd(a, b, c, d, ...) = gcd(a, gcd(b, gcd(c, gcd(d, ...))))gcd(a,b,c,d,...)=gcd(a,gcd(b,gcd(c,gcd(d,...))))
import gmpy2

"""
@param pairings
    list: [(pt1, ct1), (pt2, ct2), ..., (ptk, ctk)]
@param e
    int : encryption exponent
@return
    int : recovered N
"""
def recover_n(pairings, e):
    pt1, ct1 = pairings[0]
    N = ct1 - pow(pt1, e)
    
    # loop through and find common divisors
    for pt,ct in pairings:
        val = gmpy2.mpz(ct - pow(pt, e))
        N = gmpy2.gcd(val, N)
    
    return N
    

Common Modulus Attack

What to do when the same message is encrypted twice with the same modulus but a different public key?

Imagine we have Alice and Bob. Alice sends the SAME message to Bob more than once using the same public key. The internet being the internet, a problem may happen; a bit is flipped, and the public key changed while the modulus stayed the same.

hashtag
What we know

Let be the following:

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 with a further relaxed condition. If satisfies:

Then we can use Boneh-Durfee attack to retrive

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

Proof of correctness

We now consider necessary for the successful description of an RSA ciphertext. The core of this result is due to which states

for all coprime integers and is .

circle-info

As a reminder, we say two integers are coprime if they share no non-trivial factors. This is the same statement that .

RSA application

Tutorial for application with RSA. We are going to use openSSL, openSSH and pycryptodome for key generation, key extraction and some implementation with python

hashtag
Pycryptodome:

Pycryptodome is a python library about cryptography, see the documentation below: There is an example of RSA key generation with pycryptodome:

hashtag

RSA

Will be introduced in this page the fundamentals of RSA, mathematical requirement and also some application with python and openSSL.

circle-exclamation

This page is pretty long, probably could be split up

Edit: I haved deleted the last part, application with RSA, and i made a special part for this. Maybe we can do the same with the second part: Arithmetic for RSA.

m the message in plaintext

  • e1 the public key of the first ciphertext

  • c1 the first ciphertext

  • e2 the public key of the second ciphertext

  • c2 the second ciphertext

  • n the modulus that is common to both ciphertexts

  • All of these but m are essentially given to us.

    hashtag
    Conditions of the attack

    Because we are going to need to calculate inverses for this attack, we must first make sure that these inverses exist in the first place:

    hashtag
    The math behind the attack

    We know that RSA goes as follows:

    From the conditions above we also know that e1e1 e1 and e2e2e2 are co-prime. Thus using Bezout's Theorem we can get:

    Using this, we can derive the original message mm m :

    NB: all the calculations are done mod nn n

    In general, Bezout's Theorem gives a pair of positive and negative numbers. We just need to adapt this equation a little to make it work for us. In this case, let's assume yyy is the negative number:

    Now to truly recover the plaintext, we are actually doing:

    gcd(e1,e2)=1gcd(c2,n)=1gcd(e_1, e_2) = 1 \newline gcd(c_2, n) = 1 gcd(e1​,e2​)=1gcd(c2​,n)=1
    c=meΒ modΒ nc = m^e\ mod\ nc=meΒ modΒ n
    xe1+ye2=gcd(e1,e2)=1xe_1 +ye_2 = gcd(e_1, e_2) = 1xe1​+ye2​=gcd(e1​,e2​)=1
    C1xβˆ—C2y=(me1)xβˆ—(me2)y=me1x+e2y=m1=mC_1^x * C_2^y = (m^{e_1})^x*(m^{e_2})^y \newline = m^{e_1x+e_2y} \newline = m^1 = m C1xβ€‹βˆ—C2y​=(me1​)xβˆ—(me2​)y=me1​x+e2​y=m1=m
    LetΒ y=βˆ’aC2y=C2βˆ’a=(C2βˆ’1)a=(C2βˆ’1)βˆ’yLet\ y = -a \newline C_2^y = C_2^{-a} \newline = (C_2^{-1})^a \newline = (C_2^{-1})^{-y}LetΒ y=βˆ’aC2y​=C2βˆ’a​=(C2βˆ’1​)a=(C2βˆ’1​)βˆ’y
    C1xΓ—(C2βˆ’1)βˆ’yΒ modΒ nC_1^x \times (C_2^{-1})^{-y}\ mod\ n C1x​×(C2βˆ’1​)βˆ’yΒ modΒ n
    From the definition of the protocol, we have that

    for some k∈Zk \in \mathbb{Z}k∈Z. Combining this with Euler's theorem, we see that we recover mmmfrom the ciphertext

    When the requirement gcd⁑(m,n)=1\gcd(m, n) = 1gcd(m,n)=1does not hold, we can instead look at the equivalences modulo pppand qqqrespectively. Clearly, when gcd⁑(m,n)=n,\gcd(m, n) = n,gcd(m,n)=n,we have that c≑m≑0mod  nc \equiv m \equiv 0 \mod nc≑m≑0modnand our correctness still holds. Now, consider the case m=kβ‹…p,m = k\cdot p,m=kβ‹…p,where we have that c≑m≑0mod  pc \equiv m \equiv 0 \mod pc≑m≑0modpand cd≑(me)d(modq).c^d \equiv (m^e)^d \pmod q.cd≑(me)d(modq).Since we have already excluded the case that gcd⁑(m,q)=q,\gcd(m, q) = q,gcd(m,q)=q,we can conclude that gcd⁑(m,q)=1,\gcd(m, q) = 1,gcd(m,q)=1,as qqqis prime. This means that mβ„“Ο•(q)≑1mod  qm^{\ell\phi(q)} \equiv 1 \mod qmβ„“Ο•(q)≑1modqand by the multiplicative properties of the Ο•\phiΟ•function, we determine that mβ„“nΟ•(n)=mβ„“Ο•(q)≑1mod  q.m^{\ell_n\phi(n)} = m^{\ell\phi(q)} \equiv 1 \mod q.mβ„“n​ϕ(n)=mβ„“Ο•(q)≑1modq.We conclude by invoking the Chinese Remainder theorem with

    that meβ‹…d≑mmod  n.m^{e\cdot d} \equiv m \mod n.meβ‹…d≑mmodn.The case for m=kβ‹…qm = k\cdot qm=kβ‹…qfollows in a parallel manner.

    cd=med=mc^d = m^{ed} = mcd=med=m
    aΟ•(n)≑1mod  na^{\phi(n)} \equiv 1 \mod naΟ•(n)≑1modn
    (a,n)(a,n)(a,n)
    Ο•(n)\phi(n)Ο•(n)
    gcd⁑(a,n)=1\gcd(a,n)=1gcd(a,n)=1
    Euler's theoremarrow-up-right
    Euler's totient functionarrow-up-right
    ed≑1mod  ϕ(n),β€…β€Šβ€…β€Šβ‡’β€…β€Šβ€…β€Šed=1+kΟ•(n)ed \equiv 1 \mod \phi(n), \;\; \Rightarrow \;\; ed = 1 + k\phi(n)ed≑1modΟ•(n),β‡’ed=1+kΟ•(n)
    cd≑(me)dmod  n≑medmod  n≑mkΟ•+1mod  n≑mkΟ•mmod  n≑(mΟ•)kmmod  n≑1kmmod  n≑mmod  n\begin{align} c^d &\equiv (m^e)^d &&\mod n \\ &\equiv m^{ed} &&\mod n \\ &\equiv m^{k\phi + 1} &&\mod n \\ &\equiv m^{k\phi} m &&\mod n \\ &\equiv (m^\phi)^km &&\mod n \\ &\equiv 1^km &&\mod n \\ &\equiv m &&\mod n \\ \end{align}cd​≑(me)d≑med≑mkΟ•+1≑mkΟ•m≑(mΟ•)km≑1km≑m​​modnmodnmodnmodnmodnmodnmodn​​
    m≑0mod  pm≑1β„“mmod  q\begin{align*} m &\equiv 0 &&\mod p \\ m &\equiv 1^\ell m &&\mod q\\ \end{align*}mm​≑0≑1β„“m​​modpmodq​
    OpenSSL:

    OpenSSL is a robust, commercial-grade, and full-featured toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols. It is also a general-purpose cryptography library

    hashtag
    OpenSSH:

    https://www.pycryptodome.org/en/latest/arrow-up-right
    from Crypto.Util.number import getPrime, bytes_to_long
    
    
    def generate_keys():
        e = 0x10001    #public exponent e, we generally use this one by default
        while True:
            p = getPrime(512)
            q = getPrime(512)
            phi = (p - 1) * (q - 1)    #Euler's totient 
            d = pow(e, -1, phi)    #Private exponent d
            if d != -1:
                break
    
        n = p * q
        public_key = (n, e)
        private_key = (n, d)
        return public_key, private_key
    
    
    def encrypt(plaintext: int, public_key) -> int:
        n, e = public_key
        return pow(plaintext, e, n)    #plaintext ** e mod n
    
    
    def decrypt(ciphertext: int, private_key) -> int:
        n, d = private_key
        return pow(ciphertext, d, n)   #ciphertext ** d mod n
    
    
    message = bytes_to_long(b"super_secret_message")
    public_key, private_key = generate_keys()
    ciphertext = encrypt(message, public_key)
    plaintext = decrypt(ciphertext, private_key)
    Consider d<Nid < N^{i}d<Nifor 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 x=N+12x = \frac{N+1}{2} x=2N+1​and y=p+q2y = \frac{p+q}{2} y=2p+q​, we will have:

    At this point, finding dddis equivalent to find the 2 small solutions xxxand yyyto the congruence

    now let s=βˆ’p+q2s = -\frac{p+q}{2}s=βˆ’2p+q​and A=N+12A = \frac{N+1}{2}A=2N+1​this will preserve the scomposed Ο•(N)\phi(N) Ο•(N)subtraction

    consider e=NΞ±e=N^{\alpha}e=NΞ±(with any Ξ±\alphaΞ±), we deduct that Ξ±\alphaΞ±must be really closed to 111because eeeis in the same order of the length of NNN(so e=N∼1βˆ’e=N^{\sim 1^{-}}e=N∼1βˆ’), we will get

    hashtag
    Sage Implementation

    ddd
    ddd
    d<N0.292d < N^{0.292} d<N0.292
    ddd
    {E,n}β†’d<N0.292P{d}\{E, n\} \xrightarrow[d < N^{0.292}]{P} \{d\} {E,n}Pd<N0.292​{d}
    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​)
    1=ed+k(x+y)1 = ed + k(x+y)1=ed+k(x+y)
    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)
    k(A+s)≑1(Β modΒ e)k(A+s) \equiv 1 (\space mod \space e)k(A+s)≑1(Β modΒ e)
    ∣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
    hashtag
    I- Introduction:

    RSA is a public-key cryptosystemarrow-up-right that is widely used in the world today to provide a secure transmission system to millions of communications, is one of the oldest such systems in existence. The acronymarrow-up-right RSA comes from the surnames of Ron Rivestarrow-up-right, Adi Shamirarrow-up-right, and Leonard Adlemanarrow-up-right, who publicly described the algorithm in 1977. An equivalent system was developed secretly, in 1973 at GCHQarrow-up-right (the British signals intelligencearrow-up-right agency), by the English mathematician Clifford Cocksarrow-up-right. That system was declassifiedarrow-up-right in 1997.

    All public-key systems are based on the concept of trapdoor functionsarrow-up-right, functions that are simple to compute in one direction but computationally hard to reverse without knowledge of some special information called the trapdoor. In RSA, the trapdoor function is based on the hardness of factoring integersarrow-up-right. The function involves the use of a public keyNN Nto encrypt data, which is (supposed to be) encrypted in such a way that the function cannot be reversed without knowledge of the prime factorisation ofNN N, something that should be kept private. Except in certain cases, there exists no efficient algorithm for factoring huge integers.

    Further reading: Shor's algorithmarrow-up-right

    triangle-exclamation

    Formalize the introduction and include a discussion of the security based on the hardness of factoring integers.

    hashtag
    II- Arithmetic for RSA

    Before starting to introducing you RSA, a few arithmetic notions need to be introduce to understand perfectly other steps.

    hashtag
    III- Key generation

    • We pick two primes ppp and qqq

    • Using ppp and qqq, we calculate modulus n=pΓ—qn = p\times qn=pΓ—q and its Euler's totient Ο•(n)=(pβˆ’1)Γ—(qβˆ’1)\phi(n) = (p-1) \times (q-1)Ο•(n)=(pβˆ’1)Γ—(qβˆ’1)

    • Now, choose the public exponent e\mathbb{e}esuch as

    • By using the Extended Euclidean algorithm, we compute the invert of : which is our private exponent.

    • Public key:

    • Private key:

    • Now, chose a message that you convert into integers

    • We can encrypt this plaintext and receive a ciphertext

    • We can decrypt a ciphertext with

    hashtag
    IV- Signature

    A digital signature is a proof of the authenticity of a message, i.e. a proof that the message has not been tampered with. RSA allows us to sign messages by "encrypting" them using the private key, the result being a signature that anyone can verify by "decrypting" it with the public key and comparing it to the associated message. Any attempt to tamper with the message will result in it no longer matching the signature, and vice-versa. Futhermore, a signature can only be generated using the private key, making it a secure and efficient method of confirming the authenticity of messages.

    Say Alice wants to send a message to Bob, but does not want Mallory, who has established herself as a middleman, to make changes to the message or swap it out entirely. Fortunately, Bob knows Alice's public key, and since eee and ddd are inverses such that ed≑1mod  ϕ(n)ed \equiv 1\mod \phi(n)ed≑1modΟ•(n), Alice can sign her message mmm by "encrypting" it with the private key such that s≑mdmod  ns \equiv m^d \mod ns≑mdmodn, where sss is the signature verifying that the message came from Alice. Alice can now send mmm and sss to Bob, who is now able to check the authenticity of the message by checking if m≑semod  nm \equiv s^e \mod nm≑semodn. If Mallory tries to change mmm, this congruence no longer holds, and since she does not have the private key, she is also unable to provide a maching sssfor her tampered message.

    hashtag
    V- Format

    Wiener's Attack

    Wiener's attack is an attack on RSA that uses continued fractions to find the private exponent when it's small (less than , where is the modulus). We know that when we pick the public exponent to be a small number and calcute its inverse

    hashtag
    Wiener's theorem

    Wiener's attack is based on the following theorem:

    gcd(e,Ο•(n))=1\mathbb{gcd(e, \phi(n)) = 1}gcd(e,Ο•(n))=1
    d\mathbb{d}d
    emod  n\mathbb{e \mod n}emodn
    d≑eβˆ’1mod  ϕ(n)d \equiv e^{-1} \mod \phi(n)d≑eβˆ’1modΟ•(n)
    n,en, en,e
    n,dn, dn,d
    m\mathbb{m}m
    mmm
    c≑memod  nc \equiv m^e \mod nc≑memodn
    ccc
    m≑cdmod  nm \equiv c^d \mod nm≑cdmodn

    Low Private Component Attacks

    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 ed≑1mod  ϕ(n)ed \equiv 1 \mod \phi(n)ed≑1modΟ•(n) can be written as the equality ed=kΟ•(n)+1ed = k\phi(n)+1ed=kΟ•(n)+1 for some value kkk, we may additionally note that Ο•(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, since both ppp and qqq are much shorter than pq=npq = npq=n, we can say that Ο•(n)β‰ˆn\phi(n) \approx nΟ•(n)β‰ˆn.

    Dividing the former equation by dΟ•(n)d\phi(n)dΟ•(n) gives us eΟ•(n)=k+1d\frac{e}{\phi(n)} = \frac{k+1}{d}Ο•(n)e​=dk+1​, and using the latter approximation, we can write this as enβ‰ˆkd\frac{e}{n} \approx \frac{k}{d}neβ€‹β‰ˆdk​. 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 nnn by knowing nnn and Ο•(n)\phi(n)Ο•(n). Consider the quadratic polynomial (xβˆ’q)(xβˆ’p)(x-q)(x-p)(xβˆ’q)(xβˆ’p), this polynomial will have the roots ppp and qqq. Expanding it gives us x2βˆ’(p+q)x+pqx^2 - (p + q)x + pqx2βˆ’(p+q)x+pq, and substituting for the variables we know we can write this as x2βˆ’(nβˆ’Ο•(n)+1)x+nx^2 - (n - \phi(n) + 1)x + nx2βˆ’(nβˆ’Ο•(n)+1)x+n. Applying the quadratic formula gives us ppp and qqq: p∧q=βˆ’bΒ±b2βˆ’4ac2ap \wedge q = \frac{-b \pm \sqrt{b^2-4ac}}{2a}p∧q=2aβˆ’bΒ±b2βˆ’4ac​​, where a=1a = 1a=1, b=nβˆ’Ο•(n)+1b = n - \phi(n) + 1b=nβˆ’Ο•(n)+1, and c=nc = nc=n.

    Wiener's attack works by expanding en\frac{e}{n}ne​ to a continued fraction and iterating through the terms to check various approximations of kd\frac{k}{d}dk​. In order to make this checking process more efficient, we can make a few observations (this part is optional):

    • Since Ο•(n)\phi(n)Ο•(n) is even, and eee and ddd are both by definition coprime to Ο•(n)\phi(n)Ο•(n), we know that ddd is odd.

    • Given the above equations and the values of eee, nnn, ddd, and kkk, we can solve for Ο•(n)\phi(n)Ο•(n) with the equation Ο•(n)=edβˆ’1k\phi(n) = \frac{ed-1}{k}Ο•(n)=kedβˆ’1​, thus we know that edβˆ’1ed-1edβˆ’1 has to be divisible by kkk.

    • If our is correct, the polynomial will have roots and , which we can verify by checking if .

    hashtag
    The Attack

    Suppose we have the public key (n,e)(n, e)(n,e), this attack will determine ddd

    1. Convert the fraction en\frac{e}{n}ne​ into a continued fraction [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​]

    2. Iterate over each convergent in the continued fraction: 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​,

    3. Check if the convergent is kd\frac{k}{d}dk​ by doing the following:

      • Set the numerator to be and denominator to be

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

      • Check if , if not, move on to the next convergent

      • Set and find the roots of the polynomial

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

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

    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:

    ddd
    13n4\frac{1}{3}\sqrt[4]{n}31​4n​
    nnn
    eee
    d≑eβˆ’1mod  ϕ(n)d \equiv e^{-1} \mod \phi(n)d≑eβˆ’1modΟ•(n)
    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
    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.")
    Ο•(n)\phi(n)Ο•(n)
    x2βˆ’(nβˆ’Ο•(n)+1)x+nx^2 - (n - \phi(n) + 1)x + nx2βˆ’(nβˆ’Ο•(n)+1)x+n
    ppp
    qqq
    pq=npq = npq=n
    kkk
    ddd
    ddd
    ed≑1mod  ked \equiv 1 \mod ked≑1modk
    Ο•(n)=edβˆ’1k\phi(n) = \frac{ed-1}{k}Ο•(n)=kedβˆ’1​
    x2βˆ’(nβˆ’Ο•(n)+1)x+nx^2 - (n - \phi(n) + 1)x + nx2βˆ’(nβˆ’Ο•(n)+1)x+n
    ddd
    RSA-and-LLL-attacks/boneh_durfee.sage at master Β· mimoo/RSA-and-LLL-attacksGitHubchevron-right
    Boneh-Durfee attack Sage implementation
    Logo
    GitHub - orisano/owiener: A Python3 implementation of the Wiener attack on RSAGitHubchevron-right
    owiener
    Logo