rtfm
/ 8chan / éditeur
Enregistrer
Annuler
# Théorie : comprendre les fondations de Jiyu > Ce document explique la théorie derrière chaque solution technique choisie dans > [implementation.md](./implementation.md) : les acronymes, les concepts, et le > pourquoi des choses. Il suit le même découpage en briques. C'est un document > d'apprentissage, pas une référence normative. --- ## Brique 1 : la cryptographie de base ### Les trois familles d'outils crypto Toute la crypto du protocole se range dans trois familles, et il faut les distinguer parce qu'elles ne protègent pas contre la même chose : - **Signer** : prouver qui a écrit quoi. Ne cache rien, authentifie. - **Chiffrer** : cacher le contenu. Ne prouve pas qui écrit (c'est l'AEAD qui combine les deux, voir plus bas). - **Dériver** : fabriquer plusieurs clés à partir d'un secret, de façon déterministe et à sens unique. ### Ed25519 : les signatures Une **signature numérique** fonctionne avec une paire de clés : la clé privée signe, la clé publique vérifie. Quiconque a ta clé publique peut vérifier que c'est bien toi qui as signé, personne ne peut signer à ta place sans la privée. **Ed25519** est un algorithme de signature sur **courbes elliptiques**. L'idée des courbes elliptiques, sans les maths : ce sont des objets mathématiques où il est facile de calculer dans un sens (clé privée → clé publique) et pratiquement impossible dans l'autre. L'avantage sur l'ancien standard RSA : des clés de 32 octets et des signatures de 64 octets au lieu de plusieurs centaines, et des calculs plus rapides. Sur nos transports lents, ces 64 octets par post comptent. ### X25519, KEM, et l'accord de clés Problème fondamental : comment deux personnes qui ne se sont jamais parlé établissent-elles un secret commun, alors que tout le monde écoute le canal ? - **X25519** est un **Diffie-Hellman** sur courbe elliptique : chacun envoie sa clé publique, chacun combine sa privée avec la publique de l'autre, et les deux aboutissent au même secret sans jamais l'avoir transmis. C'est magique et c'est prouvé depuis 1976. - Un **KEM** (Key Encapsulation Mechanism) est la version moderne et généralisée : tu prends la clé publique de l'autre, tu "encapsules" un secret dedans, tu envoies la capsule ; seul le détenteur de la clé privée peut l'ouvrir. ### Post-quantique, ML-KEM et X-Wing Un ordinateur quantique suffisamment grand casserait X25519 et Ed25519 (l'algorithme de Shor résout le problème mathématique sous-jacent). Il n'existe pas encore, mais : - **La menace "harvest now, decrypt later"** : un adversaire enregistre ton trafic chiffré aujourd'hui et le déchiffrera dans dix ans. C'est pour ça que l'accord de clés doit être post-quantique dès maintenant : le secret établi aujourd'hui protège des messages qui doivent rester secrets longtemps. - Les **signatures** ne craignent rien aujourd'hui : forger une signature exige l'ordinateur quantique au moment de la forge, pas après coup. D'où Ed25519 conservé. - **ML-KEM** (Module-Lattice KEM, ex-Kyber, standardisé par le NIST sous FIPS 203) est un KEM fondé sur les **réseaux euclidiens** (lattices), un problème mathématique que les ordinateurs quantiques ne savent pas résoudre. - **X-Wing** est un **hybride** : X25519 + ML-KEM-768 combinés. Pour casser le secret, il faut casser LES DEUX. On se protège ainsi contre les deux risques : l'ordinateur quantique (qui casserait X25519 seul) et une faille découverte dans les maths jeunes de ML-KEM (qui casserait ML-KEM seul). ### AEAD et ChaCha20-Poly1305 **AEAD** = Authenticated Encryption with Associated Data. C'est le chiffrement moderne : il cache le contenu ET garantit qu'il n'a pas été modifié en route (un chiffrement sans authentification est vulnérable à des attaques par modification). **ChaCha20** fait le chiffrement, **Poly1305** l'authentification. On le choisit plutôt qu'AES parce qu'AES n'est rapide que grâce à des instructions matérielles dédiées, absentes en WebAssembly ; ChaCha20 est rapide et sûr en pur logiciel. ### KDF, HKDF, et la dérivation Une **KDF** (Key Derivation Function) fabrique des clés à partir d'un secret. C'est une fonction à sens unique : de la clé dérivée, impossible de remonter au secret. **HKDF** (RFC 5869) est la KDF standard, bâtie sur HMAC-SHA256. On lui donne un secret + une étiquette de contexte ("tag-epoque-42", "pseudonyme-place-X") et elle sort une clé propre à ce contexte. C'est elle qui fabrique : - les **tags d'époque** (pseudonymes tournants des places), - les **pseudonymes par place** (dérivés de l'identité maîtresse + ID de place : stable dans la place, incorrélable entre places), - les clés de message à partir du secret de groupe. ### Le ratchet symétrique et la forward secrecy La **forward secrecy** (confidentialité persistante) : si on te vole tes clés aujourd'hui, le trafic d'hier doit rester indéchiffrable. Le mécanisme : le **ratchet** (cliquet). La clé avance en sens unique, `clé_suivante = HKDF(clé_actuelle)`, et on efface les anciennes au fur et à mesure. Comme HKDF est à sens unique, posséder la clé du jour ne permet pas de recalculer celle d'hier. Le mot "cliquet" dit tout : ça tourne dans un sens, jamais dans l'autre. Chez Jiyu, ce cliquet opère au niveau des **générations** de clés de groupe (une génération par changement de membres ou rafraîchissement, brique 3), pas message par message : puisque nos axiomes remettent l'historique intégral aux nouveaux membres, les secrets passés sont conservés par conception, et c'est l'exclusion (nouvelle génération que l'exclu n'a pas) qui matérialise la protection. À l'intérieur d'une génération, chaque message a sa clé propre, dérivée par compteur. ### BLAKE3 et les hashs Un **hash** est une empreinte : n'importe quelle donnée → 32 octets, déterministe, impossible à inverser, impossible (en pratique) de trouver deux données avec la même empreinte. Usages chez nous : identifier un contenu (l'ID d'un post EST son hash) et chaîner des blocs (chaque bloc contient le hash du précédent : modifier l'histoire casse toute la chaîne). **BLAKE3** est un hash moderne, beaucoup plus rapide que SHA-256 en logiciel, ce qui compte sur mobile en WASM. --- ## Brique 2 : le log répliqué ### Append-only, DAG, et pourquoi pas une base de données Notre structure de données fondamentale est un **log append-only** : on ajoute des événements (post, réaction, édition), on ne modifie jamais rien. La "suppression" est un nouvel événement (tombstone) qui dit "considérez ceci comme effacé". Pourquoi : dans un système distribué sans serveur, la modification en place crée des conflits insolubles ; l'ajout pur fusionne trivialement (l'union de deux ensembles d'événements est toujours bien définie). **DAG** = Directed Acyclic Graph, graphe orienté sans cycle. Chaque entrée référence ses parents (les dernières entrées connues au moment d'écrire). Quand deux personnes écrivent en parallèle sans se voir (partition réseau), le graphe fourche ; quand elles se resynchronisent, les deux branches coexistent dans le DAG et sont fusionnées par le tri. Git fonctionne exactement comme ça. ### Les horloges de Lamport Problème : sans serveur central, pas d'horloge de référence, et les horloges des téléphones mentent. Comment ordonner les messages ? **L'horloge de Lamport** (1978) est un compteur logique : chaque auteur incrémente son compteur à chaque message, et le règle au max de ce qu'il a vu + 1. Résultat : un ordre partiel causal (si j'ai vu ton message avant d'écrire le mien, le mien a un numéro plus grand). Pour départager les égalités (deux messages avec le même numéro écrits en parallèle), on compare les clés publiques des auteurs : arbitraire mais déterministe, tout le monde calcule le même ordre. C'est un **CRDT** au sens large : une structure dont la fusion est commutative, associative et idempotente, donc tous les pairs convergent vers le même état quel que soit l'ordre de réception. ### La synchronisation : vecteurs de frontière et RBSR Deux pairs se retrouvent : comment savoir quoi s'échanger sans tout renvoyer ? - **Vecteur de frontière** (le mécanisme de Scuttlebutt) : comme chaque auteur numérote ses messages, "tout ce que je possède" se résume en une liste `{auteur → dernier numéro vu}`. On échange les listes, on compare, chacun sait exactement ce qui manque à l'autre. Un aller-retour, quelques octets par auteur. - **RBSR** (Range-Based Set Reconciliation) : pour les cas où le vecteur ne marche pas (logs troués par la rétention partielle). Les deux pairs voient leurs logs comme des ensembles triés et échangent des **empreintes par plage** (le hash agrégé de "tout ce que j'ai entre janvier et mars"). Empreintes égales : plage identique, on passe. Différentes : on coupe la plage en deux et on recommence. Convergence logarithmique, comme une recherche dichotomique sur les différences. --- ## Brique 3 : les clés de groupe ### Le problème du chiffrement de groupe Chiffrer pour une personne, c'est facile (son KEM). Chiffrer pour un groupe de 10 000 personnes dont la composition change, c'est le problème dur : à chaque exclusion il faut une nouvelle clé de groupe distribuée à tous SAUF l'exclu. Naïvement : chiffrer la nouvelle clé vers chacun des 9 999 restants, un par un. Intenable. ### TreeKEM : l'arbre qui rend ça logarithmique **TreeKEM** organise les membres en arbre binaire : chaque membre est une feuille, chaque nœud interne porte une clé connue de tout son sous-arbre. La clé racine est la clé de groupe. Quand un membre change ou part, seul le **chemin de sa feuille à la racine** doit être re-clé : log₂(N) nœuds, soit ~14 opérations pour 10 000 membres au lieu de 10 000. C'est LE mécanisme qui rend les grands groupes chiffrés possibles. ### MLS, et pourquoi on ne l'utilise pas **MLS** (Messaging Layer Security, RFC 9420) est le standard IETF qui industrialise TreeKEM. Mais il a une exigence cachée : tous les membres doivent traiter les changements de groupe **dans le même ordre total, immédiatement** ; deux opérations concurrentes non ordonnées produisent deux arbres incompatibles. MLS délègue cet ordonnancement à un serveur. Notre réseau, fait de partitions et de store-and-forward, ne peut pas fournir ça, et la recherche a montré (papier FREEK, CRYPTO 2023) que rafistoler MLS pour tolérer les fourches est un vrai sujet scientifique, pas un patch. ### La CGKA à ordre causal, notre voie La bonne famille d'outils pour nous s'appelle la **CGKA à ordre causal** (lignée DCGKA, Weidner/Kleppmann) : les opérations de groupe s'appliquent **dès leur réception, dans l'ordre causal** (celui que notre DAG fournit déjà), et les opérations concurrentes fusionnent nativement au lieu de casser l'arbre. Deux conséquences directes : plus besoin d'attendre un quorum pour qu'une exclusion coupe l'accès de l'exclu (l'exclusion est transparente pour les autres membres), et les partitions ne sont plus un cas d'erreur mais le régime normal. Notre moteur v1 est **BeeKEM** (projet Keyhive d'Ink & Switch, le labo derrière Automerge) : un TreeKEM qui a appris la concurrence : divergence arbitraire entre répliques, coût logarithmique conservé, les conflits d'updates concurrents laissent des "clés multiples" sur les nœuds de l'arbre, résorbées à l'update suivant. C'est une crypto de recherche (papier récent, pas encore d'audit) : choix assumé pour l'échelle, avec un repli désigné, `p2panda-encryption` (implémentation du DCGKA, papier peer-reviewé, trajectoire d'audit), derrière la même interface. Le **registre** (brique 4) reste dans la boucle mais change de rôle : il n'ordonne plus les clés, il les **autorise** : chaque opération de clés doit pointer l'opération de gouvernance qui la justifie (l'exclusion, le join...). Si la gouvernance invalide après coup une opération déjà appliquée, on répare par **compensation** (ré-ajouter l'exclu à tort, avec les secrets qu'il a manqués), jamais par retour arrière. --- ## Brique 4 : le registre de gouvernance ### La chaîne de hashs Chaque opération de gouvernance (transfert de tokens, exclusion...) est un **bloc signé** contenant le hash du bloc précédent. Conséquence : impossible de réécrire l'histoire sans que tout le monde le voie (changer un vieux bloc change son hash, donc casse tous les suivants). C'est la structure de Git et de toutes les blockchains, et elle ne vaut que ce que vaut la règle qui dit quel bloc est accepté. ### Quorum pondéré et finalité Notre règle : un bloc devient **final** quand des détenteurs représentant plus de 50 % des tokens en circulation l'ont **contre-signé**. Le paquet bloc + signatures s'appelle un **certificat de quorum** : n'importe qui peut vérifier, hors ligne, que le quorum a bien été atteint (les signatures sont là, les poids se calculent). Pas de mineurs, pas de course : les validateurs SONT les détenteurs, et la finalité s'accumule de façon asynchrone (les contre-signatures arrivent quand les gens se connectent). Contresigner n'est pas approuver : c'est attester la validité, et les clients le font automatiquement pour tout bloc valide qu'ils voient : la finalité avance à la vitesse de propagation. ### Fourches, double-spend, et pourquoi ce n'est pas une cryptomonnaie Un **double-spend** : Eve signe deux blocs contradictoires (envoyer les mêmes tokens à Alice dans un bloc, à Bob dans l'autre) et les diffuse dans deux partitions. À la fusion, les deux blocs signés par la même clé avec le même parent constituent une **fourche** : preuve mécanique de triche, résolue par la règle "premier finalisé gagne". Ce qui nous évite toute la machinerie des cryptomonnaies : nos tokens n'ont aucune valeur hors de leur place (pas de motivation économique au vol), les validateurs sont connus (pas de problème Sybil, pas de proof-of-work), et chaque place a sa chaîne (pas de consensus mondial). Il reste ~500-1000 lignes de règles de validation déterministes, la partie qu'on spécifie formellement et qu'on audite. ### La dormance Piège du quorum pondéré : si un détenteur de 40 % disparaît (téléphone perdu, plus de backup), plus aucun quorum de 50 % n'est possible, la gouvernance gèle à vie. Solution : un détenteur muet depuis 90 jours sort du **dénominateur** du calcul (ses tokens ne comptent plus dans le "total en circulation" tant qu'il ne se manifeste pas). Il ne perd rien : sa première signature le réintègre. Précédent : l'"inactivity leak" d'Ethereum répond au même problème. --- ## Brique 5 : le réseau ### Bundles vs streams, et le DTN Deux visions du réseau : le **stream** (un tuyau continu entre deux machines en ligne, TCP, WebSocket) et le **bundle** (un paquet autonome qui se débrouille, stocké, transporté, retransmis). Le monde des streams suppose la connexion ; notre monde (BLE en rafales, ultrason lent, courier qui prend le métro avec les données) est celui du **DTN** (Delay-Tolerant Networking), né chez la NASA pour l'interplanétaire : les deux extrémités ne sont jamais en ligne en même temps, le réseau EST le stockage intermédiaire. D'où notre abstraction : tout est bundle, et les transports à connexion (Internet) font passer des bundles dans leurs streams (trivial), jamais l'inverse (impossible proprement). ### Le pub/sub par tags **Pub/sub** (publish/subscribe) : plutôt que d'adresser des machines, on s'abonne à des sujets. Notre sujet est le **tag d'époque** d'une place : opaque pour les non-membres, recalculable par les membres. Chaque node annonce à ses voisins "je porte / je cherche ces tags", et les bundles suivent ces gradients d'abonnement. C'est du routage par centres d'intérêt, pas par adresses : personne n'a besoin de savoir où est qui. ### NAT traversal : STUN, TURN, hole punching Sur Internet, ton téléphone n'a pas d'adresse publique : il est derrière un **NAT** (le routeur qui partage une IP entre tous les appareils). Deux téléphones derrière deux NAT ne peuvent pas se joindre directement sans aide : - **STUN** : un serveur qui te dit "vu de l'extérieur, tu es telle IP:port". Léger, il n'achemine rien. - **Hole punching** : les deux pairs, connaissant leurs adresses vues de l'extérieur, s'envoient des paquets simultanément ; les NAT, croyant à des réponses, laissent passer. Marche dans la majorité des cas. - **TURN** : quand rien ne marche, un serveur relaie le trafic (coûteux, dernier recours). **WebRTC** empaquette tout ça pour le navigateur (c'est sa raison d'être), et **libp2p** le fait pour le natif (AutoNAT, DCUtR). C'est toute la valeur qu'on tire de libp2p : ce plombing pénible et éprouvé. ### DHT Une **DHT** (Distributed Hash Table) est un annuaire sans serveur : chaque clé (chez nous : un tag d'époque) est stockée par les quelques nœuds dont l'ID est le plus "proche" de la clé (proximité mathématique, XOR pour Kademlia). Pour publier ou chercher, on navigue de proche en proche vers la bonne zone, en log(N) sauts. C'est le rendez-vous de phase 2 : "qui est joignable pour le tag T ?" sans serveur central. --- ## Brique 6 : le stockage et les clés locales ### IndexedDB et OPFS Les deux stockages du navigateur : **IndexedDB** est une base clé-valeur transactionnelle (bien pour l'état, les métadonnées), **OPFS** (Origin Private File System) est un vrai système de fichiers privé, avec accès synchrone rapide depuis un worker (bien pour les tranches du log, gros et séquentiel). ### Passkeys, WebAuthn et l'extension PRF **WebAuthn** est le standard d'authentification par clé matérielle : la clé privée vit dans le **Secure Enclave** (iPhone) ou équivalent (une puce dédiée dont les clés ne sortent jamais, déverrouillée par biométrie). Une **passkey** en est l'usage grand public. L'extension **PRF** (Pseudo-Random Function) ajoute la pièce qui nous sert : la passkey peut dériver un secret symétrique stable. Résultat : "Face ID → secret → déchiffrement de la graine locale". La graine chiffrée dort dans IndexedDB, la clé qui l'ouvre dort dans le matériel, gardée par ton visage. --- ## Brique 7 : la sérialisation ### Le problème de la canonicité Une signature porte sur des octets exacts. Si deux implémentations sérialisent le même objet avec un octet de différence (ordre des champs, espaces, encodage d'un entier), la signature de l'une est invalide chez l'autre. Deux écoles : forcer un encodage canonique (fragile, Scuttlebutt s'y est brûlé), ou notre règle : **les octets signés sont opaques et voyagent verbatim**, on ne re-sérialise jamais ce qui est signé. Le problème disparaît à la racine. ### CBOR et CDDL **CBOR** (RFC 8949) est un format binaire auto-décrit : comme JSON mais compact et binaire ; les données portent leur structure, un décodeur peut sauter les champs qu'il ne connaît pas (c'est ce qui permet aux vieux octets de rester lisibles pour toujours, et aux nouveaux champs d'apparaître sans casser les vieux clients). **CDDL** (RFC 8610) est son langage de schéma : on décrit chaque format dans un fichier lisible et vérifiable mécaniquement, qui devient une pièce de la spec. --- ## Brique 8 : le runtime ### Le pattern sans-I/O Une machine à états pure : le moteur ne touche ni au réseau, ni au disque, ni à l'horloge. On lui donne "voici ce qui est arrivé, voici l'heure", il répond "voici quoi émettre, voici quoi écrire". Tout ce qui est réel (sockets, fichiers, timers) vit dans des **drivers** par plateforme. Deux conséquences majeures : le même moteur tourne partout à l'octet près, et on peut **simuler un réseau entier dans un test** (50 pairs, partitions, fusions, en accéléré, reproductible). C'est le pattern des implémentations sérieuses de protocoles en Rust (Quinn pour QUIC, str0m pour WebRTC). ### WASM, workers et SharedArrayBuffer **WebAssembly** exécute notre Rust dans le navigateur, mais dans un modèle mono-thread par défaut. Les **Web Workers** sont les threads du web : isolés, communiquant par messages. Le **SharedArrayBuffer** serait la mémoire réellement partagée entre eux ; on s'en passe parce qu'il exige des en-têtes serveur spéciaux qui limiteraient qui peut héberger un miroir de la PWA (axiome de résistance à la censure), et que nos flux (petits messages) ne le justifient pas. --- ## Brique 9 : le modem ultrasonore ### Moduler : transformer des octets en son Un modem (modulateur-démodulateur) traduit des bits en signal physique et retour. **FSK** (Frequency-Shift Keying) : chaque symbole est représenté par une fréquence (un sifflet aigu = 1, un plus grave = 0, généralisé à une grille de fréquences pour plusieurs bits par symbole). Le schéma ggwave émet 6 tonalités simultanées dans la bande 18-20 kHz (inaudible aux adultes), chacune codant 4 bits. Robuste et simple : c'est notre mode par défaut. ### FFT : lire les fréquences La **FFT** (Fast Fourier Transform) décompose un signal en ses fréquences : on lui donne 20 ms de micro, elle répond "il y a de l'énergie à 18 200 Hz et 19 400 Hz". Le décodage FSK est alors une détection de pics : quelles fréquences de la grille sont allumées → quels bits. ### Reed-Solomon : survivre aux erreurs Le canal acoustique est sale (échos, bruits, absorption). **Reed-Solomon** est un code correcteur : on ajoute de la redondance calculée aux données, et le décodeur peut reconstruire les symboles perdus ou corrompus (jusqu'à un certain taux). C'est le code des CD, des QR codes et de l'espace lointain : à chaque fois le même problème, un canal qu'on ne peut pas nettoyer, donc des données qui se réparent. ### FDD : le full-duplex par fréquences **FDD** (Frequency-Division Duplexing) : les deux pairs parlent en même temps, sur des sous-bandes disjointes (A émet en 18-19 kHz, écoute en 19,5-20,5 ; B l'inverse). Le défi : ton propre haut-parleur crie dans ton micro bien plus fort que le signal distant (problème "near-far"), d'où filtres raides et bandes de garde. Le mode cohérent ajoute l'**égalisation adaptative** : un filtre qui apprend en continu les déformations du canal (échos de la pièce) et les annule, ce qui permet des modulations plus denses et le 1-4 kbit/s. --- ## Le nommage : triangle de Zooko et petnames ### Le triangle de Zooko Un système de noms voudrait trois propriétés : **global** (le nom désigne la même chose pour tout le monde), **sécurisé** (personne ne peut s'approprier le nom d'un autre), **mémorisable** (un humain peut le retenir). La conjecture de Zooko (2001) : on ne peut en avoir que deux à la fois. Une clé publique est globale et sécurisée mais imprononçable ; "alex" est mémorisable mais ni global ni sécurisé ; un annuaire central donne les trois... au prix d'une autorité centrale, interdite chez nous. Les systèmes qui prétendent tricher dans une seule couche de nom (pseudo unique + discriminateur + règles d'unicité) accumulent des rustines : c'est le chemin qu'on a d'abord pris, puis abandonné. ### La solution : superposer les couches (modèle petname, Stiegler 2005) Au lieu d'un nom qui fait tout, quatre objets qui font chacun deux sommets du triangle : - **La clé** (`pseudo_pk`) : globale + sécurisée. La seule identité du protocole. - **La représentation de clé** : un indice calculé depuis la clé (chiffres d'un hash, identicon). Globale + sécurisée aussi (n'importe qui peut la recalculer, personne ne peut la forger), et *à moitié* mémorisable : elle rend la clé comparable d'un coup d'œil. - **Le nom allégué** (alleged name) : ce que quelqu'un *affirme* : "appelez-moi alex". Mémorisable, mais ni global ni sécurisé : c'est une suggestion venue du réseau, affichée comme telle. Notre entrée `profile` est exactement ça, et le protocole ne lui donne aucune sémantique : c'est du contenu ordinaire. - **Le petname** : le nom que TOI tu assignes à une clé dans TA table locale ("Maman", "Alex du club"). Mémorisable + sécurisé, non global : il n'existe que chez toi. Un chat s'appelle Garfield parce que *tu* l'appelles Garfield ; d'autres chats s'appellent Garfield ailleurs, mais un seul dans ta maison. La sécurité vient de la localité : un imposteur peut alléguer n'importe quoi, il ne peut pas écrire dans ta table. C'est le principe du carnet d'adresses érigé en mécanisme de sécurité, et c'est ce que fait Signal en production (noms de profil non uniques + renommage local + alertes d'homonymie). L'usurpation se combat dans la couche de perception : le protocole garantit les clés, jamais les noms. ## Brique 10 : backup et multi-device ### Argon2, scrypt : les KDF "mémoire-dures" Dériver une clé d'une passphrase avec un hash rapide est une erreur : un attaquant essaie des milliards de passphrases par seconde sur GPU. Les KDF **mémoire-dures** (Argon2, scrypt, ce dernier étant celui du format age) rendent chaque essai volontairement coûteux en mémoire ET en temps : le brute-force devient hors de prix. C'est la différence entre "ta passphrase doit être imprononçable" et "une bonne passphrase suffit". ### Le format age **age** est un format standard de chiffrement de fichiers, conçu pour remplacer GPG en plus simple. Ce qu'on lui prend : le chiffrement **par flux en tranches** (un backup de 2 Go se chiffre et se déchiffre sans tenir en mémoire, et une corruption locale ne détruit pas tout), le mode passphrase avec scrypt intégré, et l'interopérabilité (n'importe quel outil age ouvre le fichier, si on a la passphrase). ### BIP-39 : la graine en mots **BIP-39** transforme des octets aléatoires en une phrase de mots choisis dans une liste de 2048 (chaque mot code 11 bits) : `velours cactus horizon...`. Inventé pour les wallets Bitcoin, adopté partout parce que des mots se notent sur papier sans erreur de recopie (la liste est conçue pour que les mots soient non ambigus). C'est la forme papier de notre graine d'identité. ### Certificats d'appareils Une **chaîne de confiance** en miniature : l'identité maîtresse signe la clé de chaque appareil ("cet appareil est à moi"), et les places ne voient que des appareils certifiés. Révoquer un appareil volé = publier un bloc de révocation ; les places éjectent sa feuille MLS à la rotation suivante (avancée à maintenant), l'identité elle-même n'est pas compromise. C'est le modèle de Signal et de tous les systèmes multi-device sérieux : l'identité est une racine qui délègue, jamais une clé qui se promène.