PD-242 — Expression de besoin
Contexte
L'architecture technique v4.1 (doc 42) définit une Recovery Envelope : Enc(K_recovery, K_master_user) permettant a l'utilisateur de recuperer sa cle maitre en cas de perte de device.
Cette promesse est egalement mentionnee dans le pitch investisseurs (doc 43) : "Acces conserve meme apres depart entreprise".
Dependances
| Story | Description | Statut |
| PD-97 | Pipeline crypto zero-knowledge iOS (Argon2id, AES-GCM, HKDF) | DONE |
| PD-98 | Stockage K_master dans Keychain iOS (ThisDeviceOnly) | DONE |
Learnings pertinents (domaine crypto)
- PD-97 : Hermes (React Native) n'a pas de support WebAssembly — fallback requis pour les operations crypto lourdes
- PD-97 : JavaScript strings are immutable — memory zeroization is best-effort only
- PD-33 : Constants must be imported, not redefined inline — inconsistent Associated Data formats break interop
- PD-99 : Observable contractuel explicite requis (header X-Auth-Protocol)
Besoin fonctionnel
En tant que utilisateur ProbatioVault
Je veux pouvoir recuperer l'acces a mon coffre-fort numerique en cas de perte ou remplacement de mon appareil iOS, Afin de ne jamais perdre mes documents probatoires proteges par la cle maitre K_master.
Description
L'application iOS doit implementer un mecanisme de recovery cryptographique base sur :
- Generation d'une phrase de recuperation (BIP-39 24 mots, 256 bits d'entropie)
- Derivation d'une cle de recovery (K_recovery) via HKDF-SHA3-256
- Creation d'une enveloppe de recovery :
Enc(K_recovery, K_master_user) - Stockage zero-knowledge de l'enveloppe cote backend (seul le ciphertext est stocke)
- Flux de restauration sur nouveau device via saisie de la phrase
Flux utilisateur
Flux 1 : Creation de la recovery (onboarding obligatoire)
1. L'utilisateur cree son compte ProbatioVault
2. K_master_user est generee et stockee dans le Keychain iOS (PD-98)
3. L'application genere une phrase BIP-39 de 24 mots (CSPRNG local)
4. L'application affiche la phrase et demande a l'utilisateur de la sauvegarder
5. L'utilisateur DOIT re-saisir les 24 mots complets pour confirmer
6. K_recovery est derivee : HKDF-SHA3-256(seed, salt="ProbatioVault::Recovery::v1", info=user_id)
7. L'enveloppe est creee : Recovery_Envelope = Enc_AES-256-GCM(K_recovery, K_master_user)
8. Un hash de verification est genere : H_verify = SHA3-256(K_recovery || user_id)
9. Recovery_Envelope + H_verify sont envoyes au backend (zero-knowledge)
10. K_recovery est detruite en memoire IMMEDIATEMENT
11. La phrase n'est JAMAIS stockee
Flux 2 : Restauration sur nouveau device
1. L'utilisateur installe ProbatioVault sur un nouveau device
2. L'application detecte l'absence de K_master dans le Keychain local
3. L'utilisateur choisit "Recuperer mon coffre"
4. L'utilisateur saisit ses 24 mots
5. K_recovery est derivee localement (meme parametres)
6. H_verify_candidate = SHA3-256(K_recovery || user_id)
7. L'application demande H_verify au backend et compare
8. Si match : l'application demande Recovery_Envelope au backend
9. K_master_user = Dec_AES-256-GCM(K_recovery, Recovery_Envelope)
10. K_master_user est stockee dans le nouveau Keychain (PD-98)
11. K_recovery est detruite en memoire IMMEDIATEMENT
12. L'utilisateur recupere l'acces a son coffre
Flux 3 : Regeneration de phrase (sur demande utilisateur)
1. L'utilisateur demande a regenerer sa phrase de recovery
2. L'application demande l'authentification forte (biometrie + password)
3. Une nouvelle phrase BIP-39 de 24 mots est generee
4. L'utilisateur DOIT re-saisir les 24 mots complets
5. Une nouvelle K_recovery est derivee
6. Une nouvelle Recovery_Envelope est creee
7. L'ancienne Recovery_Envelope est invalidee cote backend
8. Nouvelle Recovery_Envelope + H_verify envoyes au backend
9. Nouvelle K_recovery detruite IMMEDIATEMENT
Invariants de securite
| ID | Invariant | Type |
| INV-242-01 | K_recovery ne transite JAMAIS en clair sur le reseau | SEC |
| INV-242-02 | La phrase de recuperation n'est JAMAIS stockee (ni local, ni backend) | SEC |
| INV-242-03 | K_recovery est detruite en memoire IMMEDIATEMENT apres usage | SEC |
| INV-242-04 | Le backend ne peut PAS dechiffrer K_master_user (zero-knowledge) | SEC |
| INV-242-05 | L'entropie de la phrase est de 256 bits minimum (BIP-39 24 mots) | SEC |
| INV-242-06 | La derivation utilise HKDF-SHA3-256 avec domain separation | CRYPTO |
| INV-242-07 | Le chiffrement de l'enveloppe utilise AES-256-GCM (AEAD) | CRYPTO |
| INV-242-08 | La verification de phrase utilise un hash sans exposer K_recovery | SEC |
| INV-242-09 | L'onboarding EXIGE la confirmation complete des 24 mots | UX |
| INV-242-10 | Un changement de device DECLENCHE automatiquement le flux recovery | ARCH |
Parametres cryptographiques
| Parametre | Valeur | Reference |
| Phrase format | BIP-39 (24 mots, 256 bits) | BIP-0039 |
| Derivation K_recovery | HKDF-SHA3-256 | RFC 5869 + FIPS 202 |
| HKDF salt | "ProbatioVault::Recovery::v1" | Domain separation |
| HKDF info | user_id | Context binding |
| HKDF output length | 32 bytes (256 bits) | Coherence K_master |
| Chiffrement envelope | AES-256-GCM | NIST SP 800-38D |
| GCM nonce | 96 bits (random) | Best practice |
| Hash verification | SHA3-256(K_recovery || user_id) | FIPS 202 |
Perimetre
Inclus
- Generation phrase BIP-39 24 mots (CSPRNG local)
- Derivation K_recovery via HKDF-SHA3-256
- Creation Recovery_Envelope (AES-256-GCM)
- Hash de verification H_verify
- API backend pour stocker/recuperer l'envelope (zero-knowledge)
- Flux de confirmation (re-saisie 24 mots)
- Flux de restauration sur nouveau device
- Flux de regeneration sur demande
- Destruction memoire K_recovery apres usage
- Tests avec vecteurs BIP-39 officiels
Exclu
- Stockage iCloud de l'envelope (decision : backend only)
- Rotation automatique de l'envelope
- Shamir Secret Sharing (2-of-3) — future story
- Mode enterprise custody — future story
- Implementation Android/Web — hors scope iOS
Criteres d'acceptation preliminaires
| ID | Critere | Mesurable |
| CA-242-01 | La phrase generee est valide BIP-39 (checksum correct) | Oui (lib validation) |
| CA-242-02 | K_recovery derivee est deterministe (meme phrase = meme cle) | Oui (vecteurs) |
| CA-242-03 | L'envelope peut etre dechiffree avec la phrase originale | Oui (test E2E) |
| CA-242-04 | Une phrase incorrecte ne permet PAS de dechiffrer l'envelope | Oui (test negatif) |
| CA-242-05 | H_verify permet de detecter une phrase incorrecte AVANT dechiffrement | Oui (test) |
| CA-242-06 | K_recovery n'apparait dans aucun log/trace | Oui (audit logs) |
| CA-242-07 | La re-saisie des 24 mots est obligatoire a l'onboarding | Oui (test E2E) |
| CA-242-08 | Le flux recovery restaure K_master sur un device vierge | Oui (test E2E) |
| CA-242-09 | La regeneration invalide l'ancienne envelope | Oui (test backend) |
| CA-242-10 | Les operations crypto n'excedent pas 3s sur iPhone 12+ | Oui (benchmark) |
Risques identifies
| Risque | Impact | Mitigation |
| Utilisateur ne sauvegarde pas sa phrase | Perte definitive du coffre | Confirmation obligatoire + UX claire |
| Phrase interceptee lors de l'affichage | Compromission totale | Screenshot bloque, timeout affichage |
| Memory leak de K_recovery | Compromission | Zeroization best-effort + audit |
| Backend compromis | Fuite des envelopes | Zero-knowledge : envelopes inutiles sans phrase |
| Entropie CSPRNG faible | Phrase predictible | iOS SecRandomCopyBytes audite |
Questions ouvertes (a clarifier en spec)
- Timeout affichage phrase : combien de temps avant masquage automatique ?
- Blocage screenshot : technique iOS disponible (FLAG_SECURE equivalent) ?
- Rate limiting : combien de tentatives de restauration avant blocage ?
- Observabilite : quels evenements remonter au backend (sans compromettre ZK) ?
- Migration future Android : l'envelope iOS sera-t-elle portable ?
References
- Architecture technique v4.1 (doc 42) — Section Recovery Envelope
- Specifications techniques v2.1 (doc 43) — HKDF, AES-GCM
- BIP-0039 : Mnemonic code for generating deterministic keys
- RFC 5869 : HMAC-based Extract-and-Expand Key Derivation Function
- FIPS 202 : SHA-3 Standard
- NIST SP 800-38D : Recommendation for Block Cipher Modes of Operation: GCM
- PD-97 : Pipeline crypto zero-knowledge iOS
- PD-98 : Stockage K_master dans Keychain iOS