Un algorithme parfait implémenté incorrectement est, tout simplement, non sécurisé.
Kyber est sécurisé. Les mathématiques sont publiées, révisées par les pairs, analysées pendant des années. Les paramètres sont choisis avec des marges conservatrices. La structure Module-LWE est élégante et solide.
Mais Kyber ne vit pas sur du papier. Il vit dans du code. Et le code a un problème que les équations ne connaissent pas : le temps n'est pas uniforme.
Le temps comme oracle
Les attaques de temporisation — timing attacks — exploitent une divergence fondamentale entre le modèle mathématique et la machine réelle. Dans le modèle, une opération comme x + y prend "une unité de temps". Dans la machine réelle, x + y peut prendre des microsecondes différentes selon les valeurs de x et y, selon l'état du cache, selon la prédiction de branchement du processeur.
Pour la cryptographie, c'est une catastrophe : si le temps de déchiffrement dépend du secret, l'attaquant peut mesurer le temps et récupérer le secret.
// Exemple illustratif : une comparaison NON constante dans le temps
bool comparer(List<int> a, List<int> b) {
if (a.length != b.length) return false;
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]) return false; // early exit : le temps dépend de l'endroit où ça échoue
}
return true;
}
Cette fonction retourne false dès qu'elle trouve une divergence. Si le premier byte échoue, elle prend peu de temps. Si le dernier échoue, elle prend plus de temps. Un attaquant qui peut mesurer le temps de cette comparaison peut déduire combien de bytes il a réussis, et ainsi briser la sécurité byte par byte.
Flutter et la promesse brisée
Dart est un langage qui ne garantit pas un temps constant au niveau de la VM. Il n'y a pas de @ConstantTime ni d'attribut du compilateur qui assure qu'une opération prendra le même temps indépendamment de ses opérandes.
Problème : Dart VM → sans garanties de temps constant
Contexte : Flutter pour applications mobiles multiplateformes
Risques concrets lors de l'implémentation de Kyber en Dart pur :
1. Comparaison de ciphertexts → timing du FO transform (l'étape la plus critique)
2. Décodage de polynômes → timing de Compress/Decompress
3. NTT (Number Theoretic Transform) → accès aux tables selon l'indice secret
4. Échantillonnage CBD → branchement selon les bits du secret
5. Désérialisation de clés → longueur implicite ou padding variable
Chacun de ces points est un vecteur d'attaque. Non pas parce que Kyber est faible — les équations sont correctes — mais parce que l'implémentation en Dart filtre des informations à travers le temps.
Le problème n'est pas exclusif à Dart. Tout langage sans contrôle fin sur le temps d'exécution — JavaScript, Python, Java sans précautions extrêmes — souffre du même problème. La différence est que Flutter/Dart est de plus en plus utilisé pour des applications qui nécessitent de la cryptographie (Signal, applications financières, messagerie chiffrée), et la tentation "d'écrire Kyber en Dart pur, après tout, c'est post-quantique" est grande.
Borges a imaginé un empire où les cartographes créèrent une carte si exacte qu'elle coïncidait point par point avec le territoire, jusqu'à devenir inutile. En cryptographie, c'est l'inverse : le paper est la carte parfaite — chaque opération définie, chaque paramètre justifié, chaque étape vérifiée — et l'implémentation est le territoire, qui ne coïncide jamais tout à fait avec la carte. Entre le papier et la machine, il y a un espace qu'aucun théorème ne peut combler.
Je l'ai vérifié par moi-même. Pendant ma phase d'apprentissage, j'ai implémenté Kyber en Dart/Flutter — xkyber_crypto — en suivant FIPS 203 à la lettre : NTT, CBD, FO transform, Compress/Decompress. Les tests boîte noire passaient. Les vecteurs de test de la spécification coïncidaient byte à byte. L'implémentation était mathématiquement correcte. Et pourtant, elle était cryptographiquement insoutenable.
Le papier suppose un modèle idéal où chaque instruction coûte le même temps. Le territoire — la VM de Dart, le compilateur JIT, la hiérarchie de cache du processeur — ne fait pas cette supposition. Le papier ne mentionne pas que l'accès à une table NTT selon un indice dérivé du secret peut fuiter le secret. Le papier ne sait pas ce qu'est un cache.
Sartre a dit que l'enfer, c'est les autres. Pour le papier de Kyber, les autres sont le monde physique dans lequel il doit s'exécuter : la RAM, le ramasse-miettes, le prédicteur de branchement, la VM qui réordonne les instructions sans demander la permission. Le dépôt est archivé depuis novembre 2025 comme témoignage que la distance entre la carte et le territoire ne peut pas toujours être parcourue.
La différence entre la carte et le territoire
La recherche sur l'implémentation de Kyber documente avec précision les optimisations nécessaires pour que le code soit constant dans le temps : l'utilisation de la réduction de Montgomery au lieu de la division, l'absence de if dans les fonctions d'échantillonnage, l'accès séquentiel aux tables NTT sans dépendance de données secrètes.
Couche Ce qu'elle promet Ce qui peut défaillir
───── ─────────────── ────────────────
Mathématique Sécurité LWE Pas de défaut (correcte)
Algorithme FO transform CCA-secure Pas de défaut (correct)
Langage Expressivité Sans garanties de temps constant
CPU Exécution Cache, prédicteurs, pipeline
Chaque couche introduit de nouveaux risques. Un algorithme mathématiquement parfait, implémenté dans un langage qui ne garantit pas un temps constant, exécuté sur un CPU qui optimise dynamiquement : la sécurité promise par les équations s'infiltre par chaque interstice du matériel.
Sartre a écrit que "l'enfer, c'est les autres". En cryptographie, l'enfer, ce sont les autres couches : le compilateur qui réordonne les opérations, le cache qui filtre les accès, le ramasse-miettes qui introduit des pauses mesurables.
// Implémentation constante dans le temps (C) — chaque branche prend le même temps
uint8_t ct_compare(const uint8_t *a, const uint8_t *b, size_t len) {
uint8_t result = 0;
for (size_t i = 0; i < len; i++) {
result |= a[i] ^ b[i]; // XOR : pas de early exit
}
return result; // 0 si égaux, != 0 si différents
}
En C, cette fonction est constante dans le temps (en supposant que le compilateur ne l'optimise pas). En Dart, il n'y a aucun moyen de garantir que la VM compile cela comme une boucle sans branchement dépendant des données. La même logique produit des résultats de sécurité différents selon le langage.
Ce qui n'est pas dans le papier
Le papier de Kyber (Bos et al., 2018) décrit l'algorithme. Il ne décrit pas comment l'implémenter de manière sécurisée sur chaque plateforme. Il n'avertit pas qu'une comparaison naïve de ciphertexts en Dart peut fuiter la clé. Il ne mentionne pas que la VM de Dart peut introduire des variations de temps qui annulent la sécurité du FO transform.
Cette distance — entre le papier et le produit — est là où se produisent la plupart des vulnérabilités cryptographiques réelles. Pas dans les équations. Dans les décisions d'implémentation.
| Couche | Où le risque est-il documenté ? |
|---|---|
| Algorithme | Papier, FIPS 203 |
| Paramètres | Papier, FIPS 203 |
| Implémentation sécurisée en C | Référence de pq-crystals |
| Implémentation sécurisée en Rust | Bindings, enveloppes |
| Implémentation sécurisée en Dart | Aucune documentation officielle |
| Implémentation en Flutter | Aucune |
Ce n'est pas que Kyber ne puisse pas être implémenté de manière sécurisée en Dart. C'est que cela nécessite un niveau de soin — et de connaissance de la VM de Dart — qui n'est documenté nulle part. Chaque implémentation en Dart pur est, aujourd'hui, un pari.
Dans III : La limite de l'erreur, nous explorerons la frontière physique de la cryptographie : l'énergie nécessaire pour briser un schéma, la limite de Landauer, et pourquoi même Kyber — comme tout le reste — est destiné à tomber, même si ce n'est peut-être pas pour les raisons que nous attendons.
Références croisées avec la recherche :
- Implémentation — Détails de NTT, Compress/Decompress, FO transform
- Attaques — Attaques par canaux auxiliaires contre Kyber
- Paramètres de sécurité — Probabilité d'échec et marges
- Structure du KEM — Le FO transform et pourquoi la comparaison est critique
