UIUCTF 2024 Groups Writeup
I played UIUCTF with b01lers this weekend. I was not planning on playing it initially because I had to finish up some research work and internship stuffs, but someone pinged me in the b01lers Discord server asking if I have any thoughts on this particular challenge, which made me take a look.
As a member of b01lers, I am meant to have some geopolitical rivalries (? lol) with SIGPwny (the team that hosts UIUCTF).1 But near the end, I wished I could spend more time on this competition because I was able to tell just by reading the challenges that they are written very well and with care. So, thank you, SIGPwny, for giving me a productive yet reinvigorating break from my grad school and intern work. It was fun!
As of right now, the CTF website is still alive, and click this for the CTFTime event page.
I discussed this challenge with CygnusX, enigcryptist, and VinhChilling.
Challenge Description
crypto/Groups
Author: NikhillMy friend told me that cryptography is unbreakable if moduli are Carmichael numbers instead of primes. I decided to use this CTF to test out this theory.
ncat --ssl groups.chal.uiuc.tf 1337
We are provided a Python script challenge.py
, which the server runs upon connecting:
Challenge Explained
The server takes a 512-bit (or larger) integer, say $n$, as an input and do the following inspections:
- Check whether $n$ is a prime number or not.
- Randomly picks a non-identity element $a \in \mathbb{Z}_n^\times$ and tests whether $a^{n-1} \equiv 1 \; (\text{mod } n)$ or not; repeats this 50 times.
Once we pass this initial screening, we are asked to solve a discrete log problem. The server chooses a random $a \in \mathbb{Z}_n^\times$ and $2 \leq k \leq n-1$, returns $a$ and $a^k$, and then asks us to figure out $k$ given those two values.
By Fermat's little theorem, if $n$ is prime then $a^{n-1} \equiv 1 \; (\text{mod } n)$ holds for all $a \in \mathbb{Z}_n^\times$. But unfortunately, in this challenge, we are forced to pick a composite $n$. The program tests whether a randomly picked $a \in \mathbb{Z}_n^\times$ satisfies the equation $a^{n-1} \equiv 1 \; (\text{mod } n)$ or not 50 times only. However, since $a$ is picked randomly, it is likely very difficult to create a custom $n$ that passes the test exactly 50 times or higher. That is, giving an $n$ that actually satisfies $a^{n-1} \equiv 1 \; (\text{mod } n)$ at all times is desired (but again, $n$ is not prime).
Towards the Flag
Attempt 1
The converse of Fermat's little theorem is not true in general. There are composite numbers where Fermat's little theorem still holds and they are called, as the challenge description spoiled already, Carmichael numbers.
The Wikipedia page for Carmichael numbers has a very large Carmichael number as an example:
\[ \begin{align*} n & = p (313(p-1)+1) (353(p-1)+1) \text{ where } p = 2967 \dots 2883 \end{align*} \]which is a very large number $n = 2887\dots5867$. Giving this number as input to the server works, but the problem is, we have to solve a discret log problem:
which Sage's discrete_log
function seemingly cannot handle. (For clarity: In above, c
is our input ($n$), and a
and a^k
are the responses from the server.)
Attempt 2
Carmichael numbers must have at least three distinct prime factors. This was proved by Chernick a long time ago. Chernick also proved that, every number of the form $(6k+1)(12k+1)(18k+1)$ is a Carmichael number if $6k+1$, $12k+1$, and $18k+1$ are all primes. Allegedly, this is the most commonly used method today for generating large Carmichael numbers.
I could not find any list of large Carmichael numbers (512-bit or larger) anywhere online including OEIS and research papers. Then, I found this StackExchange post that has the following Carmichael number:
\[ \begin{align*} n & = (6k+1)(12k+1)(18k+1) \text{ where } k = 10^{170} + 8786356 \end{align*} \]which gives $n = 1296\dots5009$. But evidently, Sage still cannot handle this.
Attempt 3 (Flag!)
I think this is a good time to change our plan slightly. Recall that the security of RSA stems from the fact (assumption, more accurately) that the integer factorization problem is computationally difficult. The modulus $n$ in RSA is chosen as a product of two primes $n = pq$. But why? Why not, say, $n = pqr$?
This is because the security parameters, which in this case is the number of bits, are constants. For example, RSA-2048 uses 2048-bit modulus $n$. Roughly speaking, if $n$ is a multiple of three primes, namely $n = pqr$, then $p$, $q$, and $r$ should be around $682$-bit. And if $n = pq$ then $p$ and $q$ are around $1024$-bit. Clearly, when factors are smaller, then it is easier to factor, and hence having more factors can only be detrimental.
Although this challenge isn't exactly about RSA, if the modulus can be factorized into small factors, then the discrete log problem can also be solved easily using the Chinese remainder theorem and whatnot. As far as I know, Sage's discrete_log
function does all that for you automatically.
This gives some motivations that we should look for other methods for finding large Carmichael numbers. I remembered that Erdos has a work on it, which I think is usually referred to as Erdos' method, but I don't think it has any formal name that everyone agrees on. It is explained pretty well in many places online, though I recommend this paper by Guillaume and Morain.
Anyway, the method goes as follows:
- Choose a large natural number $\Lambda$ that is even and (highly preferably) has a large number of factors.
- Find all primes $p$ such that $p - 1 \mid \Lambda$ yet $p \not\mid \Lambda$. Denote the set of all such $p$'s as $P$.
- Find $S \subseteq P$ such that $n := \prod_{p \in S} p \equiv 1 \; (\text{mod } \Lambda)$.
- Return $n$.
The correctness of this algorithm comes directly from the fact that $n$ is a Carmichael number if $\lambda(n) \mid n-1$ where $\lambda(n)$ is the Carmichael function defined to be the LCM of $(p_i - 1)$'s where $p_i$'s are prime factors of $n$.
Now the question is: What $\Lambda$ should we choose for this problem? Every $\Lambda$ in the paper by Guillaume and Morain seems too large for my machine. For example:
But if you think about it: we might not need a large $\Lambda$. We want $n = \prod_{p \in S} p$ to be large enough (512-bit or longer), and that might be achievable even with a not-very-large $\Lambda$.
A few minutes later, I found this paper by Loh and Neibuhr that has lists of $\Lambda$'s that they managed to generate Carmichael numbers from. I just picked one that looks still large enough and ran my code again. Finally, my code managed to return something fast!
It'd be great if we can enumerate over all $S \subseteq P$, but that'd take too long. Let's compute the minimum number of elements we need to multiply to get a 512-bit integer.
This gives us where we can start from. This is also how I chose my Lambda
from the list in that paper: of course, len(P)
should be larger than num_for_512
, yet the difference between the two is small enough so my computer can get it done reasonably fast.
Voila! As intended/hoped, generating this output takes only a few seconds. Now we just need to get it all together, and we are done!
Beautiful.
Flag: uiuctf{c4rm1ch43l_7adb8e2f019bb4e0e8cd54e92bb6e3893}
I'd say this was more a computational number theory problem than a cryptography problem, but still it is crypto-related enough to be called a crypto chall. And regardless, it was fun.
Epilogue
This writeup apparently was selected as one of the best writeups. Thank you again, SIGPwny!
I was reading my solution again, and I think I could've stopped at my second attempt. I mentioned there that my $n = (6k+1)(12k+1)(18k+1)$ was too large for my SageMath to handle. That might be true, but we know the full prime factorization of $n$ already, and we can even compute $\varphi(n)$ ourselves:
\[ \varphi(n) = 6k \cdot 12k \cdot 18k \]So, we could have just called Pohlig-Hellman with $\varphi(n)$ instead. The issue was that, we knew the prime factorization of $n$ already, but my SageMath didn't because I did not tell her, and hence it was too large for her to handle.
As always, attention to detail is key.
1. I hope my advisor doesn’t read this because he went to UIUC, lol. (Though, I don’t think he was involved in any SIGPwny activities.)