# UserWallet – Protection des clés par mot de passe **Author:** Équipe 4NK **Date:** 2026-01-26 ## Objectif Chiffrer la clé privée au repos avec un mot de passe utilisateur. Déverrouillage requis pour signer (login, iframe auth). Verrouillage possible pour vider la session sans toucher au stockage. ## Impacts - **Fonctionnels** : Activation/désactivation de la protection, déverrouillage au démarrage si protégé, verrouillage manuel. Export inclut la clé seulement si déverrouillé. - **Techniques** : `keyProtection` (PBKDF2 + AES-GCM), `sessionUnlockedKey`, extension de `identity` (enable/disable/unlock/lock). `LocalIdentity.privateKey` optionnel. Gate applicatif (UnlockScreen) quand protégé et non déverrouillé. ## Modifications ### Nouveaux fichiers - **`utils/keyProtection.ts`** : `encryptPrivateKey`, `decryptPrivateKey`, `EncryptedPayload`. PBKDF2 100k itérations, AES-GCM, salt/iv aléatoires. - **`utils/sessionUnlockedKey.ts`** : `getUnlockedPrivateKey`, `setUnlockedPrivateKey` (module-level). - **`components/UnlockScreen.tsx`** : Formulaire mot de passe, appel à `unlock`, affichage erreur. ### identity.ts - `isProtectionEnabled`, `enableProtection`, `disableProtection`, `unlock`, `lock`. - Stockage : `userwallet_identity_encrypted` (ciphertext, iv, salt). Identité stockée sans `privateKey` quand protection activée. ### useIdentity - `isProtected`, `isUnlocked`, `enableProtection`, `disableProtection`, `unlock`, `lock`, `refreshIdentity`. - Identité renvoyée : stockée + `privateKey` de session si protégé et déverrouillé. ### App - **AppGate** : Si `identity && isProtected && !isUnlocked` → `UnlockScreen`, sinon `AppContent`. ### UI - **HomeScreen** : Bouton « Verrouiller » si protégé et déverrouillé. - **DataExportImportScreen** : Section « Protection par mot de passe » (activer / désactiver / verrouiller). Gestion erreurs export si verrouillé. ### Autres - **useChannel** : Si `identity` sans `privateKey` → erreur « Identité verrouillée ». - **LoginScreen** : Vérification `identity.privateKey` avant signature. - **exportImport** : Export utilise la clé de session si protégé ; sinon throw « Déverrouillez… ». ### Types - **`LocalIdentity.privateKey`** : optionnel. ## Modalités de déploiement - Rebuild frontend, déploiement des assets. Aucune migration. ## Modalités d’analyse - Activer la protection → recharger → UnlockScreen. Déverrouiller → accès normal. Verrouiller → UnlockScreen à nouveau. - Exporter sans déverrouiller (si contournement du gate) → erreur. Exporter après déverrouillage → JSON contient `identity.privateKey`. - Désactiver la protection → identité de nouveau en clair ; `userwallet_identity_encrypted` supprimé.