Solution de iv3l pour La PIN

intro crypto symétrique

20 février 2025

Le fichier lapin.py chiffre le flag avec AES-GCM, en utilisant une clé dérivée du code PIN (un entier à 4 chiffres) avec la fonction scrypt. Pour retrouver le flag, il faut :

  1. Deviner le PIN (il y a au maximum 9999 possibilités).
  2. Reconstituer la clé à partir du PIN avec scrypt().
  3. Déchiffrer le flag avec AES-GCM.

Nous pouvons bruteforcer le PIN en testant toutes les valeurs possibles (0001 à 9999) et voir laquelle permet de déchiffrer correctement le message. Voici un script Python qui le fait :

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

# Données fournies
enc_hex = "f049de59cbdc9189170787b20b24f7426ccb9515e8b0250f3fc0f0c14ed7bb1d4b42c09d02fe01e0973a7233d99af55ce696f599050142759adc26796d64e0d6035f2fc39d2edb8a0797a9e45ae4cd55074cf99158d3a64dc70a7e836e3b30382df30de49ba60a"
enc = bytes.fromhex(enc_hex)

# Séparation des éléments (nonce, ciphertext, tag)
nonce, ciphertext_tag = enc[:16], enc[16:]
ciphertext, tag = ciphertext_tag[:-16], ciphertext_tag[-16:]

salt = b"FCSC"

# Brute-force des PINs possibles
for pin in range(1, 10000):
    pin_bytes = long_to_bytes(pin)
    key = scrypt(pin_bytes, salt, 32, N=2**10, r=8, p=1)

    try:
        aes = AES.new(key, AES.MODE_GCM, nonce=nonce)
        flag = aes.decrypt_and_verify(ciphertext, tag)
        print(f"PIN trouvé : {pin}")
        print(f"Flag : {flag.decode()}")
        break
    except Exception:
        continue

Explication du script :

Ce script récupérera le flag en quelques secondes, car il ne teste que 9999 valeurs au maximum.