TD2 — Chiffrement symetrique : AES et modes d'operation¶
Duree : 2h | Par groupe
Prerequis : CM2 — Cryptographie symetrique
Rendu : depot Forgejo
Dependance : pip install cryptography
Objectifs¶
- Manipuler les representations decimal / hexadecimal / ASCII utilisees par AES
- Sentir le fonctionnement interne d'un round AES (sans entrer dans la theorie des corps de Galois)
- Maitriser le padding PKCS7
- Comprendre pourquoi ECB est dangereux et comment CBC corrige le probleme
- Implementer AES-ECB et AES-CBC en Python
Plan¶
- Exercices sur papier (1h) — six exercices pour batir l'intuition
- Exercices de programmation (1h) — implementation et effet pingouin
Exercices sur papier¶
A la main
Ces exercices se font sans ordinateur. Utiliser la table ASCII en annexe.
Exercice 1 — Conversions decimal / hexadecimal¶
L'AES manipule des octets. Chaque octet (8 bits) s'ecrit avec 2 chiffres hexadecimaux (de 00 a FF).
Sous-partie A — Conversions
Convertir en hexadecimal :
| Decimal | Hex |
|---|---|
| 65 | ? |
| 200 | ? |
| 255 | ? |
| 16 | ? |
Convertir en decimal :
| Hex | Decimal |
|---|---|
4A |
? |
FF |
? |
1F |
? |
B0 |
? |
Sous-partie B — Encodage ASCII
A l'aide de la table ASCII (annexe), encoder en hexadecimal les mots suivants (un octet par caractere) :
AESCryptoHello!
Sous-partie C — XOR sur octets
Le XOR (⊕) est l'operation fondamentale d'AES. Sur deux bits : 0⊕0 = 0, 0⊕1 = 1, 1⊕0 = 1, 1⊕1 = 0.
Sur deux octets, on XOR bit a bit. Exemple : 4A ⊕ 35 :
Calculer :
FF ⊕ 0F= ?A5 ⊕ A5= ?41 ⊕ 20= ? (que vaut'A'XOR espace en ASCII ? Que represente le resultat ?)42 ⊕ 0F= ?
Exercice 2 — Sentir AES : un round complet a la main¶
AES traite des blocs de 16 octets organises en une matrice 4x4 (column-major). Un round applique 4 operations dans l'ordre :
AddRoundKey → SubBytes → ShiftRows → MixColumns
(Le tout premier round commence par AddRoundKey ; le dernier round saute MixColumns.)
On va executer un round sur le texte BONJOUR LES AMIS (16 caracteres) avec une sous-cle simple.
Question 1 — Construire la matrice d'etat
Encoder les 16 caracteres en hexadecimal (table ASCII), puis remplir la matrice 4x4 colonne par colonne :
| col 0 | col 1 | col 2 | col 3 |
|---|---|---|---|
| ? | ? | ? | ? |
| ? | ? | ? | ? |
| ? | ? | ? | ? |
| ? | ? | ? | ? |
Question 2 — AddRoundKey
Sous-cle (matrice 4x4 de 0F partout) :
0F |
0F |
0F |
0F |
|---|---|---|---|
0F |
0F |
0F |
0F |
0F |
0F |
0F |
0F |
0F |
0F |
0F |
0F |
XOR position par position avec la matrice d'etat. Ecrire la matrice resultante.
Question 3 — SubBytes
On remplace chaque octet par sa valeur dans la S-Box d'AES (table de substitution non-lineaire fixe). Pour un octet XY (en hex), la valeur de remplacement se trouve a la ligne X, colonne Y de la S-Box.
Extrait de la S-Box AES (lignes 2, 4, 5 — suffisantes pour cet exercice) :
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2 |
B7 | FD | 93 | 26 | 36 | 3F | F7 | CC | 34 | A5 | E5 | F1 | 71 | D8 | 31 | 15 |
4 |
09 | 83 | 2C | 1A | 1B | 6E | 5A | A0 | 52 | 3B | D6 | B3 | 29 | E3 | 2F | 84 |
5 |
53 | D1 | 00 | ED | 20 | FC | B1 | 5B | 6A | CB | BE | 39 | 4A | 4C | 58 | CF |
Exemple : 4D → ligne 4, colonne D → E3.
Appliquer SubBytes a chaque octet de la matrice obtenue en Q2.
Question 4 — ShiftRows
Decaler chaque ligne vers la gauche (rotation circulaire) :
- Ligne 0 : pas de decalage
- Ligne 1 : decalage de 1
- Ligne 2 : decalage de 2
- Ligne 3 : decalage de 3
Ecrire la matrice resultante.
Question 5 — MixColumns (a comprendre, pas a calculer)
MixColumns multiplie chaque colonne par une matrice fixe dans le corps de Galois GF(2^8). Ce calcul depasse le cadre du TD : on en garde l'intuition et le role.
Role : MixColumns diffuse chaque octet sur toute la colonne. Apres MixColumns, chaque octet de sortie depend des 4 octets de la colonne d'entree.
Question 6 — Reflexion : pourquoi 10 rounds ?
Apres un seul round, si on change un bit du message d'entree, combien d'octets de la sortie sont affectes ? Apres 2 rounds ? Apres 10 rounds ?
Exercice 3 — Padding PKCS7¶
AES chiffre par blocs de 16 octets. Si le message n'est pas un multiple de 16, on complete avec PKCS7 : on ajoute n octets, chacun de valeur n.
Si le message fait deja un multiple de 16, on ajoute un bloc complet de 16 octets de valeur 0x10 (= 16).
Question 1 — Calculer le padding
Pour chaque taille de message, indiquer la valeur des octets de padding et le nombre d'octets ajoutes :
| Taille message (octets) | Octets ajoutes | Valeur des octets |
|---|---|---|
| 13 | ? | ? |
| 5 | ? | ? |
| 1 | ? | ? |
| 16 | ? | ? |
| 31 | ? | ? |
Question 2 — Retirer le padding
Apres dechiffrement, on obtient les octets suivants (en hex). Donner le message original (sans padding) :
a) 48 65 6C 6C 6F 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B
b) 54 65 73 74 21 21 21 21 21 21 21 21 04 04 04 04
Question 3 — Pourquoi toujours padder, meme un message multiple de 16 ?
Exercice 4 — Le mode ECB est dangereux¶
Le mode ECB (Electronic Code Book) chiffre chaque bloc independamment avec la meme cle.
Bloc 1 ──[AES_K]──> Bloc chiffre 1
Bloc 2 ──[AES_K]──> Bloc chiffre 2
Bloc 3 ──[AES_K]──> Bloc chiffre 3
Question 1 — Si deux blocs du message clair sont identiques, que peut-on dire des blocs chiffres correspondants ?
Question 2 — Le salaire de Jane
Dans une entreprise, les salaires sont stockes dans une base de donnees, chiffres avec AES en mode ECB. Pour la demonstration, la fonction de chiffrement utilise des blocs de 2 caracteres (au lieu de 16).
Vous savez que Jack gagne 105 000 EUR/an. Son entree chiffree dans la base est :
Vous trouvez l'entree chiffree de Jane, la patronne de Jack. Elle figure parmi les 5 candidats suivants :
| Candidat | Cipher |
|---|---|
| 1 | TO AV 6R FP Y5 VX C9 |
| 2 | YP FG FP DF DF IO |
| 3 | Q9 AX FP C9 IO IO |
| 4 | AC ED 4T FP VX IO IO |
| 5 | UT JS DG FP RT AV IO |
Sachant que Jane est la patronne (donc gagne plus que Jack) et que la structure du salaire suit le meme format pour tous les employes, lequel de ces candidats est le salaire de Jane ? Justifier en utilisant la propriete d'ECB.
Question 3 — Pourquoi ECB est-il deplorable pour les images ?
Imaginez une photo encodee en pixels : de nombreuses zones de couleur uniforme (ciel bleu, mur blanc, peau...) produisent des blocs de pixels identiques. Que va-t-il rester visible sur l'image chiffree en ECB ?
Exercice 5 — Le mode CBC corrige ECB¶
Le mode CBC (Cipher Block Chaining) XOR chaque bloc clair avec le bloc chiffre precedent avant de chiffrer. Le premier bloc utilise un vecteur d'initialisation (IV) aleatoire.
Bloc 1 ⊕ IV ──[AES_K]──> Bloc chiffre 1
Bloc 2 ⊕ C1 ──[AES_K]──> Bloc chiffre 2
Bloc 3 ⊕ C2 ──[AES_K]──> Bloc chiffre 3
Question 1 — Schema
Dessiner le schema de chiffrement CBC pour 3 blocs (sur papier ou tableau).
Question 2 — Chiffrement CBC a la main
Pour rendre l'exercice tractable, on remplace AES par un chiffrement simplifie :
avec des blocs de 8 bits (1 octet).
Donnees :
- Cle : $K = $
5A - IV :
3C - Message clair : 4 blocs =
A1 B2 C3 D4
Calculer les 4 blocs chiffres \(C_1, C_2, C_3, C_4\). Detailler chaque etape XOR.
Question 3 — Dechiffrement CBC
Avec la meme cle $K = $ 5A et le meme IV = 3C, dechiffrer le message :
C7 2F B6 38
(Indication : la fonction de dechiffrement est \(D_K(C) = C \oplus K\) ; puis appliquer l'inverse de CBC.)
Question 4 — Reflexion
a) Si on chiffre deux fois le meme message avec la meme cle mais des IV differents, les chiffres sont-ils identiques ? b) Que se passe-t-il si on reutilise le meme IV avec la meme cle pour deux messages differents qui partagent le meme premier bloc ? c) Pourquoi CBC corrige-t-il le probleme d'ECB observe a l'exercice 4 ?
Exercice 6 — Attaque par clair connu sur XOR¶
Un systeme naif chiffre les messages par simple XOR avec une cle repetee : $\(C_i = M_i \oplus K_{i \bmod |K|}\)$
Question 1 — Retrouver la cle a partir d'un clair connu
On vous donne un message clair \(M\) et son chiffre \(C\) :
- \(M\) =
HELLO→ en hex :48 45 4C 4C 4F - \(C\) =
68 65 6C 6C 6F
Trouver la cle \(K\) (1 octet).
Question 2 — Dechiffrer un nouveau message
Avec la meme cle $K = $ 20, dechiffrer le message intercepte $C' = $ world (en hex : 77 6F 72 6C 64).
Question 3 — Attaque a clair partiellement connu
On intercepte le message chiffre suivant (en hex), produit avec une cle multi-octets repetee :
Vous savez que le message clair commence par Bonjour (7 caracteres).
a) Calculer les 7 premiers octets de la cle. b) Quelle est la longueur probable de la cle ? (Indice : observer la periodicite dans les octets retrouves.) c) Dechiffrer le message complet.
Question 4 — Discussion
a) Pourquoi le chiffrement XOR avec cle courte est-il vulnerable ? b) Et si la cle est aussi longue que le message et utilisee une seule fois ? (= One-Time Pad, OTP). Quel(s) probleme(s) cela pose-t-il en pratique ?
Exercices de programmation (Python)¶
Programmation
Les exercices suivants se font en Python avec la bibliotheque cryptography (pip install cryptography).
Structure du projet¶
Telecharger le scaffolding (td2-template.zip)
td2/
├── README.md
├── aes_ecb.py # chiffrer_ecb / dechiffrer_ecb
├── aes_cbc.py # chiffrer_cbc / dechiffrer_cbc
├── pinguin.py # chiffrer_image_ecb / chiffrer_image_cbc
└── images/
└── tux.bmp # fourni
Partie 7 — AES-ECB : chiffrement texte¶
Fichier : aes_ecb.py
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
import os
def chiffrer_ecb(message: bytes, cle: bytes) -> bytes:
"""
Chiffre un message en AES-ECB.
- Applique le padding PKCS7 avant de chiffrer.
- cle doit faire 16, 24 ou 32 bytes (128, 192 ou 256 bits).
"""
pass
def dechiffrer_ecb(chiffre: bytes, cle: bytes) -> bytes:
"""
Dechiffre un message chiffre en AES-ECB.
- Retire le padding PKCS7 apres dechiffrement.
"""
pass
Test revelateur :
cle = os.urandom(32)
# Deux blocs identiques dans le message
message = b"AAAAAAAAAAAAAAAA" + b"AAAAAAAAAAAAAAAA"
chiffre = chiffrer_ecb(message, cle)
print(f"Bloc 1 : {chiffre[:16].hex()}")
print(f"Bloc 2 : {chiffre[16:32].hex()}")
print(f"Identiques ? {chiffre[:16] == chiffre[16:32]}")
README
Les deux blocs chiffres sont-ils identiques ? Qu'est-ce que cela implique pour la securite ?
Partie 8 — L'effet pingouin¶
Fichier : pinguin.py
def chiffrer_image_ecb(chemin_entree: str, chemin_sortie: str, cle: bytes) -> None:
"""
Chiffre les pixels d'une image BMP en AES-ECB.
- Conserver le header BMP (54 premiers bytes) tel quel.
- Chiffrer uniquement les donnees pixel (apres le header).
- Appliquer un padding si necessaire.
- Ecrire header original + pixels chiffres dans chemin_sortie.
"""
pass
def chiffrer_image_cbc(chemin_entree: str, chemin_sortie: str, cle: bytes, iv: bytes) -> None:
"""
Chiffre les pixels d'une image BMP en AES-CBC.
Meme principe que ECB, mais avec CBC.
"""
pass
Instructions :
- Generer une cle aleatoire :
cle = os.urandom(32) - Generer un IV aleatoire :
iv = os.urandom(16) - Chiffrer
tux.bmpen ECB →tux_ecb.bmp - Chiffrer
tux.bmpen CBC →tux_cbc.bmp - Ouvrir les trois images cote a cote et comparer
README
Decrire ce qu'on voit sur chaque image. Expliquer pourquoi ECB revele des informations et pourquoi CBC ne le fait pas.
Partie 9 — AES-CBC : chiffrement texte¶
Fichier : aes_cbc.py
def chiffrer_cbc(message: bytes, cle: bytes, iv: bytes) -> bytes:
"""
Chiffre un message en AES-CBC.
- Applique le padding PKCS7.
- iv doit faire 16 bytes.
"""
pass
def dechiffrer_cbc(chiffre: bytes, cle: bytes, iv: bytes) -> bytes:
"""
Dechiffre un message chiffre en AES-CBC.
- Retire le padding PKCS7.
"""
pass
Test :
cle = os.urandom(32)
iv = os.urandom(16)
message = b"AAAAAAAAAAAAAAAA" + b"AAAAAAAAAAAAAAAA"
chiffre = chiffrer_cbc(message, cle, iv)
print(f"Bloc 1 : {chiffre[:16].hex()}")
print(f"Bloc 2 : {chiffre[16:32].hex()}")
print(f"Identiques ? {chiffre[:16] == chiffre[16:32]}")
README
Comparer avec le resultat ECB. Pourquoi CBC est-il plus sur pour ce cas ?
Annexe — Table ASCII (caracteres imprimables)¶
Symboles et chiffres
| Char | Dec | Hex | Char | Dec | Hex | Char | Dec | Hex |
|---|---|---|---|---|---|---|---|---|
| (espace) | 32 | 20 |
0 |
48 | 30 |
@ |
64 | 40 |
! |
33 | 21 |
1 |
49 | 31 |
[ |
91 | 5B |
" |
34 | 22 |
2 |
50 | 32 |
\ |
92 | 5C |
# |
35 | 23 |
3 |
51 | 33 |
] |
93 | 5D |
$ |
36 | 24 |
4 |
52 | 34 |
^ |
94 | 5E |
% |
37 | 25 |
5 |
53 | 35 |
_ |
95 | 5F |
& |
38 | 26 |
6 |
54 | 36 |
` |
96 | 60 |
' |
39 | 27 |
7 |
55 | 37 |
{ |
123 | 7B |
( |
40 | 28 |
8 |
56 | 38 |
\| |
124 | 7C |
) |
41 | 29 |
9 |
57 | 39 |
} |
125 | 7D |
* |
42 | 2A |
: |
58 | 3A |
~ |
126 | 7E |
+ |
43 | 2B |
; |
59 | 3B |
|||
, |
44 | 2C |
< |
60 | 3C |
|||
- |
45 | 2D |
= |
61 | 3D |
|||
. |
46 | 2E |
> |
62 | 3E |
|||
/ |
47 | 2F |
? |
63 | 3F |
Lettres majuscules
| Char | Dec | Hex | Char | Dec | Hex | Char | Dec | Hex | Char | Dec | Hex |
|---|---|---|---|---|---|---|---|---|---|---|---|
A |
65 | 41 |
H |
72 | 48 |
O |
79 | 4F |
V |
86 | 56 |
B |
66 | 42 |
I |
73 | 49 |
P |
80 | 50 |
W |
87 | 57 |
C |
67 | 43 |
J |
74 | 4A |
Q |
81 | 51 |
X |
88 | 58 |
D |
68 | 44 |
K |
75 | 4B |
R |
82 | 52 |
Y |
89 | 59 |
E |
69 | 45 |
L |
76 | 4C |
S |
83 | 53 |
Z |
90 | 5A |
F |
70 | 46 |
M |
77 | 4D |
T |
84 | 54 |
|||
G |
71 | 47 |
N |
78 | 4E |
U |
85 | 55 |
Lettres minuscules
| Char | Dec | Hex | Char | Dec | Hex | Char | Dec | Hex | Char | Dec | Hex |
|---|---|---|---|---|---|---|---|---|---|---|---|
a |
97 | 61 |
h |
104 | 68 |
o |
111 | 6F |
v |
118 | 76 |
b |
98 | 62 |
i |
105 | 69 |
p |
112 | 70 |
w |
119 | 77 |
c |
99 | 63 |
j |
106 | 6A |
q |
113 | 71 |
x |
120 | 78 |
d |
100 | 64 |
k |
107 | 6B |
r |
114 | 72 |
y |
121 | 79 |
e |
101 | 65 |
l |
108 | 6C |
s |
115 | 73 |
z |
122 | 7A |
f |
102 | 66 |
m |
109 | 6D |
t |
116 | 74 |
|||
g |
103 | 67 |
n |
110 | 6E |
u |
117 | 75 |
README a rendre¶
# TD2 — AES en pratique
## Exercices sur papier
### Exercice 1 — Conversions
- Reponses sous-partie A (decimal → hex et hex → decimal) : \_\_\_
- Reponses sous-partie B (encodage ASCII de AES, Crypto, Hello!) : \_\_\_
- Reponses sous-partie C (XOR octets) : \_\_\_
### Exercice 2 — Round AES
- Matrice d'etat initiale : \_\_\_
- Apres AddRoundKey : \_\_\_
- Apres SubBytes : \_\_\_
- Apres ShiftRows : \_\_\_
- Reflexion sur les 10 rounds : \_\_\_
### Exercice 3 — Padding PKCS7
- Tableau des paddings : \_\_\_
- Messages originaux Q2 a) et b) : \_\_\_
- Pourquoi padder un message multiple de 16 ? : \_\_\_
### Exercice 4 — ECB et salaire de Jane
- Salaire de Jane = candidat n°\_\_\_
- Justification (proprietes ECB) : \_\_\_
- Pourquoi ECB est deplorable pour les images : \_\_\_
### Exercice 5 — CBC a la main
- Chiffrement (C1 C2 C3 C4) : \_\_\_
- Dechiffrement : \_\_\_
- Reflexion IV : \_\_\_
### Exercice 6 — Attaque XOR
- Cle Q1 : \_\_\_
- Dechiffrement Q2 : \_\_\_
- Cle Q3 et message dechiffre : \_\_\_
- Discussion XOR vs OTP : \_\_\_
## Exercices Python
### Partie 7 — ECB et blocs identiques
- Les deux blocs chiffres sont-ils identiques ? \_\_\_
- Qu'est-ce que cela implique pour la securite ? (2-3 phrases)
### Partie 8 — Effet pingouin
- Decrire ce qu'on voit sur tux_ecb.bmp :
- Decrire ce qu'on voit sur tux_cbc.bmp :
- Expliquer pourquoi ECB revele des informations :
- Expliquer pourquoi CBC ne le fait pas :
### Partie 9 — CBC et blocs identiques
- Les deux blocs chiffres sont-ils identiques en CBC ? \_\_\_
- Comparaison avec ECB :
## Difficultes rencontrees
(libre)