Home
Writeups Misc About
Broken RSA

Broken RSA

We need to recover the plaintext from the incorrectly generated RSA parameters, in this case, e = 16 and the modulo n is a prime. As the public exponent and the totient of n is not coprime, this implies

The first, and intended solution is to take advantage of the fact that e = 2 ^ 4, hence we only need to calculate the square root of the plaintext in the finite field four times.

Kudos to Robin_Jadoul on Cryptohack for this solution.

Another solution takes advantage of the fact that the modulo is a prime. With m being the plaintext message, we can see it is a root of the polynomial X^e - ct over Z/nZ[X]. As n is prime, calculating the square root multiple times when the modulus is a prime is quick. nth_root is insanely slow in comparison, as the underlying method is not optimised for non coprime power.

Kudos to AZ on Cryptohack for this solution.

Lastly, the God solution. Don't know how it works, root of unity is that strong I guess. I think I will leave this to the future me to figure out! This works for composite n, as seen in this writeup.

This runs very quick. The following is the way that the algorithm works.

As we cannot find a unique m, we can instead find x satisfying

(mx)ecmodn
xe1modn

x in this case is called a root of unity modulo n which can be computed fairly easily. The algorithm for calculating this is in the roots_of_unity method in the Python script.

Denote g=gcd(e,ϕ(n)), hence we have e=kg and ϕ(n)=lg for some integers k and l. phi_coprime is l (as we are dividing ϕ(n) by gcd(e,ϕ(n))). The returned solution is within some number of rounds, as there can be collisions of the solutions, in mathematical terms, there exists some a,b where ab such that:

al=blmodn

Indeed, if the elements a are of order divides phi_coprime, or l, then al=1 (Lagrange's theorem).

The set of the solutions indeed satisfy the assert line because

roote=(il)e=ile=ilkg=ikϕ(n)=(iϕ(n))k=1k=1modn

d = inverse_mod(e, phi_coprime), or ed=1+zl for some z.

Denote the original plaintext as m and the corresponding ciphertext ct as c, and the possible plaintext obtained from pt = pow(ct, d, n) as M.

M=cd=(me)d=med=m1+zlmodn

For the assert line, we have:

Me=(m1+zl)e=me+zle=memzle=memzϕ(n)k=me=cmodn

Hence M is one of the possible plaintext. Combining this with the root of unity, we should have a set of possible plaintexts. Finding one with indications of the flag should give us the solution.