Welcome back to the 3rd Part of this ongoing Cryptography series. As mentioned earlier, this series is about solving cryptography challenges and providing write-ups and explanations as we counter new concepts and techniques.
For curious minds, links are attached for further reading and deep scouting into the concepts.
Part 3 will cover further six challenges from PicoCTF, from where we left last time.
6. Mini RSA
As the name reveals, this is an RSA challenge. The description of the challenge further gave us a hint of the solution. The message(m) is padded and raised to the power of the public exponent(e). The produced number is just barely larger than modulo N.
The challenge contains a ciphertext file attached:
Modulo operation is applied on the raised number with N, producing ciphertext(c). As mentioned above, the number isn’t that large, so we can brute-force the number of cycles(k) and get the original padded message(m).
mᵉ > n m = ᵉ√(k*n + ct)
It is called Direct Root Attack. I have covered detailed explanations and resources of this attack in my last post.
Let’s carve a simple python script to obtain the flag:
Executing the script generates the flag and k value.
As you can see, decoded m contains padded spaces before the flag.
7. Dachshund Attacks
The description reads that the value of d is small and provides a remote netcat server to connect.
Connecting with it stages out e, n and c values, which indicates it is an RSA challenge. The unusual part is the value of e(public exponent) which is very large.
There is a relation between the values of e and d. As the value of e increases, d decreases. (Inversely proportional)
d = e^(−1) modϕ(n)
In an ideal RSA encryption, the private exponent d must be large enough. If not, and with few other factors, the encryption can break using Wiener’s attack
It’s a cryptographic attack against RSA. The attack uses the continued fraction method to expose the private key d when d is small.
I won’t go into deeper details about how the attack works but will provide resources to study it.
There is a python3 implementation of wieners attack on github. Download the script, and import the functionality into your custom script to calculate d.
Make sure the downloaded script is in the same folder as your script.
A custom script may look something like this:
Executimg the script returns the flag.
8. No Padding, No Problem
The challenge provides a remote netcat server to connect.
Here is the output:
The output produced again indicates that it is an RSA challenge. The catch here is that the server will decrypt any other ciphertext but the ciphertext of the flag produced.
The above output confirms it.
To solve this, we somehow have to do some computations on the encrypted cyphertext and after decrypting the result via the remote server, figure out the way to retrieve the original m.
This computation can be done using Homomorphic encryption. Homomorphic encryption is a form of encryption that permits users to perform computations on its encrypted data without first decrypting it. These resulting computations are left in an encrypted form which, when decrypted, results in an identical output to that produced had the operations been performed on the unencrypted data.
Read further here.
This homomorphic property can be used on RSA, where we can multiply the encrypted cypher with another encrypted cypher. It looks something like this:
encrypt(m1) * encrypt(m2) = ((m1**e)*(m2**e)) mod n = (m1*m2)**e mod n = encrypt(m1*m2)
Now we can choose a value like 2 and encrypt it using
2**e mod n. Multiply the result with ct. The returned value can be decrypted by the server. Then dividing the decrypted value with 2 will give us our m1(flag in long).
Let’s first generate our cyphertext from 2.
Lets multiply the cyphertext with the original ct of the flag.
Slap this calculated ct3 into the server to get the decrypted m1m2.
m1m2 = 580550060391700078946913236734911770139931497702556153513487440893406629034802718534645538074938502890769281669222390720762
Lets now divide the m2 which is 2 with the above value to get m1.
Now lets just convert this value into bytes.
The challenge provides an encrypted flag(UFJKXQZQUNB), a key(SOLVECRYPTO) and a file named table. Viewing the table contents and the key hints that it is a Vigenère cypher.
Vigenère is again a substitution cypher where each letter of the plain string shifts +n times. The plain string and the key are mapped together as the key repeats itself until it matches the length of the plain string. n is the position of the key’s letter in ALPHABET, which shifts its adjacent letter in plain text.
You can read further about it here.
To decrypt the encrypted flag, shift the string with -n, where n is described above.
We can create a simple python script to automate our task.
It is a simple rot13 challenge. It is a substitution cipher. Read more about it in my first post.
Cyberchef to the rescue!
11 — caesar
As the name of the challenge indicates that it is an easy Caeser cypher challenge. It is a simple and easy-to-use encryption technique. It is a kind of substitution cypher, where every letter of the plain string is replaced by a letter of some fixed number of positions down the alphabet.
Read further about it here.
The challenge provides a ciphertext file which contains the encrypted flag.
There are about 26 possible shifts in caesar cypher. No hints given so we can brute force the flag with every possible shift, and try to recognize the flag.
A script can be written to automate the task:
Running the script outputs all possible shifts on the flag.
The last shift makes sense and is our flag.