TD1 — Cryptographie classique : Cesar & analyse frequentielle¶
Duree : 2h
Prerequis : CM1 — Histoire & fondamentaux Rendu : depot Forgejo
Objectifs¶
- Maitriser les chiffrements classiques (Cesar, substitution, Vigenere, affine, Hill, ADFGVX)
- Implementer chiffrement/dechiffrement de Cesar
- Attaque par force brute
- Analyse frequentielle
Fichiers du projet¶
Telecharger le scaffolding (td1-template.zip)
td1/
├── README.md # template a remplir
├── cesar.py # chiffrer / dechiffrer
├── force_brute.py # attaque_force_brute
├── freq.py # calculer_frequences / deviner_cle
├── messages/
│ ├── message_fr.txt # message francais chiffre (cle inconnue)
│ └── message_en.txt # message anglais chiffre (cle inconnue)
└── vigenere.py # chiffrer_vigenere / casser_vigenere
Exercices sur papier¶
A la main
Les exercices de cette section sont a realiser sur papier, sans ordinateur.
Exercice 1 — Chiffrement par decalage (Cesar)¶
-
Chiffrer le message « la rencontre est prevue a la cafeteria » a l'aide du chiffrement par decalage et de la cle K = 5.
-
Decrypter le message « RGNEIDVGPEWXTRAPHHXFJT » sachant qu'il a ete cree par un chiffrement par decalage.
-
Dans un texte en francais les lettres les plus frequentes sont le A (8.4%) et le E (17.26%). Sachant que le message est en francais, chiffre en utilisant le chiffrement par decalage sur les 26 lettres de l'alphabet, determiner la clef et decrypter le debut du message :
Exercice 2 — Chiffrement par substitution¶
- Chiffrer le message « la rencontre est prevue a la cafeteria » a l'aide du chiffrement par substitution et de la cle suivante :
| a | b | c | d | e | f | g | h | i | j | k | l | m |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| X | N | Y | A | H | P | O | G | Z | Q | W | B | T |
| n | o | p | q | r | s | t | u | v | w | x | y | z |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| S | F | L | R | C | V | M | U | E | K | J | D | I |
- Est-il possible de decrypter le message « YHVMQUVMH » chiffre par un chiffrement par substitution sans connaitre la cle ? Dechiffrer ce message sachant qu'il a ete cree avec la cle precedente.
Exercice 3 — Chiffrement de Vigenere¶
Ici la lettre « A » correspond a un decalage de 0.
-
Chiffrer le message « la rencontre est prevue a la cafeteria » a l'aide de la methode de Vigenere et du mot cle POULE.
-
Est-il possible de decrypter le message « BAUNBEKLZLQSKQKEBGCJYHVSKR » chiffre par un chiffrement de Vigenere sans connaitre la cle ? Dechiffrer ce message sachant qu'il a ete cree a l'aide du mot cle TNCY.
Exercice 4 — Chiffrement affine¶
Pour coder un message, on peut proceder de la facon suivante : chaque lettre du message munie de son numero d'ordre n est remplacee par la lettre de l'alphabet munie du numero d'ordre x (x ∈ [0 … 25]) obtenu a l'aide de la formule x ≡ 3n + 7 [26].
| A | B | C | D | E | F | G | H | I | J | K | L | M |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
- Verifier qu'avec ce chiffrement, le S est remplace par J.
- Coder le mot SECRET.
- Dechiffrer le message suivant : KGHSX
Exercice 5 — Chiffrement de Hill¶
Le chiffrement de Hill utilise des matrices comme cle de chiffrement. Le message est decoupe en paires de lettres, chaque paire est convertie en un vecteur de deux nombres, puis multipliee par la matrice cle. Tous les calculs se font modulo 26.
On associe a chaque lettre de l'alphabet un entier de l'ensemble E = {0, 1, 2, ..., 25} suivant le tableau ci-dessous :
| A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
Principe du chiffrement :
Pour chiffrer une paire de lettres \((l_1, l_2)\) de numeros \((x_1, x_2)\) avec la matrice cle \(A\) :
Les nombres \(y_1\) et \(y_2\) sont ensuite reconvertis en lettres.
Exemple : chiffrer « OK » avec la matrice identite
O = 14, K = 10. Avec \(A = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix}\) :
Resultat : O, K → OK (la matrice identite ne chiffre rien, logique !)
Exemple : chiffrer « HI » avec \(A = \begin{pmatrix} 3 & 2 \\ 1 & 5 \end{pmatrix}\)
H = 7, I = 8.
Modulo 26 : \(37 \mod 26 = 11\) = L, \(47 \mod 26 = 21\) = V.
Resultat : HI → LV
Pour dechiffrer, on utilise la matrice inverse de A (calculee modulo 26). C'est la que les choses se compliquent...
Partie A : On se donne pour cle de chiffrement la matrice :
On va chiffrer dans la suite le mot INDICE a l'aide de la grille ci-dessus.
- Chiffrer le mot INDICE en utilisant la cle A. (Decouper en paires : IN, DI, CE)
- On souhaite a present retrouver le message clair correspondant au message chiffre DVUBYO. En deduire la cle de dechiffrement (message clair associe au texte chiffre).
- Dechiffrer le message YOWPEE.
Partie B : On se donne maintenant pour cle la matrice :
- Chiffrer le mot INDICE avec cette cle.
- Soit la matrice \(M = \begin{pmatrix} 7 & -5 \\ -4 & 9 \end{pmatrix}\). Calculer le produit MA et en deduire que A est inversible. On appellera B la matrice inverse de A.
- Expliquer pourquoi l'utilisation de la cle B ne permet pas de dechiffrer le message HTPQMK.
- Verifier que l'utilisation de la matrice C = 23M permet le dechiffrage du message HTPQMK.
Exercice 6 — Chiffrement ADFGVX¶
Le chiffrement ADFGVX est un systeme utilise par l'armee allemande durant la Premiere Guerre mondiale. Il combine une substitution (via une grille 6×6) et une transposition (via un mot cle).
Etape 1 — Substitution : On utilise la grille suivante, ou chaque lettre ou chiffre est remplace par un couple de lettres parmi {A, D, F, G, V, X} :
| A | D | F | G | V | X | |
|---|---|---|---|---|---|---|
| A | N | A | 1 | C | 3 | H |
| D | 8 | T | B | 2 | O | M |
| F | E | 5 | V | R | I | S |
| G | D | U | F | X | G | Y |
| V | 0 | P | L | W | 7 | 6 |
| X | J | 9 | Q | Z | 4 | K |
Par exemple, la lettre E se trouve a l'intersection de la ligne F et de la colonne A, donc E → FA.
Etape 2 — Transposition : On utilise le mot cle MARK. On ecrit le resultat de la substitution sous le mot cle (ligne par ligne), puis on reordonne les colonnes par ordre alphabetique du mot cle. Le message chiffre final se lit colonne par colonne (de haut en bas, de gauche a droite) dans le tableau reordonne.
Exemple detaille avec le mot « TE »
Substitution : T → DD, E → FA → resultat : DDFA
Transposition avec la cle MARK (4 colonnes) :
On ecrit les caracteres ligne par ligne sous le mot cle :
| M | A | R | K |
|---|---|---|---|
| D | D | F | A |
On reordonne les colonnes dans l'ordre alphabetique (A, K, M, R) :
| A | K | M | R |
|---|---|---|---|
| D | A | D | F |
On lit colonne par colonne, de haut en bas, de gauche a droite : DADF
Questions :
- Chiffrer le message « ATTAQUE » avec la grille ci-dessus et le mot cle MARK.
??? tip "Indication pour l'etape de substitution" Chaque lettre est remplacee par un couple de deux lettres parmi {A, D, F, G, V, X} en utilisant la grille. Le premier caractere du couple correspond a la ligne, le second a la colonne. Exemple : A se trouve ligne A, colonne D → A devient AD.
??? tip "Indication pour l'etape de transposition" Ecrire le resultat de la substitution (14 caracteres) ligne par ligne sous les lettres du mot cle MARK (4 colonnes), puis reordonner les colonnes dans l'ordre alphabetique : A, K, M, R. Attention : la derniere ligne peut etre incomplete. Lire ensuite colonne par colonne.
-
On recoit le message chiffre suivant : ADFFGFFGFFAFDXAXGGDGFGADVA. Le mot cle est CLEF. Dechiffrer ce message.
-
Pourquoi l'armee allemande a-t-elle choisi les lettres A, D, F, G, V, X pour ce chiffrement ? (Indice : pensez au code Morse et a la transmission radio.)
-
En quoi la double etape (substitution + transposition) rend-elle ce chiffrement plus resistant que chacune des deux techniques utilisee seule ?
Exercices de programmation (Python)¶
Programmation
Les exercices suivants sont a realiser en Python sur machine.
Partie 1 — Chiffrement de Cesar¶
Fichier : cesar.py
def chiffrer(texte: str, cle: int) -> str:
"""
Chiffre un texte avec le chiffre de Cesar.
- Seules les lettres sont chiffrees, le reste est conserve.
- La casse est preservee.
- La cle peut etre negative ou > 26.
"""
pass
def dechiffrer(texte: str, cle: int) -> str:
"""
Dechiffre un texte chiffre avec le chiffre de Cesar.
"""
pass
Tests a passer :
assert chiffrer("Hello World!", 3) == "Khoor Zruog!"
assert dechiffrer("Khoor Zruog!", 3) == "Hello World!"
assert chiffrer(dechiffrer("Test", 13), 13) == "Test"
Partie 2 — Force brute¶
Fichier : force_brute.py
def attaque_force_brute(texte_chiffre: str) -> list[tuple[int, str]]:
"""
Retourne tous les dechiffrements possibles sous forme de tuples (cle, texte),
tries par cle croissante.
"""
pass
Messages a casser :
Note
Les deux messages sont dans des langues differentes. La force brute fonctionne dans les deux cas — mais pouvez-vous identifier la bonne cle sans comprendre la langue ?
README : noter la cle trouvee et le message clair pour chaque message.
Partie 3 — Analyse frequentielle¶
Fichier : freq.py
3a. Calculer les frequences¶
# Frequences de reference (top 10)
FREQ_FR = {'e': 0.1471, 'a': 0.0762, 'i': 0.0744, 's': 0.0733, 't': 0.0721,
'n': 0.0711, 'r': 0.0655, 'u': 0.0631, 'l': 0.0546, 'o': 0.0514}
FREQ_EN = {'e': 0.1270, 't': 0.0906, 'a': 0.0817, 'o': 0.0751, 'i': 0.0697,
'n': 0.0675, 's': 0.0633, 'h': 0.0609, 'r': 0.0599, 'd': 0.0425}
# Frequences completes (26 lettres) pour les graphiques
FREQ_FR_FULL = {
'a': 0.0762, 'b': 0.0090, 'c': 0.0326, 'd': 0.0367, 'e': 0.1471,
'f': 0.0107, 'g': 0.0087, 'h': 0.0074, 'i': 0.0744, 'j': 0.0061,
'k': 0.0005, 'l': 0.0546, 'm': 0.0297, 'n': 0.0711, 'o': 0.0514,
'p': 0.0286, 'q': 0.0136, 'r': 0.0655, 's': 0.0733, 't': 0.0721,
'u': 0.0631, 'v': 0.0164, 'w': 0.0003, 'x': 0.0042, 'y': 0.0019,
'z': 0.0021
}
def calculer_frequences(texte: str) -> dict[str, float]:
"""
Calcule la frequence de chaque lettre dans le texte (float entre 0 et 1).
Insensible a la casse. Ignore les non-lettres.
Retourne un dictionnaire avec les 26 lettres (meme celles absentes, a 0.0).
"""
pass
def deviner_cle(texte_chiffre: str, langue: str = "fr") -> int:
"""
Estime la cle par analyse frequentielle.
Strategie : lettre la plus frequente dans le texte chiffre ≈ 'e' dans la langue.
langue : "fr" ou "en"
Retourne la cle estimee (int 0-25).
"""
pass
A faire : charger les messages depuis messages/message_fr.txt et messages/message_en.txt, deviner la cle, dechiffrer.
3b. Visualiser avec matplotlib¶
import matplotlib.pyplot as plt
def afficher_frequences(texte_chiffre: str, langue: str = "fr") -> None:
"""
Affiche un graphique comparant :
- les frequences des lettres dans le texte chiffre (barres bleues)
- les frequences theoriques de la langue (barres rouges, transparentes)
Etapes :
1. Calculer les frequences du texte chiffre avec calculer_frequences()
2. Recuperer les frequences theoriques (FREQ_FR_FULL ou FREQ_EN_FULL)
3. Tracer deux series de barres cote a cote pour les 26 lettres (a-z)
4. Ajouter titre, legende et labels des axes
5. Appeler plt.show()
"""
pass
Indices pour le graphique
import matplotlib.pyplot as plt
import numpy as np
lettres = list("abcdefghijklmnopqrstuvwxyz")
x = np.arange(26)
largeur = 0.35
# Barres cote a cote
plt.bar(x - largeur/2, freq_texte, largeur, label="Texte chiffre", color="steelblue")
plt.bar(x + largeur/2, freq_langue, largeur, label="Francais theorique", color="indianred", alpha=0.7)
plt.xticks(x, lettres)
plt.ylabel("Frequence")
plt.title("Analyse frequentielle — texte chiffre vs langue")
plt.legend()
plt.tight_layout()
plt.show()
```
### 3c. Verifier visuellement la cle
```python
def afficher_comparaison_decalage(texte_chiffre: str, cle: int, langue: str = "fr") -> None:
"""
Affiche un graphique comparant les frequences du texte DECHIFFRE
(avec la cle donnee) aux frequences theoriques de la langue.
Si la cle est correcte, les barres bleues et rouges doivent se superposer.
"""
pass
!!! example "Resultat attendu" - Avant dechiffrement : les barres bleues sont decalees par rapport aux rouges. Le decalage correspond a la cle. - Apres dechiffrement (bonne cle) : les barres bleues et rouges se superposent → la cle est correcte. - Apres dechiffrement (mauvaise cle) : les barres ne correspondent toujours pas.
README : noter la cle devinee, le message dechiffre, et si l'analyse a fonctionne du premier coup. Inclure une capture d'ecran du graphique avant/apres dechiffrement.
Partie 4 — Vigenere¶
Fichier : vigenere.py
def chiffrer_vigenere(texte: str, cle: str) -> str:
"""
Chiffre avec Vigenere. La cle est une chaine de lettres (ex: "CRYPTO").
Seules les lettres sont chiffrees, le reste est conserve.
"""
pass
def casser_vigenere(texte_chiffre: str, langue: str = "fr") -> tuple[str, str]:
"""
Casse le chiffre de Vigenere par analyse frequentielle.
Etapes suggerees :
1. Trouver la longueur de cle (indice de coincidence ou test de Kasiski)
2. Traiter chaque position comme un Cesar independant
3. Appliquer l'analyse frequentielle sur chaque groupe
Retourne (cle_trouvee, texte_dechiffre).
"""
pass
README a rendre¶
# TD1 — Cryptographie classique
## Exercices sur papier
### Exercice 1 — Cesar
- 1. Message chiffre (K=5) : \_\_\_
- 2. Message dechiffre (RGNEIDVGPEWXTRAPHHXFJT) : **_, cle = _**
- 3. Cle trouvee : **_, debut du message clair : _**
### Exercice 2 — Substitution
- 1. Message chiffre : \_\_\_
- 2. YHVMQUVMH dechiffre : **_. Peut-on le casser sans la cle ? _**
### Exercice 3 — Vigenere (papier)
- 1. Message chiffre (cle POULE) : \_\_\_
- 2. BAUNBEKLZLQSKQKEBGCJYHVSKR dechiffre (cle TNCY) : \_\_\_
### Exercice 4 — Chiffrement affine
- 1. Verification S → J : \_\_\_
- 2. SECRET code : \_\_\_
- 3. Demonstration : \_\_\_
- 4. KGHSX dechiffre : \_\_\_
### Exercice 5 — Chiffrement affine (generalisation)
- 1. Demonstration (a premier avec 26) : \_\_\_
- 2a. Existence de u : \_\_\_
- 2b. Fonction de decodage : \_\_\_
- 2c. ZSPS decode (cle 15;2) : \_\_\_
### Exercice 6 — Hill
- Partie A : INDICE chiffre = **_, DVUBYO dechiffre = _**, YOWPEE dechiffre = \_\_\_
- Partie B : INDICE chiffre = **_, produit MA = _**, explication cle B = **_, verification C = 23M : _**
### Exercice 7 — ADFGVX
- 1. ATTAQUE chiffre : \_\_\_
- 2. DFAADDGAFXDDADFA dechiffre : \_\_\_
- 3. Pourquoi A, D, F, G, V, X ? \_\_\_
- 4. Interet de la double etape : \_\_\_
## Exercices Python
### Force brute
- Message francais : cle = **_, message clair = _**
- Message anglais : cle = **_, message clair = _**
### Analyse frequentielle
- Message francais : cle devinee = **_, correcte ? _**
- Message anglais : cle devinee = **_, correcte ? _**
- Observations : (l'analyse a-t-elle fonctionne du premier coup ? Pourquoi ?)
### Vigenere
- Cle trouvee : \_\_\_
- Methode utilisee : \_\_\_
## Difficultes rencontrees
(libre)