ajout activités autour de X-Files

This commit is contained in:
2026-08-11 22:31:56 +02:00
parent fc19dd07d7
commit bd1a254398
2 changed files with 825 additions and 0 deletions
+374
View File
@@ -0,0 +1,374 @@
# TP : Dossier Dudley — une enquête épidémiologique
## Contexte
Vous êtes analyste de données au **Centre de veille sanitaire**. On vous confie un dossier
concernant **Dudley**, une petite commune rurale de l'Arkansas organisée autour d'une seule
entreprise : l'usine de transformation de volaille **Chaco Chicken**.
Le signalement est bref :
> *Plusieurs habitants de Dudley sont décédés récemment d'une maladie neurologique rare,
> la maladie de Creutzfeldt-Jakob. Le nombre de cas paraît anormalement élevé pour une
> commune de cette taille. Un inspecteur fédéral de l'agriculture envoyé sur place au
> mois de mars a disparu.*
Vous disposez de six tables : l'état civil, les emplois à l'usine, les diagnostics
enregistrés par le cabinet médical, les repas communautaires organisés dans la commune,
la liste des participants à ces repas, et les disparitions signalées.
**Votre mission : trouver la source de la contamination, uniquement avec des requêtes SQL.**
> *Ce TP s'inspire librement de l'épisode « Our Town » (X-Files, saison 2). Le mécanisme
> biologique, lui, est réel : les maladies à prions se transmettent par l'alimentation.
> C'est ce mécanisme qui a provoqué la crise de la « vache folle » en Europe dans les
> années 1990.*
---
## Objectifs
- Interroger une base de données relationnelle à six tables
- Maîtriser les jointures, y compris à travers une table d'association
- Utiliser les fonctions d'agrégation (`COUNT`, `AVG`, `MIN`, `MAX`) et la clause `HAVING`
- Comprendre qu'une requête n'est pas seulement un exercice de syntaxe : c'est un
**instrument d'enquête**
---
## Partie 1 : Mise en place de la base
### 1.1. Création des tables
Ouvrez **DB Browser for SQLite**, créez une base `dudley.db`, puis exécutez :
```sql
-- État civil de la commune et des environs
CREATE TABLE HABITANTS (
id INTEGER PRIMARY KEY,
nom TEXT NOT NULL,
prenom TEXT NOT NULL,
annee_naissance INTEGER,
annee_deces INTEGER, -- NULL si la personne est vivante
commune TEXT
);
-- Emplois occupés à l'usine Chaco Chicken
CREATE TABLE EMPLOIS (
id INTEGER PRIMARY KEY,
id_habitant INTEGER,
poste TEXT,
annee_embauche INTEGER,
annee_fin INTEGER, -- NULL si toujours en poste
FOREIGN KEY (id_habitant) REFERENCES HABITANTS(id)
);
-- Diagnostics enregistrés par le cabinet médical
CREATE TABLE DIAGNOSTICS (
id INTEGER PRIMARY KEY,
id_habitant INTEGER,
annee INTEGER,
symptome TEXT,
diagnostic TEXT,
FOREIGN KEY (id_habitant) REFERENCES HABITANTS(id)
);
-- Repas communautaires organisés dans la commune
CREATE TABLE REPAS (
id INTEGER PRIMARY KEY,
date DATE,
lieu TEXT,
occasion TEXT
);
-- Table d'association : qui a participé à quel repas
CREATE TABLE PARTICIPATIONS (
id INTEGER PRIMARY KEY,
id_habitant INTEGER,
id_repas INTEGER,
FOREIGN KEY (id_habitant) REFERENCES HABITANTS(id),
FOREIGN KEY (id_repas) REFERENCES REPAS(id)
);
-- Disparitions signalées à la gendarmerie
CREATE TABLE DISPARITIONS (
id INTEGER PRIMARY KEY,
id_habitant INTEGER,
date_disparition DATE,
statut_enquete TEXT,
FOREIGN KEY (id_habitant) REFERENCES HABITANTS(id)
);
```
### 1.2. Insertion des données
```sql
-- ------------------------------------------------------------------
-- HABITANTS
-- ------------------------------------------------------------------
INSERT INTO HABITANTS (id, nom, prenom, annee_naissance, annee_deces, commune) VALUES
-- Dudley : les anciens
(1, 'Chaco', 'Walter', 1902, NULL, 'Dudley'),
(2, 'Riddick', 'Doris', 1891, 1988, 'Dudley'),
(3, 'Bowman', 'Elias', 1888, 1985, 'Dudley'),
(4, 'Kingston', 'Martha', 1893, 1989, 'Dudley'),
(5, 'Prine', 'Howard', 1890, 1987, 'Dudley'),
(6, 'Sheldon', 'Rita', 1895, 1989, 'Dudley'),
(7, 'Farrow', 'Nelson', 1899, 1989, 'Dudley'),
-- Dudley : décès récents
(8, 'Gwynn', 'Paula', 1957, 1995, 'Dudley'),
(9, 'Kittel', 'Ray', 1949, 1995, 'Dudley'),
(10, 'Vance', 'Bonnie', 1962, 1994, 'Dudley'),
(11, 'Hooper', 'Jess', 1954, 1994, 'Dudley'),
(12, 'Traylor', 'Sam', 1960, 1995, 'Dudley'),
(13, 'Doyle', 'Nancy', 1951, 1995, 'Dudley'),
-- Dudley : vivants
(14, 'Ashby', 'Curtis', 1965, NULL, 'Dudley'),
(15, 'Lowell', 'Beatrice', 1970, NULL, 'Dudley'),
(16, 'Pruitt', 'Wendell', 1958, NULL, 'Dudley'),
(17, 'Kearns', 'George', 1948, NULL, 'Dudley'),
-- Millhaven : commune voisine, prise comme référence
(18, 'Sorrel', 'Agnes', 1912, 1988, 'Millhaven'),
(19, 'Buckley', 'Harold', 1918, 1994, 'Millhaven'),
(20, 'Neame', 'Constance', 1921, 1995, 'Millhaven'),
(21, 'Ferrell', 'Douglas', 1908, 1986, 'Millhaven'),
(22, 'Whitlock', 'Irene', 1925, 1993, 'Millhaven'),
(23, 'Amos', 'Leonard', 1915, 1989, 'Millhaven'),
(24, 'Bly', 'Marjorie', 1930, NULL, 'Millhaven'),
-- Dudley : deux dossiers anciens
(25, 'Guthrie', 'Samuel', 1935, NULL, 'Dudley'),
(26, 'Lomax', 'Edna', 1940, NULL, 'Dudley');
-- ------------------------------------------------------------------
-- EMPLOIS (usine Chaco Chicken)
-- ------------------------------------------------------------------
INSERT INTO EMPLOIS (id, id_habitant, poste, annee_embauche, annee_fin) VALUES
(1, 1, 'Directeur', 1944, NULL),
(2, 2, 'Ouvriere de decoupe', 1932, 1972),
(3, 4, 'Contremaitresse', 1935, 1975),
(4, 5, 'Veterinaire', 1930, 1970),
(5, 7, 'Ouvrier de decoupe', 1938, 1978),
(6, 8, 'Ouvriere de decoupe', 1978, 1994),
(7, 9, 'Conducteur de ligne', 1971, 1995),
(8, 10, 'Ouvriere de decoupe', 1984, 1994),
(9, 11, 'Agent d''entretien', 1976, 1994),
(10, 12, 'Conducteur de ligne', 1982, 1995),
(11, 13, 'Ouvriere de conditionnement', 1973, 1995),
(12, 14, 'Conducteur de ligne', 1988, NULL),
(13, 15, 'Ouvriere de conditionnement', 1992, NULL),
(14, 16, 'Chef d''equipe', 1980, NULL),
(15, 26, 'Ouvriere de conditionnement', 1962, 1988);
-- ------------------------------------------------------------------
-- DIAGNOSTICS
-- ------------------------------------------------------------------
INSERT INTO DIAGNOSTICS (id, id_habitant, annee, symptome, diagnostic) VALUES
(1, 8, 1993, 'Troubles de la coordination', 'Trouble neurologique non identifie'),
(2, 8, 1994, 'Demence rapide', 'Maladie de Creutzfeldt-Jakob'),
(3, 9, 1994, 'Pertes de memoire', 'Trouble neurologique non identifie'),
(4, 9, 1995, 'Myoclonies', 'Maladie de Creutzfeldt-Jakob'),
(5, 10, 1993, 'Troubles de la vision', 'Trouble neurologique non identifie'),
(6, 10, 1994, 'Demence rapide', 'Maladie de Creutzfeldt-Jakob'),
(7, 11, 1993, 'Troubles de la coordination', 'Maladie de Creutzfeldt-Jakob'),
(8, 12, 1994, 'Myoclonies', 'Maladie de Creutzfeldt-Jakob'),
(9, 13, 1994, 'Pertes de memoire', 'Maladie de Creutzfeldt-Jakob'),
(10, 14, 1994, 'Fracture du poignet', 'Traumatisme'),
(11, 15, 1995, 'Angine', 'Infection ORL'),
(12, 19, 1993, 'Douleurs thoraciques', 'Insuffisance cardiaque'),
(13, 22, 1992, 'Toux persistante', 'Cancer du poumon'),
(14, 2, 1987, 'Fatigue', 'Vieillissement'),
(15, 16, 1994, 'Lombalgie', 'Trouble musculo-squelettique');
-- ------------------------------------------------------------------
-- REPAS communautaires
-- ------------------------------------------------------------------
INSERT INTO REPAS (id, date, lieu, occasion) VALUES
(1, '1988-09-17', 'Ferme Chaco', 'Banquet annuel Chaco Chicken'),
(2, '1989-06-24', 'Salle des fetes', 'Fete de la moisson'),
(3, '1990-09-15', 'Ferme Chaco', 'Banquet annuel Chaco Chicken'),
(4, '1992-12-24', 'Eglise de Dudley', 'Reveillon de Noel'),
(5, '1995-03-11', 'Ferme Chaco', 'Banquet annuel Chaco Chicken');
-- ------------------------------------------------------------------
-- PARTICIPATIONS
-- ------------------------------------------------------------------
INSERT INTO PARTICIPATIONS (id, id_habitant, id_repas) VALUES
-- Repas 1 (17 septembre 1988)
(1, 8, 1), (2, 9, 1), (3, 10, 1), (4, 11, 1), (5, 12, 1), (6, 13, 1),
(7, 1, 1), (8, 2, 1), (9, 4, 1), (10, 14, 1), (11, 16, 1),
-- Repas 2 (24 juin 1989)
(12, 8, 2), (13, 9, 2), (14, 10, 2), (15, 11, 2),
(16, 1, 2), (17, 14, 2), (18, 15, 2), (19, 16, 2),
-- Repas 3 (15 septembre 1990)
(20, 8, 3), (21, 9, 3), (22, 12, 3), (23, 13, 3),
(24, 1, 3), (25, 14, 3), (26, 16, 3), (27, 17, 3),
-- Repas 4 (24 decembre 1992)
(28, 9, 4), (29, 10, 4), (30, 11, 4), (31, 12, 4), (32, 13, 4),
(33, 15, 4), (34, 16, 4),
-- Repas 5 (11 mars 1995)
(35, 1, 5), (36, 14, 5), (37, 15, 5), (38, 16, 5), (39, 24, 5);
-- ------------------------------------------------------------------
-- DISPARITIONS
-- ------------------------------------------------------------------
INSERT INTO DISPARITIONS (id, id_habitant, date_disparition, statut_enquete) VALUES
(1, 25, '1961-07-22', 'Classee sans suite'),
(2, 26, '1988-09-14', 'Classee sans suite'),
(3, 17, '1995-03-08', 'En cours');
```
> **Remarque.** Les accents ont été retirés des données pour éviter tout problème
> d'encodage selon les postes. Les apostrophes des textes SQL sont doublées (`d''entretien`) :
> c'est la façon d'écrire une apostrophe *à l'intérieur* d'une chaîne.
### 1.3. Schéma relationnel
Dessinez le schéma de la base en identifiant les clés primaires (PK) et les clés
étrangères (FK).
**Question de mise en route :** la table `PARTICIPATIONS` ne contient aucune information
« propre » — que des clés étrangères. À quoi sert-elle ? Pourquoi ne peut-on pas simplement
ajouter une colonne `id_repas` dans `HABITANTS` ?
---
## Partie 2 : Prise en main (requêtes simples)
**Pour chaque question, écrivez la requête et notez le résultat obtenu.**
**1.** Affichez le nom, le prénom et l'année de naissance de tous les habitants de Dudley,
triés du plus âgé au plus jeune.
**2.** Affichez le nom et le prénom des habitants encore en vie.
*(Indice : une valeur absente se teste avec `IS NULL`, pas avec `= NULL`.)*
**3.** Affichez la liste des postes différents occupés à l'usine Chaco Chicken, sans doublon.
**4.** Affichez la date et l'occasion des repas qui se sont tenus à la Ferme Chaco.
---
## Partie 3 : Croiser les tables (jointures)
**5.** Affichez le nom, le prénom et le poste de chaque personne ayant travaillé à l'usine.
**6.** Affichez le nom, le prénom et l'année du diagnostic de tous les habitants
diagnostiqués `'Maladie de Creutzfeldt-Jakob'`.
**7.** Affichez le nom et le prénom de toutes les personnes ayant participé au repas
du 17 septembre 1988.
*(Indice : il faut passer par `PARTICIPATIONS`, donc joindre trois tables.)*
**8.** Affichez le nom, le prénom, la date et le statut de l'enquête pour chaque disparition
signalée.
**9.** Affichez le nom et le prénom des habitants de Dudley qui n'ont **jamais** travaillé
à l'usine.
*(Indice : `NOT IN (SELECT ...)` ou une jointure externe.)*
---
## Partie 4 : Compter et mesurer (agrégations)
**10.** Combien y a-t-il d'habitants recensés dans chaque commune ?
**11.** Pour chaque repas, affichez sa date et son nombre de participants.
**12.** Pour chaque commune, calculez l'âge moyen au décès des personnes décédées.
*(Indice : l'âge au décès se calcule à partir de deux colonnes.)*
**13.** Combien de fois chaque diagnostic apparaît-il dans la base ? Classez du plus
fréquent au moins fréquent.
**14.** Quels habitants ont participé à au moins 3 repas ? Affichez leur nom et leur nombre
de participations.
---
## Partie 5 : Une anomalie
Les résultats de la question 12 méritent qu'on s'y arrête. Reprenons-les en séparant
les époques.
**15.** Pour chaque commune, calculez l'âge moyen au décès **des personnes décédées avant 1990**.
Que constatez-vous pour Dudley ?
**16.** Même question pour les personnes décédées **à partir de 1990**. Comparez les deux
résultats commune par commune.
> Rédigez deux ou trois phrases : que s'est-il passé à Dudley entre ces deux périodes ?
> Le même phénomène s'observe-t-il à Millhaven ?
**17.** Affichez le nom, le prénom et l'âge au décès de chaque personne diagnostiquée
`'Maladie de Creutzfeldt-Jakob'`. Combien sont-elles ? Toutes appartiennent-elles à la
même commune ?
---
## Partie 6 : La source
Vous avez maintenant un groupe de malades identifié. En épidémiologie, la question suivante
est toujours la même : **qu'ont-ils en commun que les autres n'ont pas ?**
**18.** Trouvez **le repas auquel ont participé toutes les personnes** diagnostiquées
`'Maladie de Creutzfeldt-Jakob'`, et uniquement celui-là.
*Indice :* comptez, pour chaque repas, le nombre de malades présents, puis ne gardez que
les repas où ce nombre est égal au nombre total de malades. La clause qui filtre **après**
un regroupement s'appelle `HAVING`.
**19.** Affichez chaque disparition signalée, accompagnée du repas qui a eu lieu dans les
**7 jours suivants**, s'il y en a un.
*Indice :* en SQLite, `date(d.date_disparition, '+7 days')` renvoie la date décalée de
sept jours. Vous pouvez alors comparer directement les dates entre elles.
**20.** Le dernier banquet a eu lieu le 11 mars 1995. Affichez le nom et le prénom de ses
participants, et indiquez pour chacun s'il figure ou non dans la table `DIAGNOSTICS`
avec le diagnostic `'Maladie de Creutzfeldt-Jakob'`.
> **Rédigez la conclusion de votre rapport (5 à 10 lignes).** Quelle est la source probable
> de la contamination ? Quel lien faites-vous entre les dates des banquets et celles des
> disparitions ? Et surtout : au vu de la question 20, l'affaire est-elle close ?
---
## Questions de réflexion
**1.** Pourquoi avoir séparé `HABITANTS` et `EMPLOIS` dans deux tables, plutôt que d'ajouter
une colonne `poste` dans `HABITANTS` ?
**2.** À la question 18, on compte les malades présents à chaque repas. Un même habitant
peut apparaître plusieurs fois dans `DIAGNOSTICS`. En quoi cela pourrait-il fausser le
comptage, et comment s'en prémunir ?
**3.** L'incubation d'une maladie à prion dure souvent **plus de dix ans** entre la
contamination et les premiers symptômes. En quoi ce délai rend-il ce type d'enquête
difficile ? Quelles données faudrait-il conserver, et pendant combien de temps ?
**4.** La base ne contient que les repas *déclarés* et les disparitions *signalées*.
Quelles conclusions cela vous interdit-il de tirer ? Formulez une phrase précisant ce que
vos requêtes démontrent réellement, et ce qu'elles ne font que suggérer.
---
## Barème indicatif
| Partie | Points |
|--------|--------|
| Partie 1 : schéma et question de mise en route | 2 |
| Partie 2 : requêtes simples | 3 |
| Partie 3 : jointures | 4 |
| Partie 4 : agrégations | 4 |
| Partie 5 : anomalie + rédaction | 3 |
| Partie 6 : source + conclusion | 3 |
| Questions de réflexion | 1 |
| **Total** | **20** |
---
Auteur : Florian Mathieu
Licence CC BY NC
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
+451
View File
@@ -0,0 +1,451 @@
# TP : La bande du Penseur
## Contexte
Un informaticien surnommé **le Penseur** est parvenu à extraire des serveurs du
ministère de la Défense une archive de documents classifiés, produits par un comité
interne baptisé **Majestic Twelve** (en abrégé : MJ-12). Il a copié le tout sur une
bande numérique et l'a transmise à un enquêteur.
La bande contient **trois fichiers**. Aucun n'est lisible directement.
Vous êtes chargé·e de les ouvrir, dans l'ordre : chaque fichier contient l'information
nécessaire pour aborder le suivant.
Ce TP est aussi, et peut-être surtout, une enquête sur une question de fond :
**qu'est-ce qui protège réellement un message ?**
> *Ce TP s'inspire de l'épisode « Anasazi » (X-Files, saison 2, épisode 25, diffusé le
> 19 mai 1995). La partie 6 revient sur l'épisode et sur ce qu'il raconte - vous pouvez
> la lire dès maintenant, elle ne dévoile rien des solutions.*
---
## Objectifs
- Attaquer un chiffrement par **analyse de fréquences**
- Attaquer un chiffrement **XOR** à clé courte par **force brute**
- Comprendre la différence entre le **secret de l'algorithme** et le **secret de la clé**
- Découvrir et formuler le **principe de Kerckhoffs**
- Connaître l'histoire des **code talkers navajos** et ce qu'elle apprend en cryptographie
---
## Partie 1 : Le premier fichier
### 1.1. Ce qu'on sait
Le fichier `fichier1.txt` a été chiffré par le comité avec un système **conçu en interne**,
dont les spécifications n'ont jamais été publiées. D'après une note retrouvée, chaque
lettre du message a été systématiquement remplacée par une autre lettre, toujours la même.
Espaces et ponctuation ont été conservés.
Voici son contenu :
```
YKLF QF PFWCNMF NYLFWYF. JF AWFPFYL QKMSIFYL YF QKNL FY HSMSY MHP ZSNLLFW
JF PFWCNMF. JFP FJFIFYLP WHPPFIDJFP QFASNP QNR HYP PSW JF AWKBFL PKYL
QFPKWIHNP WFSYNP QHYP SY PFSJ QKPPNFW. YKSP HCKYP MOKNPN QF YF AHP SLNJNPFW
JFP PVPLFIFP QF MONUUWFIFYL QS INYNPLFWF, QKYL JFP PAFMNUNMHLNKYP PKYL
ASDJNZSFP FL QKYM CSJYFWHDJFP. YKLWF AWKAWF IFLOKQF, MKYMSF FY NYLFWYF FL
MKYYSF QFP PFSJP IFIDWFP QS MKINLF, KUUWF SYF AWKLFMLNKY DNFY PSAFWNFSWF
ASNPZSF AFWPKYYF H J FRLFWNFSW Y FY MKYYHNL JF AWNYMNAF. JH MJF QS PFMKYQ
UNMONFW FPL SY IKL QF LWKNP JFLLWFP ZSN QFPNEYF JF MKINLF JSN IFIF.
```
### 1.2. Travail demandé
**Q1.** Quel type de chiffrement reconnaissez-vous ? Est-ce un chiffre de César ?
Justifiez en observant le texte : le décalage est-il le même pour toutes les lettres ?
**Q2.** Écrivez une fonction qui compte les occurrences de chaque lettre du texte chiffré
et affiche les résultats du plus fréquent au moins fréquent.
```python
def frequences(texte):
"""Renvoie la liste des couples (lettre, nombre d'occurrences),
triee par nombre d'occurrences decroissant.
Les caracteres qui ne sont pas des lettres sont ignores."""
...
```
**Q3.** En français, les lettres les plus fréquentes sont, dans l'ordre :
**E, A, S, I, N, T, R, U, L, O**. Le texte compte 474 lettres, ce qui est suffisant
pour que la statistique soit fiable.
Quelle lettre du texte chiffré correspond très probablement à `E` ? Et à la deuxième
lettre la plus fréquente ?
**Q4.** Le mot d'une seule lettre `H` apparaît dans le texte, ainsi que `J` et `Y`.
En français, quels sont les mots d'une seule lettre ? Que vous apprend cette observation ?
**Q5.** Complétez progressivement votre table de correspondance et déchiffrez le message.
Vous pouvez travailler par essais successifs : remplacez les lettres dont vous êtes sûr·e,
puis devinez les mots partiellement révélés.
```python
def dechiffre(texte, table):
"""Remplace chaque lettre de texte selon le dictionnaire table.
Les lettres absentes de table sont laissees telles quelles."""
...
```
**Q6.** Le message se vante d'une protection « bien supérieure » à celle du ministère,
au motif que personne à l'extérieur n'en connaît le principe.
**Combien de temps vous a-t-il fallu pour le lire ?** Que pensez-vous de l'argument ?
---
## Partie 2 : Le deuxième fichier
### 2.1. Ce qu'on sait
Le premier fichier vous a indiqué la nature de la clé du second. Le fichier `fichier2.hex`
a été chiffré par **XOR** — l'opération que vous avez déjà utilisée dans le TP du
gestionnaire de mots de passe — avec une **clé de trois lettres majuscules**, répétée
tout au long du message.
Le contenu est donné en **hexadécimal** (deux caractères par octet) :
```
0e05191d1e116d1811030e016d0e016d091b000300086474010f7419181b04191d0807116d
0c1d0e021d081874036a111e1e741d0b076d091c040c121f0f7a6d03186d0f07196a06080e
1d0a0f74090b1a1e6a01030f74010b1a0a1f116d1b01086a041f0f071c1f116d1a111f191b
0304116d04116d1a151f06116d0f006d1b01046a1a086a076d0f171f03006d1a151e64740c
1f171804116d07150e021d030f74030f741d05011f18156d0015000b1d1e6a18086a180418
11636a176d0f07196a180c6a19080318010f011f0f741d181b190f1719031b036a05180374
1e051d196474191815031919081e001f0f740c1f741e0300086a10086a07190517060b1308
64
```
### 2.2. Travail demandé
**Q7.** Rappelez la propriété du XOR qui rend le déchiffrement possible :
que vaut `A XOR B XOR B` ?
**Q8.** Convertissez la chaîne hexadécimale en octets, puis écrivez la fonction de
déchiffrement.
```python
donnees = bytes.fromhex(HEXA) # HEXA = la chaine ci-dessus, sans retours a la ligne
def xor(donnees, cle):
"""Renvoie les octets de donnees combines par XOR avec la cle,
repetee autant de fois que necessaire."""
...
```
**Q9.** La clé fait trois lettres majuscules. **Combien de clés faut-il tester au
maximum ?** Ce nombre est-il un obstacle pour un ordinateur ?
**Q10.** Écrivez une attaque par force brute. Le problème n'est pas de produire les
17 576 déchiffrements — c'est de **reconnaître automatiquement le bon**.
Proposition : le message clair ne contient que des majuscules, des espaces, des points
et des virgules. Écrivez une fonction qui teste si un déchiffrement ne contient
**que** des caractères de cet ensemble, et n'affichez que les clés qui passent ce test.
```python
AUTORISES = set("ABCDEFGHIJKLMNOPQRSTUVWXYZ .,")
def est_plausible(octets):
"""Renvoie True si octets se decode en ASCII et si tous ses caracteres
appartiennent a AUTORISES."""
...
```
**Q11.** Combien de clés passent le test ? Déchiffrez le message.
**Q12.** À quoi correspondent les trois lettres de la clé ? Quelqu'un qui connaît le
contexte de l'affaire aurait-il eu besoin de la force brute ?
**Q13.** Cette fois, l'algorithme était **public** : vous saviez dès le départ qu'il
s'agissait d'un XOR. Pourtant le fichier est tombé. **Qu'est-ce qui a échoué ici :
l'algorithme, ou la clé ?**
---
## Partie 3 : Le troisième fichier
### 3.1. Ce qu'on sait
Le deuxième fichier annonce que le troisième **n'est pas chiffré**.
Le voici, dans son intégralité :
```
NA-NIL-IN BEH-EH-HO-ZINZ
TSA-OND
WOL-LA-CHEE TSAH BE-LA-SANA DIBEH TSE-NILL BESH-DO-TLIZ TKIN
```
### 3.2. Première approche
**Q14.** Appliquez votre fonction `frequences` de la question 2 à ce texte.
Le résultat vous aide-t-il ? Pourquoi ?
**Q15.** Pourriez-vous monter une attaque par force brute ? Sur quoi porterait-elle ?
Combien de possibilités devriez-vous tester ?
**Q16.** À ce stade, expliquez en deux phrases **pourquoi vous êtes bloqué·e**.
La difficulté est-elle de nature mathématique ?
### 3.3. Le lexique
Voici un extrait du document qui permet de lire le fichier. Il s'agit d'un extrait
authentique du **dictionnaire des code talkers navajos**, dans sa révision du
15 juin 1945, déclassifié en 1968.
**Vocabulaire**
| Terme navajo | Traduction littérale | Sens codé |
|---|---|---|
| NA-NIL-IN | *kept secret* | CONFIDENTIEL |
| BEH-EH-HO-ZINZ | *document* | DOCUMENT |
| TSA-OND | *rock cave* | GROTTE |
**Alphabet** (chaque mot vaut la **première lettre** de sa traduction anglaise)
| Terme navajo | Traduction littérale | Lettre |
|---|---|---|
| WOL-LA-CHEE | *ant* (fourmi) | **A** |
| BE-LA-SANA | *apple* (pomme) | **A** |
| TSE-NILL | *axe* (hache) | **A** |
| TSAH | *needle* (aiguille) | **N** |
| DIBEH | *sheep* (mouton) | **S** |
| BESH-DO-TLIZ | *zinc* | **Z** |
| TKIN | *ice* (glace) | **I** |
**Q17.** Déchiffrez le fichier. Combien de temps cela vous a-t-il pris, une fois le
lexique en main ?
**Q18.** Observez les trois premières lignes du tableau de l'alphabet. **Trois mots
différents désignent la même lettre.** À votre avis, pourquoi les concepteurs du code
ont-ils fait ce choix ? Reliez votre réponse à la question 14.
---
## Partie 4 : Les code talkers navajos — ce qui s'est réellement passé
*Cette partie est à lire. Elle ne demande pas de programmation, mais deux questions
sont posées à la fin.*
### Le problème
Au début de 1942, dans le Pacifique, les transmissions radio américaines sont
systématiquement interceptées et décryptées par l'armée japonaise. Les chiffrements
mécaniques disponibles sont sûrs mais lents : coder puis décoder un ordre demande de
longues minutes, ce qui est incompatible avec la conduite d'un combat.
### L'idée
**Philip Johnston**, ingénieur civil et vétéran de la Première Guerre mondiale, avait
grandi sur la réserve navajo où son père était missionnaire. Il faisait partie du très
petit nombre de non-Navajos parlant la langue. Il propose au Corps des Marines
d'utiliser le navajo pour les transmissions.
La langue s'y prêtait remarquablement : elle **ne s'écrivait pas**, sa grammaire et sa
tonalité la rendaient très difficile à acquérir, et on estimait alors qu'une trentaine
de personnes extérieures au peuple navajo la parlaient — aucune n'étant japonaise.
### Ce que le code était vraiment
C'est ici que l'idée reçue — « ils parlaient navajo à la radio » — est fausse.
**Vingt-neuf** premières recrues navajos, engagées en mai 1942, ne se sont pas contentées
de traduire : elles ont **construit un code**, avec deux niveaux.
1. **Un alphabet phonétique.** Chaque lettre est représentée par un mot navajo dont la
traduction anglaise commence par cette lettre. Pour transmettre `N`, on dit *tsah*,
qui signifie « aiguille » — *needle* en anglais. Le déchiffrement demande donc de
traduire le mot navajo en anglais, puis d'en garder l'initiale.
2. **Un dictionnaire de code.** Environ quatre cents termes militaires reçoivent un mot
navajo convenu, sans rapport avec leur sens. Un sous-marin devient *besh-lo*,
« poisson de fer ». Un avion de chasse, *da-he-tih-hi*, « colibri ». Un cuirassé,
*lo-tso*, « baleine ». Un destroyer, *ca-lo*, « requin ».
Autrement dit, ce dictionnaire **est une clé**. Il a été appris par cœur, jamais emporté
au combat.
### La parade contre l'analyse de fréquences
Les concepteurs avaient identifié la faiblesse que vous avez exploitée en partie 1.
Si chaque lettre correspondait à un seul mot navajo, il aurait suffi de compter les
occurrences pour retrouver le `E`.
Ils ont donc **attribué plusieurs mots aux lettres les plus fréquentes**, entre lesquels
l'opérateur alternait au hasard. L'alphabet est passé de 26 à 44 termes, enrichi
précisément sur E, T, A, O, I, N, S, H, R, D, L et U.
C'est pourquoi votre lexique de la partie 3 contient trois mots pour la lettre A.
### La preuve par un prisonnier
**Joe Kieyoomia**, sergent navajo du 200<sup>e</sup> régiment d'artillerie côtière du
Nouveau-Mexique, est capturé aux Philippines en 1942 et survit à la marche de la mort de
Bataan. Les Japonais découvrent qu'il est navajo et lui font écouter les transmissions
interceptées.
**Il ne comprend rien.** Il parle pourtant parfaitement le navajo — mais il ignorait
jusqu'à l'existence du code, et les messages, faits de mots de code convenus, ne
formaient pour lui aucun sens. Il est torturé pour ce refus supposé, forcé de rester nu
dans la neige. Il survivra à la guerre, et se trouvera à Nagasaki lors du bombardement
atomique du 9 août 1945, protégé par les murs de sa cellule.
### Le résultat
Le code n'a jamais été cassé. À Iwo Jima, six code talkers ont transmis plus de huit
cents messages en deux jours sans une seule erreur. Le major Howard Connor, officier
transmissions de la 5<sup>e</sup> division de Marines, déclarera : *« Sans les Navajos,
les Marines n'auraient jamais pris Iwo Jima. »*
Le programme est resté **classifié jusqu'en 1968** : pendant vingt-trois ans, les code
talkers n'ont pas eu le droit de dire ce qu'ils avaient fait. La reconnaissance officielle
du Congrès des États-Unis n'est intervenue qu'en 2000 et 2001, alors que la plupart
étaient morts.
Le même peuple avait, une génération plus tôt, vu ses enfants punis dans les pensionnats
fédéraux pour avoir parlé cette langue.
**Q19.** L'histoire de Joe Kieyoomia est l'expérience décisive. Un locuteur natif, aux
mains de l'adversaire, ne peut pas lire les messages. **Qu'est-ce que cela prouve
exactement sur la source de la sécurité du système ?**
**Q20.** Si les code talkers s'étaient contentés de parler navajo en clair, sans
dictionnaire de code, que se serait-il passé lors de la capture de Kieyoomia ?
---
## Partie 5 : Le principe de Kerckhoffs
Vous avez attaqué trois protections :
| Fichier | Protection | Ce qui l'a fait tomber |
|---|---|---|
| 1 | un algorithme tenu secret | l'analyse de fréquences, en quelques minutes |
| 2 | un algorithme public, une clé faible | la force brute, 17 576 essais |
| 3 | une langue rare *et* un dictionnaire de code | rien — jusqu'à ce qu'on vous donne le lexique |
**Q21.** En 1883, le cryptographe néerlandais **Auguste Kerckhoffs** énonce un principe
qui gouverne encore toute la cryptographie moderne. À partir du tableau ci-dessus,
essayez de le formuler vous-même : sur quoi la sécurité d'un système doit-elle reposer,
et sur quoi ne doit-elle **jamais** reposer ?
**Q22.** On appelle **sécurité par l'obscurité** le fait de compter sur le secret du
fonctionnement d'un système plutôt que sur celui d'une clé. Lequel de vos trois fichiers
relevait de l'obscurité pure ?
**Q23.** Relisez la section 3 du cours, consacrée à l'AES. Les spécifications de l'AES
sont **entièrement publiques** : n'importe qui peut lire l'algorithme, le programmer,
le tester. Le cours indique qu'à ce jour la meilleure attaque connue reste la force
brute sur 2<sup>256</sup> clés.
En quoi cette publicité est-elle une **force** et non une faiblesse ? Que se passerait-il
si un algorithme secret contenait un défaut ?
**Q24.** Une entreprise vous propose son logiciel de messagerie en affirmant :
*« nos communications sont inviolables, car nous utilisons un algorithme de chiffrement
propriétaire que nous avons développé nous-mêmes et que nous ne divulguons pas. »*
Rédigez en cinq lignes ce que vous répondez.
**Q25.** Le troisième fichier avait une vraie clé — le dictionnaire de code — et il a
résisté. Pourtant, ce système n'aurait aucune valeur aujourd'hui. **Pourquoi ?**
*(Pensez à ce qui se passe si la clé est perdue, capturée, ou si un seul opérateur
la divulgue. Comparez avec l'AES, où changer de clé prend une seconde.)*
---
## Partie 6 : L'épisode, et la série
*Pour la culture. Rien à rendre.*
**« Anasazi »** est le vingt-cinquième et dernier épisode de la deuxième saison de
*X-Files* (*The X-Files*), diffusé le 19 mai 1995. Il est réalisé par R. W. Goodwin,
sur une histoire de Chris Carter — le créateur de la série — et de David Duchovny,
l'interprète de l'agent Mulder.
*X-Files* raconte l'enquête de deux agents du FBI sur des affaires non résolues :
**Fox Mulder**, convaincu de l'existence d'une dissimulation gouvernementale, et
**Dana Scully**, médecin de formation, chargée à l'origine de contrôler son travail par
la rigueur scientifique. La série a construit son identité sur cette tension entre
l'intuition et la preuve — les deux personnages ayant tour à tour raison.
Dans l'épisode, un hacker surnommé **le Penseur** (Kenneth Soona) extrait des serveurs
du ministère de la Défense un ensemble de fichiers classifiés et les remet à Mulder sur
une bande numérique. Les fichiers sont illisibles. C'est **Scully** qui identifie la
raison : le contenu n'est pas chiffré au sens informatique, il est rédigé en **navajo**.
Un ancien du peuple navajo, **Albert Hosteen** — interprété par Floyd « Red Crow »
Westerman, acteur et musicien dakota — entreprend de les traduire.
Le titre renvoie aux **Anasazis**, peuple du sud-ouest américain dont les cités furent
abandonnées vers le XIII<sup>e</sup> siècle, et dont la disparition reste discutée.
Le nom, d'origine navajo, est aujourd'hui contesté : les descendants pueblos lui
préfèrent l'appellation *Ancestral Puebloans*.
L'épisode est le premier volet d'un triptyque qui se poursuit dans la saison 3 avec
*The Blessing Way* et *Paper Clip*, et se termine sur un des cliffhangers les plus
célèbres de la série.
**Ce que l'épisode arrange.** Vous êtes maintenant mieux informé·e que le scénario :
la série présente le navajo comme un chiffrement à lui seul, alors que le vrai système
combinait la langue **et** un dictionnaire de code appris par cœur. La nuance n'est pas
mineure — c'est précisément elle qui sépare la sécurité par l'obscurité d'une véritable
cryptographie, et c'est tout l'objet de ce TP.
Une remarque, enfin. La série s'est emparée d'une histoire réelle, et le fait que des
lycéens français la découvrent trente ans plus tard par une série de science-fiction en
dit long sur la façon dont elle a été traitée : classifiée vingt-trois ans, reconnue
plus d'un demi-siècle après les faits.
---
## Questions de réflexion
**1.** En partie 1, l'auteur du message écarte explicitement les systèmes du ministère
*parce que* leurs spécifications sont publiques. En quoi ce raisonnement inverse-t-il
exactement le principe de Kerckhoffs ?
**2.** La force brute de la partie 2 a demandé 17 576 essais. Combien en faudrait-il
pour une clé de 8 lettres majuscules ? Et de 12 ? *(Une machine teste environ un milliard
de clés par seconde.)* Concluez sur ce qui détermine la solidité d'une clé.
**3.** Le chiffrement XOR est utilisé dans de vrais systèmes cryptographiques, alors même
que vous venez de le casser. Quelle condition faudrait-il respecter sur la clé pour
qu'un chiffrement XOR devienne **incassable** ? *(Cherchez « masque jetable ».)*
Pourquoi cette condition est-elle presque impossible à tenir en pratique ?
**4.** Le dictionnaire des code talkers a été appris par cœur et jamais écrit ni emporté
au combat. En termes modernes, quel problème de sécurité cette décision résolvait-elle ?
---
## Barème indicatif
| Partie | Points |
|--------|--------|
| Partie 1 : analyse de fréquences | 6 |
| Partie 2 : XOR et force brute | 5 |
| Partie 3 : le fichier qui résiste | 3 |
| Partie 4 : lecture historique (Q19, Q20) | 2 |
| Partie 5 : principe de Kerckhoffs | 4 |
| **Total** | **20** |
---
## Sources
- *Navajo Code Talkers' Dictionary*, révision du 15 juin 1945, déclassifié sous
DoD Directive 5200.9 — [Naval History and Heritage Command](https://www.history.navy.mil/research/library/online-reading-room/title-list-alphabetically/n/code-talkers.html)
- « Semper Fidelis, Code Talkers », *Prologue*, [National Archives](https://www.archives.gov/publications/prologue/2001/winter/navajo-code-talkers.html)
- [Joe Kieyoomia](https://en.wikipedia.org/wiki/Joe_Kieyoomia) — Wikipédia
- [Anasazi (The X-Files)](https://en.wikipedia.org/wiki/Anasazi_(The_X-Files)) — Wikipédia
---
Auteur : Florian Mathieu
Licence CC BY NC
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.