← Projets

stockholm

janvier 2026

GoCryptographieChacha20-Poly1305Argon2idDocker42
github

Réalisé dans le cadre de la Piscine Cybersecurity de 42. Une belle introduction au monde de la cryptographie, que j’espère continuer à explorer.

Aperçu

Implémente les mécanismes essentiels d’un ransomware dans un environnement Docker contrôlé — ciblage sélectif de fichiers par extension (inspiré de la liste de cibles de WannaCry), chiffrement authentifié et réversibilité complète avec la même clé.

La stack cryptographique est un choix délibéré. Ayant déjà travaillé avec des schémas plus classiques lors d’un exercice précédent de cette piscine (ft_otp, un générateur de mots de passe à usage unique (OTP)), je voulais explorer des constructions AEAD (authenticated encryption with associated data, chiffrement authentifié avec données associées), modernes et une dérivation de clé “memory-hard”. Chaque fichier est chiffré avec Chacha20-Poly1305, avec une clé dérivée du mot de passe utilisateur via Argon2id. Le format sur disque: MAGIC | Salt | Nounce | ciphertext | est autonome — toutes les données nécessaires au déchiffrement sont intégrées dans le fichier lui-même. Les octets magiques (STOCK1) servent de données additionnelles AEAD, authentifiant l’en-tête et rendant toute altération ou incompatibilité de format détectable au moment du déchiffrement.

Go a été préféré à Rust et au C++ pour ce projet — et pour la majeure partie de la piscine cybersécurité — principalement pour ses bibliothèques standards de cryptographie et HTTP bien fournies et bien documentées.

Fonctionnement

Dérivation de clé avec Argon2id

Stockholm utilise Argon2id, qui combine les propriétés de ses deux variantes: Argon2i, qui accède à la mémoire selon un schéma indépendant des données (résistant aux attaques par canal auxiliaire), et Argon2d, qui utilise un schéma dépendant de données (résistant aux attaques par GPU) → Argon2id fait les deux: accès indépendant des données pendant la première moitié du calcul, puis dépendant pendant la seconde.

Les paramètres retenus sont 64 Mo de mémoire, 3 itérations et 1 thread. Ils déterminent le coût de la dérivation pour un attaquant cherchant à retrouver le mot de passe par force brute (plus de mémoire et d’itérations = plus de temps et de matériel requis par tentative). Le sel (16 octets aléatoires générés pour chaque fichier) garantit que deux fichiers chiffrés avec le même mot de passe produisent des clés différentes, empêchant les attaques par précalcul.

Chiffrement authentifié avec ChaCha20-Poly1305

ChaCha20-Poly1305 est un chiffrement AEAD. Il offres deux garantis simultanées: la confidentialité (personne ne peut lire le texte en clair sans la clé) et l’authenticité (personne ne peut altérer le texte chiffré sans que cela soit détecté).

ChaCha20 est un chiffrement par flot. À partir d’une clé de 32 octets et d’un nonce de 12 octets, il génère un flux pseudo-aléatoire de longueur arbitraire. Chiffrer revient à appliquer un XOR entre le texte en clair et ce flux — trivialement réversible avec la même clé et le même nonce. Le nonce ne doit jamais être réutilisé avec la même clé, c’est pourquoi Stockholm génère un nonce aléatoire différent pour chaque fichier.

Poly1305 est un code d’authentification de message à usage unique. Il prend en entrée le texte chiffré et les données additionnelles (les octets magiques STOCK1) et calcule une balise d’authentification de 16 octets, à partir d’une clé dérivée du même flux ChaCha20. Au déchiffrement, la balise est recalculée puis comparée — si quoi que ce soit a été modifié (le texte chiffré, l’en-tête), le déchiffrement échoue. C’est ce qui donne aux octets magiques une utilité au delà du simple identifiant de format: ils sont cryptographiquement liés au texte chiffré, si bien qu’un fichier qui n’a pas été chiffré par Stockholm ne peut pas passer l’authentification.

Format sur disque

[ MAGIC (6B) | Salt (16B) | Nonce (12B) Ciphertext + Tag (N+16B) ]

Le sel alimente Argon2id pour redériver la clé. Le nonce alimente ChaCha20-Poly1305 pour déchiffrer et authentifier.