# FCSC 2021 - Intro - La PIN

May 03, 2021
Also available in:  🇫🇷

## Challenge

I protected the flag by encrypting it with modern algorithms. Can you find it?

Files :

## Solving the challenge

First, read the python script rabbit.py which was used to encrypt the flag. In this script we notice a code block allowing to enter a pin code between 0 and 9999:

``````while True:
pin = int(input(">>> PIN code (4 digits): "))
if 0 < pin < 9999:
break
``````

The second part manages the flag encryption. The encryption key `k` is generated using a key generation function scrypt depending only of the PIN entered above.

``````flag = open("flag.txt", "rb").read()
k = scrypt(long_to_bytes(pin), b"FCSC", 32, N = 2 ** 10, r = 8, p = 1)
``````

Then the flag is encrypted with the key `k` on AES in GCM mode and the encrypted message is saved in hexadecimal format.

``````aes = AES.new(k, AES.MODE_GCM)
c, tag = aes.encrypt_and_digest(flag)

enc = aes.nonce + c + tag
print(enc.hex())
``````

Now that we have an idea of ​​how the flag is encrypted, we can think about an attack. The first idea that comes up is to brute force the PIN. Indeed as this one consists of only 4 digits, the bruteforce will be very fast.

Before doing bruteforce, we need to read the encrypted flag and extract the 16 byte `nonce` at the beginning and the 16 byte`tag` at the end. Then we make a loop from 0 to 9999 to generate all the keys possible with the function scrypt and we let's try to decrypt and verify the encrypted message. Here is all of that combined in a python script:

``````#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import binascii
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import scrypt
from Crypto.Util.number import long_to_bytes

nonce, encrypted, tag = data[:16], data[16:-16], data[-16:]

print(' Nonce : %s' % nonce)
print(' tag   : %s' % tag)

for pin in range(0,9999):
print('\r[>] Trying PIN %04d' % pin,end="")
key = scrypt(long_to_bytes(pin), b"FCSC", 32, N = 2 ** 10, r = 8, p = 1)
try:
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
print(cipher.decrypt_and_verify(encrypted, tag))
except Exception as e:
pass
``````

All that's left to do is run the script, and 2 minutes later:

``````\$ ./bf.py
Nonce : b'\xf0I\xdeY\xcb\xdc\x91\x89\x17\x07\x87\xb2\x0b\$\xf7B'
tag   : b'M\xc7\n~\x83n;08-\xf3\r\xe4\x9b\xa6\n'
[>] Trying PIN 6273
b'FCSC{c1feab88e6c6932c57fbaf0c1ff6c32e51f07ae87197fcd08956be4408b2c802}\n'
[>] Trying PIN 9998
``````

And we get the flag:

``````FCSC{c1feab88e6c6932c57fbaf0c1ff6c32e51f07ae87197fcd08956be4408b2c802}
``````