Public Exponent

Salty

We are given this code that implements RSA with e = 1.

#!/usr/bin/env python3

from Crypto.Util.number import getPrime, inverse, bytes_to_long, long_to_bytes

e = 1
d = -1

while d == -1:
    p = getPrime(512)
    q = getPrime(512)
    phi = (p - 1) * (q - 1)
    d = inverse(e, phi)

n = p * q

flag = b"XXXXXXXXXXXXXXXXXXXXXXX"
pt = bytes_to_long(flag)
ct = pow(pt, e, n)

print(f"n = {n}")
print(f"e = {e}")
print(f"ct = {ct}")

pt = pow(ct, d, n)
decrypted = long_to_bytes(pt)
assert decrypted == flag

Since in RSA, ct = m^e mod n. So, e = 1 would make it ct = m mod n. The value of m would most likely be less than n, which results in ct = m.

Here's the solver code.

Flag: crypto{saltstack_fell_for_this!}

Modulus Inutilis

The challenge name literally translates to "useless modulus", which hints about the vulnerability. We are given this source code.

Here, e = 3 is used. The value for n is very big and the value for m is low (since the message is very short). It is very likely that m^3 is less than n, resulting in ct = m^3, rendering the modulus useless.

Below is the PoC for this challenge.

Flag: crypto{N33d_m04R_p4dd1ng}

Everything is Big

References

In this challenge, we are given this source code.

The main thing to note here is that e is as big as n, while d is notably small. In the condition where d is small enough, Wiener's attack might be possible.

Wiener's attack works by approximating e/n to k/d using continued fractions. Basically, a continued fractions takes a fraction and find the "simplest" form. Adding more terms mean converging into the most correct value. We are hoping that at least one of the convergents of e/n equals to k/d. In fact, when d is small enough, a convergent which equals to k/d is guaranteed.

I tried implementing the solution using Sage's continued_fraction() function, but it didn't work for large numbers. So, I used a code from mananpal1997arrow-up-right which turned out to be working well.

Here's the mathematical derivation.

Now, if d is small enough, 1/(d*phi) wouldn't be too small, and we can hope for k/d to coincide with one of the convergents.

For this challenge's solution, I attached two files: continued_fractions.py and solve.py.

continued_fractions.py

solve.py

Output of solve.py

Flag: crypto{s0m3th1ng5_c4n_b3_t00_b1g}

Crossed Wires

We are given this source code.

Here, we are given both n and d, but the d will be useless in directly decrypting the ciphertext, since the plaintext was encrypted using a different e. However, there is a way that we can efficiently factor n given d. This articlearrow-up-right explains such algorithm.

Here is the solver code for the challenge.

Flag: crypto{3ncrypt_y0ur_s3cr3t_w1th_y0ur_fr1end5_publ1c_k3y}

Everything is Still Big

This is a continuation of the Wiener's attack (Everything is Big) challenge. This time, the size of d is raised just so that it's slightly above Wiener's boundary.

Boneh-Durfee showed that Wiener's boundary might've been too tight and that an extended attack can efficiently factor N as long as d < N^(0.292).

In this challenge, even with the modification, N can still be factored using Wiener's attack. However, in the spirit of the challenge, I tried searching for the most convenient implementation of Boneh-Durfee attack to use, and came across this repoarrow-up-right.

Here is the solution for the challenge.

Flag: crypto{bon3h5_4tt4ck_i5_sr0ng3r_th4n_w13n3r5}

Endless Emails

We are given this source code.

According to the description, some of the messages are exactly the same. Meaning, there is one value of m that's encrypted using different public moduli. For this scenario, we can implement Hastad's broadcast attack using Chinese Remainder Theorem (CRT).

The tricky part is that among the ciphertexts, only some of them have the same m. Therefore, we need to try every single combination and hope that at least a group of them have the same m.

Here's the solution code.

Flag: crypto{1f_y0u_d0nt_p4d_y0u_4r3_Vuln3rabl3}

Last updated