- Python 100%
| images | ||
| aes_cbc.py | ||
| aes_ecb.py | ||
| pinguin.py | ||
| README.md | ||
TD2 — AES en pratique
Exercices sur papier
Exercice 1 — Conversions
Sous-partie A — Décimal → Hexadécimal :
| Décimal | Hex |
|---|---|
| 65 | 41 |
| 200 | C8 |
| 255 | FF |
| 16 | 10 |
Hexadécimal → Décimal :
| Hex | Décimal |
|---|---|
| 4A | 74 |
| FF | 255 |
| 1F | 31 |
| B0 | 176 |
Sous-partie B — Encodage ASCII en hexadécimal :
- AES →
41 45 53 - Crypto →
43 72 79 70 74 6F - Hello! →
48 65 6C 6C 6F 21
Sous-partie C — XOR sur octets :
-
FF ⊕ 0F=F0(1111 1111 ⊕ 0000 1111 = 1111 0000) -
A5 ⊕ A5=00(XOR d'un octet avec lui-même = toujours 0) -
41 ⊕ 20=61'A' (0100 0001) ⊕ espace (0010 0000) = 0110 0001 = 'a' Le XOR entre une majuscule et l'espace donne la minuscule correspondante. -
42 ⊕ 0F=4D(0100 0010 ⊕ 0000 1111 = 0100 1101)
Exercice 2 — Round AES
Question 1 — Matrice d'état initiale (BONJOUR LES AMIS, column-major) :
ASCII : B=42, O=4F, N=4E, J=4A, O=4F, U=55, R=52, (espace)=20, L=4C, E=45, S=53, (espace)=20, A=41, M=4D, I=49, S=53
col 0 col 1 col 2 col 3
42 4F 4C 41
4F 55 45 4D
4E 52 53 49
4A 20 20 53
Question 2 — Après AddRoundKey (XOR avec 0F partout) :
4D 40 43 4E
40 5A 4A 42
41 5D 5C 46
45 2F 2F 5C
Question 3 — Après SubBytes :
On applique la S-Box AES sur chaque octet (extrait fourni pour les lignes 2, 4, 5) :
- 4D → ligne 4, col D → E3
- 40 → ligne 4, col 0 → 09
- 43 → ligne 4, col 3 → 1A
- 4E → ligne 4, col E → 2F
- 40 → 09
- 5A → ligne 5, col A → BE
- 4A → ligne 4, col A → D6
- 42 → ligne 4, col 2 → 2C
- 41 → ligne 4, col 1 → 83
- 5D → ligne 5, col D → 4C
- 5C → ligne 5, col C → 4A
- 46 → ligne 4, col 6 → 5A
- 45 → ligne 4, col 5 → 6E
- 2F → ligne 2, col F → 15
- 2F → 15
- 5C → 4A
E3 09 1A 2F
09 BE D6 2C
83 4C 4A 5A
6E 15 15 4A
Question 4 — Après ShiftRows :
- Ligne 0 : pas de décalage →
E3 09 1A 2F - Ligne 1 : décalage 1 gauche →
BE D6 2C 09 - Ligne 2 : décalage 2 gauche →
4A 5A 83 4C - Ligne 3 : décalage 3 gauche →
4A 6E 15 15
E3 09 1A 2F
BE D6 2C 09
4A 5A 83 4C
4A 6E 15 15
Question 5 — MixColumns :
MixColumns multiplie chaque colonne par une matrice fixe dans GF(2⁸). Son rôle est la diffusion : chaque octet de sortie dépend des 4 octets de la colonne d'entrée. Ainsi, une modification d'un seul octet d'entrée modifie les 4 octets de la colonne après MixColumns.
Question 6 — Pourquoi 10 rounds ?
- Après 1 round (ShiftRows + MixColumns) : modifier 1 bit affecte environ 1 octet en sortie du SubBytes, puis 4 octets après MixColumns.
- Après 2 rounds : ces 4 octets modifiés se propagent à 4 colonnes → environ 16 octets affectés (tout le bloc).
- Après 10 rounds : chaque bit de la sortie dépend de chaque bit de l'entrée (effet avalanche complet). Modifier 1 bit d'entrée change statistiquement la moitié des bits de sortie. 10 rounds garantissent cette diffusion totale avec une marge de sécurité.
Exercice 3 — Padding PKCS7
Question 1 — Tableau des paddings :
| Taille message | Octets ajoutés | Valeur des octets |
|---|---|---|
| 13 | 3 | 03 |
| 5 | 11 | 0B |
| 1 | 15 | 0F |
| 16 | 16 | 10 |
| 31 | 1 | 01 |
Question 2 — Retirer le padding :
a) 48 65 6C 6C 6F 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B
→ Dernier octet = 0B = 11 → on retire 11 octets de padding
→ Message original : 48 65 6C 6C 6F = Hello
b) 54 65 73 74 21 21 21 21 21 21 21 21 04 04 04 04
→ Dernier octet = 04 → on retire 4 octets de padding
→ Message original : 54 65 73 74 21 21 21 21 21 21 21 21 = Test!!!!!!!!
Question 3 — Pourquoi toujours padder, même un multiple de 16 ?
Si on ne paddait pas les messages dont la taille est déjà multiple de 16, l'algorithme de retrait du padding ne pourrait pas distinguer un message sans padding d'un message dont les derniers octets ressemblent à du padding. En ajoutant toujours un bloc complet de 16 octets (valeur 0x10), on garantit que le dernier octet est toujours un octet de padding, rendant le retrait non ambigu.
Exercice 4 — ECB et salaire de Jane
Candidat n° 1
Justification : En ECB, deux blocs clairs identiques donnent deux blocs chiffrés identiques. Le salaire de Jack (105 000 EUR/an) a pour blocs chiffrés : Q9 2D | FP VX | C9 IO. On cherche un salaire supérieur qui partage certains blocs avec Jack. Le candidat 1 contient FP VX C9 en commun avec Jack — les blocs correspondant aux centaines de milliers et à la structure du montant sont les mêmes, mais avec un préfixe différent (TO AV 6R) indiquant un montant plus élevé. Jane est la patronne donc gagne plus.
Pourquoi ECB est déplorable pour les images :
Une image contient de vastes zones de couleur uniforme (ciel, mur, fond uni). Ces zones produisent des blocs de 16 octets identiques. En ECB, ces blocs identiques donnent des blocs chiffrés identiques → les contours et les formes de l'image originale restent visibles sur l'image chiffrée. C'est l'effet pingouin.
Exercice 5 — CBC à la main
Rappel : Ici AES est simplifié : chiffrer(K, X) = K ⊕ X (XOR avec la clé).
Données : K = 5A, IV = 3C, blocs clairs : A1 B2 C3 D4
Question 2 — Chiffrement :
- C1 = chiffrer(K, P1 ⊕ IV) = 5A ⊕ (A1 ⊕ 3C) = 5A ⊕ 9D = C7
- C2 = chiffrer(K, P2 ⊕ C1) = 5A ⊕ (B2 ⊕ C7) = 5A ⊕ 75 = 2F
- C3 = chiffrer(K, P3 ⊕ C2) = 5A ⊕ (C3 ⊕ 2F) = 5A ⊕ EC = B6
- C4 = chiffrer(K, P4 ⊕ C3) = 5A ⊕ (D4 ⊕ B6) = 5A ⊕ 62 = 38
Résultat : C7 2F B6 38
Question 3 — Déchiffrement de C7 2F B6 38 :
Déchiffrer(K, C) = K ⊕ C (même opération), puis XOR avec le bloc précédent (ou IV).
- P1 = dechiffrer(K, C1) ⊕ IV = (5A ⊕ C7) ⊕ 3C = 9D ⊕ 3C = A1 ✓
- P2 = dechiffrer(K, C2) ⊕ C1 = (5A ⊕ 2F) ⊕ C7 = 75 ⊕ C7 = B2 ✓
- P3 = dechiffrer(K, C3) ⊕ C2 = (5A ⊕ B6) ⊕ 2F = EC ⊕ 2F = C3 ✓
- P4 = dechiffrer(K, C4) ⊕ C3 = (5A ⊕ 38) ⊕ B6 = 62 ⊕ B6 = D4 ✓
Question 4 — Réflexion :
a) Non — même message + même clé + IV différent → blocs chiffrés différents. Le premier bloc clair est XORé avec un IV différent avant chiffrement, ce qui produit un résultat différent pour tous les blocs suivants.
b) Si le même IV est réutilisé avec deux messages qui partagent le même premier bloc, les premiers blocs chiffrés seront identiques. Un attaquant peut en déduire que les deux messages commencent pareil — fuite d'information.
c) CBC corrige ECB car chaque bloc clair est XORé avec le bloc chiffré précédent avant d'être chiffré. Deux blocs clairs identiques produiront des blocs chiffrés différents car ils ont des "précédents" différents. Les schémas répétitifs du clair n'apparaissent plus dans le chiffré.
Exercice 6 — Attaque XOR
Question 1 — Retrouver la clé :
C = M ⊕ K → K = M ⊕ C
- H = 48, C_1 = 68 → K = 48 ⊕ 68 = 20
- E = 45, C_2 = 65 → K = 45 ⊕ 65 = 20 ✓
- L = 4C, C_3 = 6C → K = 20 ✓
Clé : K = 20 (le caractère espace)
Question 2 — Déchiffrement de C' = 77 6F 72 6C 64 :
- 77 ⊕ 20 = 57 = 'W'
- 6F ⊕ 20 = 4F = 'O'
- 72 ⊕ 20 = 52 = 'R'
- 6C ⊕ 20 = 4C = 'L'
- 64 ⊕ 20 = 44 = 'D'
Message déchiffré : WORLD
Question 3 — Attaque à clair partiellement connu :
Message chiffré : 03 2D 2D 2B 2D 36 33 62 02 2D 2B 20 24
Clair connu : B=42, o=6F, n=6E, j=6A, o=6F, u=75, r=72
a) Les 7 premiers octets de la clé :
- K[0] = 03 ⊕ 42 = 41 = 'A'
- K[1] = 2D ⊕ 6F = 42 = 'B'
- K[2] = 2D ⊕ 6E = 43 = 'C'
- K[3] = 2B ⊕ 6A = 41 = 'A'
- K[4] = 2D ⊕ 6F = 42 = 'B'
- K[5] = 36 ⊕ 75 = 43 = 'C'
- K[6] = 33 ⊕ 72 = 41 = 'A'
Clé partielle : ABCABCA
b) On observe le motif répétitif ABC (période 3). La longueur probable de la clé est 3.
c) Déchiffrement complet avec la clé ABC (41 42 43) répétée :
- 03 ⊕ 41 = 42 = 'B'
- 2D ⊕ 42 = 6F = 'o'
- 2D ⊕ 43 = 6E = 'n'
- 2B ⊕ 41 = 6A = 'j'
- 2D ⊕ 42 = 6F = 'o'
- 36 ⊕ 43 = 75 = 'u'
- 33 ⊕ 41 = 72 = 'r'
- 62 ⊕ 42 = 20 = ' '
- 02 ⊕ 43 = 41 = 'A'
- 2D ⊕ 41 = 6C = 'l'
- 2B ⊕ 42 = 69 = 'i'
- 20 ⊕ 43 = 63 = 'c'
- 24 ⊕ 41 = 65 = 'e'
Message déchiffré : Bonjour Alice
Question 4 — Discussion :
a) Le XOR avec une clé courte répétée est vulnérable car il introduit de la périodicité. Un attaquant peut estimer la longueur de la clé (test de Kasiski, indice de coïncidence), puis traiter chaque position comme un chiffrement de César indépendant et appliquer l'analyse fréquentielle.
b) Le One-Time Pad (clé aussi longue que le message, utilisée une seule fois) est théoriquement incassable (sécurité parfaite prouvée par Shannon). Problèmes pratiques : il faut distribuer une clé aussi longue que le message de manière sécurisée (problème de distribution de clé), et ne jamais réutiliser la clé (sinon C1 ⊕ C2 = M1 ⊕ M2, ce qui permet de retrouver les messages).
Exercices Python
Partie 7 — ECB et blocs identiques
Les deux blocs chiffrés sont identiques (résultat confirmé par le test : Identiques ? True).
Cela implique qu'en ECB, tout attaquant qui observe le chiffré peut détecter des répétitions dans le message clair sans connaître la clé. Si un message contient deux blocs identiques (ex : même montant dans une base de données, même en-tête dans un protocole), cela est visible directement dans le chiffré — fuite d'information structurelle majeure.
Partie 8 — Effet pingouin
-
tux.bmp (original) : Le pingouin Tux est clairement visible, avec ses couleurs noires, blanches et oranges distinctes.
-
tux_ecb.bmp : La silhouette et les formes du pingouin restent reconnaissables. Les zones de couleur uniforme (ventre blanc, corps noir) produisent des blocs identiques qui donnent des blocs chiffrés identiques → les contours du pingouin apparaissent en négatif dans le bruit.
-
tux_cbc.bmp : L'image ressemble à du bruit aléatoire uniforme. Aucune forme n'est reconnaissable. Le pingouin a totalement disparu.
Pourquoi ECB révèle des informations : Chaque bloc de 16 pixels est chiffré indépendamment. Deux zones identiques donnent deux blocs chiffrés identiques. Les patterns visuels (grandes zones unies) survivent au chiffrement sous forme de répétitions.
Pourquoi CBC ne le fait pas : Chaque bloc est XORé avec le bloc chiffré précédent avant d'être chiffré. Même si deux blocs de pixels sont identiques, leur contexte (bloc précédent) est différent → blocs chiffrés différents → image de sortie indiscernable du bruit.
Partie 9 — CBC et blocs identiques
Les deux blocs chiffrés sont différents (résultat confirmé : Identiques ? False).
Comparaison avec ECB : En ECB, deux blocs clairs identiques donnent obligatoirement deux blocs chiffrés identiques. En CBC, le premier bloc est XORé avec l'IV et le second avec le premier bloc chiffré — contextes différents → chiffrés différents. CBC élimine donc la fuite d'information structurelle d'ECB et est bien plus sûr pour des messages avec redondance.
Difficultés rencontrées
- La manipulation des headers BMP (54 octets à conserver intact) est délicate : si on chiffre le header, l'image n'est plus lisible par les visionneuses.
- Le padding PKCS7 doit être appliqué avant le chiffrement et retiré après le déchiffrement — oublier cette étape génère des erreurs ou des données corrompues.
- En CBC, l'IV doit être transmis avec le message chiffré pour pouvoir déchiffrer. Il n'est pas secret mais doit être aléatoire et unique pour chaque chiffrement.