Home
Writeups Misc About
Let's Decrypt Again

Let's Decrypt Again

The challenge has the most code in it so far, but should not take too long to realize the task we had to do. This follows the same idea as the prequel challenge Let's Decrypt - that is to find an appropriate N, e such that the pow(sig, e, N) is equal to the value of the PKCS1 padded messages.

However, in this challenge, we had a twist - we can only use one non-prime modulus N but has to generate three es such that pow(sig, e_n, N) = m_n with e_n being the public exponent correlated to the nth message m_n.

Also, the messages has to end with a given suffix and passes the regex checks. Combining the checks together, the form of the three messages should be like this

Now we need to find the appropriate N so we can find the discrete logs of the three messages after being padded with PKCS1. This is essentially the Duplicate Signature Key Selection (DSKS) attack on RSA. More information can be found in this paper. Basically, we want to find an N such that the prime factors are smooth primes so that we can solve discrete log in N using Pohlig-Hellman.

Before moving to the solution, let's walk through a bit on my failed attempts.

I initially had the idea of using some special N in the form of pk, where p is a small prime. However, I only tested on primes like 2, 3, 17 and primes that are less than 5 bits, so none of them returned a solution for the discrete log. So I jumped to the conclusion that this idea is not feasible.

Later, when consulting ConnorM from the Cryptohack Discord, he gave me a hint of the idea to generate a smooth prime using the following Python code, then the modulus N is the result of squaring a prime.

n should be bigger than the padded messages, else the check of pow(sig, e, N) == msg will never be satisfied. However, after consulting yassinebelarbi, again from the Cryptohack Discord, this approach is really bad. This is simply because the order of the group, or ϕ(n) is equal to p(p1), hence Pohlig-Hellman will run insanely slow as it will try to run until it reaches p (then later retrieve the solution using CRT).

Hence, yassinebelarbi hinted at the use of a different modulo N = p ^ k again, but this time p is a randomly picked 15-bit prime. This added another layer of randomness to the result of the discrete log, which is beneficial as sometimes discrete logs does not exist for some value of the messages. The challenge creator helps us a bit here - the suffix is there to make the message probabilistic, so we have a higher chance of having a discrete log. This runs significantly faster as p is much smaller, hence the Pohlig-Hellman algorithm should not take that long to output the result.

It sometimes will be the case that the discrete log does not exist, if that's the case then just retry until we obtain the flag.

Some other ideas from ciphr at Cryptohack. We can improve a bit the speed of the discrete log calculation knowing the factorization of N (which we obviously know as we are constructing N).

The above can also be found in the general implementation of Pohlig-Hellman anyways, but I was not aware of this way and probably my Sage instance can run a lot faster knowing this technique.

There is also a implementation in Sage that can help generate the smooth primes that we needed. Check out the awesome Sage script by mimoo.