# Pairing : Encodage de la clé publique dans les mots BIP32 **Author:** Équipe 4NK **Date:** 2026-01-28 **Version:** 1.0 ## Problème identifié ### Question initiale Si les mots BIP32 encodent l'UUID du pair, cela implique que : - Le pair a déjà été créé et publié sur un relais - Il faut récupérer le pair depuis le relais pour obtenir sa clé publique - **Mais lors du pairing initial, le pair n'existe pas encore sur le relais** ### Problème technique Il n'existe **pas de mécanisme** pour récupérer un pair par UUID sur un relais. Les relais permettent uniquement de : - Récupérer des messages par hash : `GET /messages/:hash` - Récupérer des messages par fenêtre temporelle : `GET /messages?start=&end=` Il n'y a pas d'endpoint `GET /pairs/:uuid` ou équivalent. ### Conséquence Si les mots encodent l'UUID du pair : 1. Le pair doit être publié sur un relais avant le pairing 2. Il faut un mécanisme pour le récupérer par UUID (qui n'existe pas) 3. Le pairing initial devient impossible sans publication préalable ## Solution implémentée ### Principe Les mots BIP32 encodent maintenant **directement la clé publique de l'identité** (66 hex = 33 bytes) au lieu de l'UUID du pair. ### Avantages - ✅ **Pas besoin de récupérer quoi que ce soit depuis un relais** - ✅ **La clé publique est disponible immédiatement** (elle fait partie de l'identité) - ✅ **Les mots peuvent être échangés directement** entre les deux devices - ✅ **La clé publique est stockée dans `PairConfig.publicKey`** et utilisée pour ECDH - ✅ **Le pairing initial fonctionne sans publication préalable** ### Format - **Clé publique** : 66 caractères hex (33 bytes) - **Encodage** : 17 mots BIP32 - 16 mots pour les 32 premiers bytes (2 bytes par mot) - 1 mot pour le dernier byte (33ème byte, padding avec 0) ## Modifications techniques ### Nouvelles fonctions (`userwallet/src/utils/bip32.ts`) ```typescript /** * Convert public key (hex, 66 chars) to BIP32 word list. * Public key is 33 bytes. Each word encodes 2 bytes (16 bits), so we need 17 words. * Last word encodes only 1 byte (the 33rd byte), so we pad with 0. */ export function publicKeyToBip32Words(publicKey: string): string[] /** * Convert BIP32 word list back to public key (hex, 66 chars). * Expects 17 words: 16 words for 32 bytes + 1 word for the last byte. */ export function bip32WordsToPublicKey(words: string[]): string | null ``` ### Modifications du pairing (`userwallet/src/utils/pairing.ts`) #### `createLocalPair()` **Avant :** - Génère un UUID - Encode l'UUID en mots BIP32 (8 mots) **Maintenant :** - Génère un UUID pour le pair - Encode la clé publique de l'identité en mots BIP32 (17 mots) - Stocke la clé publique dans `PairConfig.publicKey` #### `addRemotePairFromWords()` **Avant :** - Décode les mots pour obtenir l'UUID du pair - Clé publique optionnelle (fournie séparément) **Maintenant :** - Décode les mots pour obtenir directement la clé publique - Génère un UUID pour le pair localement - Stocke automatiquement la clé publique dans `PairConfig.publicKey` #### `ensureLocalPairForSetup()` **Avant :** - Retourne les mots de l'UUID du pair local **Maintenant :** - Nécessite la clé publique de l'identité en paramètre - Retourne les mots de la clé publique #### `parseAndValidatePairingWords()` **Avant :** - Valide 8 mots - Vérifie qu'ils décodent un UUID valide **Maintenant :** - Valide 17 mots - Vérifie qu'ils décodent une clé publique valide (préfixe 02/03/04) ### Modifications de l'interface utilisateur #### Messages d'erreur - **Avant** : "Mots invalides. 8 mots requis." - **Maintenant** : "Mots invalides. 17 mots requis." #### Composants affectés - `PairingDisplayScreen.tsx` : Saisie des mots du 1er appareil - `PairingSetupBlock.tsx` : Saisie des mots du 2ème appareil - `PairManagementScreen.tsx` : Affichage des mots de la clé publique ### ECDH et pairing La clé publique extraite des mots est : 1. **Stockée automatiquement** dans `PairConfig.publicKey` 2. **Utilisée pour ECDH** lors du pairing (`publishPairingMessage`) 3. **Récupérée depuis les signatures** si nécessaire (fallback) ## Flux de pairing ### Device 1 (premier appareil) 1. Génère un UUID pour le pair local 2. Encode la clé publique de son identité en 17 mots BIP32 3. Affiche les mots pour le device 2 4. Reçoit les mots du device 2 5. Décode les mots pour obtenir la clé publique du device 2 6. Crée le pair distant avec cette clé publique 7. Utilise la clé publique pour ECDH lors du pairing ### Device 2 (second appareil) 1. Génère un UUID pour le pair local 2. Encode la clé publique de son identité en 17 mots BIP32 3. Affiche les mots pour le device 1 4. Reçoit les mots du device 1 5. Décode les mots pour obtenir la clé publique du device 1 6. Crée le pair distant avec cette clé publique 7. Utilise la clé publique pour ECDH lors du pairing ## Comparaison avant/après ### Avant (UUID) ``` Mots → UUID du pair → Besoin de récupérer le pair depuis un relais → Problème : pas d'endpoint pour récupérer par UUID → Problème : le pair n'existe pas encore sur le relais ``` ### Maintenant (Clé publique) ``` Mots → Clé publique directement → Stockée dans PairConfig.publicKey → Utilisée pour ECDH → Pas besoin de relais ``` ## Impact ### Positif - ✅ Pairing initial fonctionne sans publication préalable - ✅ Pas de dépendance à un relais pour le pairing - ✅ Clé publique disponible immédiatement - ✅ ECDH fonctionne dès le pairing ### Changements nécessaires - ⚠️ Les mots passent de 8 à 17 mots - ⚠️ Les anciens pairs avec mots UUID ne sont plus compatibles - ⚠️ Migration nécessaire si des pairs existent déjà ## Migration Si des pairs existent déjà avec l'ancien format (UUID) : 1. Les pairs locaux peuvent être régénérés avec la nouvelle méthode 2. Les pairs distants doivent être re-pairés avec les nouveaux mots (17 mots) 3. L'ancien format (8 mots) n'est plus supporté ## Références - `userwallet/src/utils/bip32.ts` : Fonctions d'encodage/décodage - `userwallet/src/utils/pairing.ts` : Logique de pairing - `userwallet/src/services/pairingConfirm.ts` : Confirmation de pairing avec ECDH - `userwallet/src/components/PairingDisplayScreen.tsx` : Interface de pairing - `userwallet/src/components/PairingSetupBlock.tsx` : Configuration de pairing