PD-242 — Enveloppe cryptographique de recuperation (K_recovery)¶
Navigation User Story
| Document | | | ---------- | -- | | Specification | *(ce document)* | | [Plan d'implementation](PD-242-plan.md) | | | [Criteres d'acceptation](PD-242-acceptability.md) | | | [Retour d'experience](PD-242-rex.md) | | [← Retour a crypto](../PD-189-epic.md) · [Index User Story](index.md)References¶
- EPIC : PD-189 — CRYPTO
- JIRA : PD-242
- Composant : Client-side crypto (mobile iOS)
Objectif¶
Implementer un mecanisme de recovery cryptographique permettant a l'utilisateur de recuperer l'acces a son coffre-fort numerique en cas de perte ou remplacement de son appareil iOS, via une phrase de recuperation BIP-39 de 24 mots.
Ce mecanisme garantit la promesse d'architecture zero-knowledge : le backend stocke uniquement l'enveloppe chiffree (Recovery_Envelope) sans jamais pouvoir acceder a la cle maitre utilisateur (K_master_user).
La phrase de recuperation n'est jamais stockee (ni localement, ni cote backend). Seul l'utilisateur en possede une copie physique.
Description fonctionnelle¶
Flux 1 : Creation de la recovery (onboarding obligatoire)¶
Lors de la creation de compte ProbatioVault :
K_master_userest generee et stockee dans le Keychain iOS (PD-98)- L'application genere une phrase BIP-39 de 24 mots via CSPRNG local
- L'application affiche la phrase avec protection screenshot
- L'affichage expire apres 120 secondes (masquage automatique)
- L'utilisateur DOIT re-saisir les 24 mots complets pour confirmer
K_recoveryest derivee via HKDF-SHA3-256Recovery_Envelopeest creee :Enc_AES-256-GCM(K_recovery, K_master_user)H_verifyest genere :SHA3-256(K_recovery || user_id)Recovery_Envelope+H_verifysont envoyes au backend (zero-knowledge)K_recoveryest detruite en memoire IMMEDIATEMENT- La phrase n'est JAMAIS stockee
Flux 2 : Restauration sur nouveau device¶
Lorsqu'un utilisateur installe ProbatioVault sur un nouveau device :
- L'application detecte l'absence de
K_masterdans le Keychain local - L'ecran propose "Recuperer mon coffre" ou "Creer un nouveau compte"
- L'utilisateur choisit "Recuperer mon coffre" et saisit ses 24 mots
K_recoveryest derivee localement (memes parametres)H_verify_candidate = SHA3-256(K_recovery || user_id)- L'application demande
H_verifyau backend et compare - Si match : l'application demande
Recovery_Envelopeau backend K_master_user = Dec_AES-256-GCM(K_recovery, Recovery_Envelope)K_master_userest stockee dans le nouveau Keychain (PD-98)K_recoveryest detruite en memoire IMMEDIATEMENT- L'utilisateur recupere l'acces a son coffre
Flux 3 : Regeneration de phrase (sur demande utilisateur)¶
Lorsqu'un utilisateur souhaite regenerer sa phrase de recovery :
- L'application demande l'authentification forte (biometrie + password)
- Une nouvelle phrase BIP-39 de 24 mots est generee
- L'affichage expire apres 120 secondes
- L'utilisateur DOIT re-saisir les 24 mots complets
- Une nouvelle
K_recoveryest derivee - Une nouvelle
Recovery_Envelopeest creee - L'ancienne
Recovery_Envelopeest invalidee cote backend - Nouvelle
Recovery_Envelope+H_verifyenvoyes au backend - Nouvelle
K_recoverydetruite IMMEDIATEMENT
5bis. Diagrammes¶
5bis.1 Diagramme d'etats — Recovery Envelope¶
stateDiagram-v2
[*] --> NO_ENVELOPE : Compte cree / nouveau device
state "Flux Creation (onboarding)" as creation {
NO_ENVELOPE --> PHRASE_DISPLAYED : generateMnemonic() [INV-242-05]
PHRASE_DISPLAYED --> PHRASE_EXPIRED : timeout 120s [INV-242-12]
PHRASE_EXPIRED --> PHRASE_DISPLAYED : re-affichage (auth)
PHRASE_DISPLAYED --> PHRASE_CONFIRMED : re-saisie 24 mots OK [INV-242-09]
PHRASE_CONFIRMED --> K_RECOVERY_DERIVED : HKDF-SHA3-256 [INV-242-06]
K_RECOVERY_DERIVED --> ENVELOPE_STORED : Enc AES-256-GCM + POST backend [INV-242-07, INV-242-01]
ENVELOPE_STORED --> K_RECOVERY_WIPED : fill(0) immediat [INV-242-03]
}
state "Flux Restauration (nouveau device)" as restoration {
NO_ENVELOPE --> RECOVERY_INITIATED : "Recuperer mon coffre"
RECOVERY_INITIATED --> VERIFY_PENDING : deriveRecoveryKey() + computeVerificationHash() [INV-242-08]
VERIFY_PENDING --> VERIFY_FAILED : H_verify mismatch
VERIFY_PENDING --> VERIFY_SUCCESS : H_verify match
VERIFY_FAILED --> RECOVERY_INITIATED : nouvelle tentative (< 5/15min) [INV-242-13]
VERIFY_FAILED --> RATE_LIMITED : >= 5 echecs / 15 min [INV-242-13]
RATE_LIMITED --> RECOVERY_INITIATED : apres expiration fenetre 15 min
VERIFY_SUCCESS --> ENVELOPE_DECRYPTED : Dec AES-256-GCM [INV-242-07]
ENVELOPE_DECRYPTED --> RESTORED : K_master -> Keychain [INV-242-04]
RESTORED --> K_RECOVERY_WIPED_R : fill(0) immediat [INV-242-03]
}
state "Flux Regeneration" as regeneration {
ENVELOPE_STORED --> REGEN_AUTH : auth forte (biometrie + password)
REGEN_AUTH --> REGEN_PHRASE_DISPLAYED : nouvelle phrase BIP-39 [INV-242-05]
REGEN_PHRASE_DISPLAYED --> REGEN_PHRASE_EXPIRED : timeout 120s [INV-242-12]
REGEN_PHRASE_EXPIRED --> REGEN_PHRASE_DISPLAYED : re-affichage (auth)
REGEN_PHRASE_DISPLAYED --> REGEN_PHRASE_CONFIRMED : re-saisie 24 mots OK [INV-242-09]
REGEN_PHRASE_CONFIRMED --> OLD_ENVELOPE_INVALIDATED : DELETE ancien [INV-242-02]
OLD_ENVELOPE_INVALIDATED --> NEW_ENVELOPE_STORED : POST nouveau [INV-242-01, INV-242-07]
NEW_ENVELOPE_STORED --> K_RECOVERY_WIPED_RG : fill(0) immediat [INV-242-03]
}
K_RECOVERY_WIPED --> [*] : Onboarding termine
K_RECOVERY_WIPED_R --> [*] : Coffre restaure
K_RECOVERY_WIPED_RG --> [*] : Regeneration terminee
note right of RATE_LIMITED : 429 Too Many Requests\n5 tentatives / 15 min / user_id\n20 tentatives / 15 min / IP
note right of K_RECOVERY_WIPED : INV-242-02 : phrase JAMAIS stockee\nINV-242-03 : K_recovery detruite 5bis.2 Diagramme de sequence — Flux complet (creation + restauration + regeneration)¶
sequenceDiagram
actor User
participant App as App iOS
participant Crypto as RecoveryService<br/>(client-side)
participant Keychain as Keychain iOS
participant Backend as Backend API
note over User, Backend: ━━━ FLUX 1 : Creation (onboarding) ━━━
User->>App: Creer un compte
App->>Keychain: Lire K_master_user (PD-98)
Keychain-->>App: K_master_user
App->>Crypto: generateMnemonic()
note right of Crypto: SecRandomCopyBytes<br/>256 bits entropie<br/>+ checksum 8 bits SHA-256<br/>[INV-242-05]
Crypto-->>App: phrase (24 mots BIP-39)
App->>User: Afficher phrase (screenshot protege) [INV-242-11]
note right of App: Timer 120s demarre [INV-242-12]
User->>App: Re-saisir 24 mots [INV-242-09]
App->>App: Validation complete (24/24 mots)
App->>Crypto: deriveRecoveryKey(phrase, user_id)
note right of Crypto: BIP-39 seed : PBKDF2-HMAC-SHA512<br/>(2048 iter, passphrase="")<br/>K_recovery : HKDF-SHA3-256<br/>(salt="ProbatioVault::Recovery::v1",<br/>info=user_id, len=32)<br/>[INV-242-06]
Crypto-->>App: K_recovery (32 bytes)
App->>Crypto: createRecoveryEnvelope(K_recovery, K_master_user)
note right of Crypto: AES-256-GCM<br/>nonce=96 bits random<br/>tag=128 bits<br/>[INV-242-07]
Crypto-->>App: {envelope, nonce, tag}
App->>Crypto: computeVerificationHash(K_recovery, user_id)
note right of Crypto: H_verify = SHA3-256(K_recovery || user_id)<br/>[INV-242-08]
Crypto-->>App: H_verify
App->>Backend: POST /recovery/envelope {user_id, envelope, h_verify}
note right of App: Seuls envelope (ciphertext)<br/>et H_verify (hash) transitent<br/>[INV-242-01, INV-242-04]
Backend-->>App: 201 Created
Backend->>Backend: Trace recovery.envelope.created
App->>Crypto: wipeKey(K_recovery)
note right of Crypto: Uint8Array.fill(0)<br/>[INV-242-03]
note over App: Phrase JAMAIS stockee [INV-242-02]
note over User, Backend: ━━━ FLUX 2 : Restauration (nouveau device) ━━━
User->>App: Installer sur Device B
App->>Keychain: Lire K_master_user
Keychain-->>App: null (absent)
App->>User: "Recuperer mon coffre" / "Creer un compte"
User->>App: "Recuperer mon coffre"
User->>App: Saisir 24 mots [INV-242-10]
App->>Crypto: deriveRecoveryKey(phrase, user_id)
Crypto-->>App: K_recovery
App->>Crypto: computeVerificationHash(K_recovery, user_id)
Crypto-->>App: H_verify_candidate
App->>Backend: GET /recovery/h_verify/:user_id
Backend-->>App: {h_verify}
Backend->>Backend: Trace recovery.restore.attempt
alt H_verify mismatch
App->>User: Erreur : phrase incorrecte
Backend->>Backend: Trace recovery.restore.failed (hash_mismatch)
note right of Backend: Rate limit : 5 tentatives/15min<br/>[INV-242-13]
else H_verify match
App->>Backend: GET /recovery/envelope/:user_id<br/>X-H-Verify-Candidate: H_verify_candidate
Backend-->>App: {envelope}
App->>Crypto: restoreFromEnvelope(K_recovery, envelope)
note right of Crypto: Dec AES-256-GCM<br/>[INV-242-07]
Crypto-->>App: K_master_user
App->>Keychain: Stocker K_master_user (PD-98)
Backend->>Backend: Trace recovery.restore.success (device_id)
App->>Crypto: wipeKey(K_recovery)
note right of Crypto: [INV-242-03]
App->>User: Coffre restaure
end
note over User, Backend: ━━━ FLUX 3 : Regeneration ━━━
User->>App: Regenerer ma phrase
App->>User: Authentification forte (biometrie + password)
User->>App: Auth OK
App->>Crypto: generateMnemonic()
Crypto-->>App: nouvelle phrase (24 mots)
App->>User: Afficher nouvelle phrase [INV-242-11, INV-242-12]
User->>App: Re-saisir 24 mots [INV-242-09]
App->>Crypto: deriveRecoveryKey(nouvelle_phrase, user_id)
Crypto-->>App: nouvelle K_recovery
App->>Crypto: createRecoveryEnvelope(nouvelle_K_recovery, K_master_user)
Crypto-->>App: {nouvelle_envelope, nonce, tag}
App->>Crypto: computeVerificationHash(nouvelle_K_recovery, user_id)
Crypto-->>App: nouveau H_verify
App->>Backend: DELETE /recovery/envelope/:user_id
Backend-->>App: 204 No Content
note right of Backend: Ancienne envelope invalidee<br/>(ancienne phrase inutilisable)
App->>Backend: POST /recovery/envelope {user_id, nouvelle_envelope, nouveau_h_verify}
Backend-->>App: 201 Created
Backend->>Backend: Trace recovery.envelope.regenerated
App->>Crypto: wipeKey(nouvelle_K_recovery)
note right of Crypto: [INV-242-03] Perimetre¶
Inclus¶
- Generation phrase BIP-39 24 mots (CSPRNG local via
SecRandomCopyBytes) - Derivation
K_recoveryvia HKDF-SHA3-256 avec domain separation - 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
- Protection screenshot de l'affichage phrase
- Timeout affichage phrase (120 secondes)
- Rate limiting des tentatives de restauration
- Destruction memoire
K_recoveryapres 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
- UX de sauvegarde phrase (papier, coffre physique) — responsabilite utilisateur
Parametres cryptographiques normatifs¶
| Parametre | Valeur | Reference | Testable |
|---|---|---|---|
| Phrase format | BIP-39 (24 mots, 256 bits) | BIP-0039 | Oui |
| Wordlist | BIP-39 English (2048 mots) | BIP-0039 | Oui |
| Phrase entropy | 256 bits | BIP-0039 | Oui |
| Phrase checksum | 8 bits (SHA-256) | BIP-0039 | Oui |
| Seed derivation | PBKDF2-HMAC-SHA512 | BIP-0039 | Oui |
| PBKDF2 iterations | 2048 | BIP-0039 | Oui |
| PBKDF2 passphrase | "" (vide) | BIP-0039 | Oui |
| Derivation K_recovery | HKDF-SHA3-256 | RFC 5869 + FIPS 202 | Oui |
| HKDF salt | "ProbatioVault::Recovery::v1" (UTF-8) | Domain separation | Oui |
| HKDF info | user_id (UUID bytes) | Context binding | Oui |
| HKDF output length | 32 bytes (256 bits) | Coherence K_master | Oui |
| Chiffrement envelope | AES-256-GCM | NIST SP 800-38D | Oui |
| GCM key | K_recovery (32 bytes) | Oui | |
| GCM nonce | 96 bits (random) | Best practice | Oui |
| GCM tag length | 128 bits | NIST | Oui |
| Hash verification | SHA3-256(K_recovery || user_id) | FIPS 202 | Oui |
| Timeout affichage | 120 secondes | UX | Oui |
| Rate limit restore | 5 tentatives / 15 minutes / user_id | SEC | Oui |
| Rate limit IP | 20 tentatives / 15 minutes / IP | SEC | Oui |
Proprietes attendues¶
Securite¶
- Resistance aux attaques par dictionnaire sur la phrase (256 bits d'entropie)
- Couplage obligatoire phrase + user_id + domain separation
- Aucune fuite de
K_recoveryvia logs, stacktraces ou exceptions - Protection contre le screenshot de la phrase affichee
- Masquage automatique de la phrase apres timeout
- Rate limiting des tentatives de restauration (protection brute-force backend)
- Effacement memoire best-effort de
K_recoveryapres usage (Uint8Array.fill(0))
Zero-Knowledge¶
- La phrase ne quitte JAMAIS l'appareil
K_recoveryne transite JAMAIS en clair sur le reseau- Le backend ne peut PAS dechiffrer
K_master_user - Seuls
Recovery_Envelope(ciphertext) etH_verify(hash) sont stockes backend - Aucun log backend ne contient de materiel cryptographique sensible
Interoperabilite¶
- Resultat derivation strictement deterministe
- Phrase BIP-39 compatible avec standards industrie (wallets, etc.)
- Envelope portable entre iOS/Android/Web (future story)
- Vecteurs de test BIP-39 officiels valides
Observabilite (sans compromettre ZK)¶
Le backend peut tracer les evenements suivants (sans materiel sensible) :
| Evenement | Donnees tracees |
|---|---|
recovery.envelope.created | user_id, timestamp, envelope_hash |
recovery.restore.attempt | user_id, timestamp, success: boolean |
recovery.restore.success | user_id, timestamp, device_id |
recovery.restore.failed | user_id, timestamp, failure_reason |
recovery.envelope.regenerated | user_id, timestamp |
recovery.rate_limit.exceeded | user_id ou IP, timestamp |
Contraintes¶
- Execution exclusivement cote client pour la cryptographie
- Bibliotheque BIP-39 auditee et maintenue (ex:
bip39npm) - Bibliotheque SHA3 conforme FIPS 202 (ex:
js-sha3) - Aucun fallback vers des algorithmes moins securises
- Aucun calcul cryptographique deporte (backend, HSM) sauf stockage envelope
- Compatible Hermes (React Native) — pas de WebAssembly requis
- Effacement memoire best-effort (JavaScript strings immutables)
Hypotheses¶
user_idest un UUID v4 stable disponible localement- Le Keychain iOS est accessible (PD-98 DONE)
- Le backend dispose d'un endpoint REST pour stocker/recuperer l'envelope
- L'utilisateur comprend l'importance de sauvegarder sa phrase de maniere securisee
- Les bibliotheques cryptographiques utilisees sont auditees
- Les operations crypto ne bloquent pas le thread UI (async)
Invariants de securite¶
| ID | Invariant | Type | Testable |
|---|---|---|---|
| INV-242-01 | K_recovery ne transite JAMAIS en clair sur le reseau | SEC | Oui — capture reseau |
| INV-242-02 | La phrase de recuperation n'est JAMAIS stockee (ni local, ni backend) | SEC | Oui — audit stockage |
| INV-242-03 | K_recovery est detruite en memoire apres usage | SEC | Partiel — best-effort |
| INV-242-04 | Le backend ne peut PAS dechiffrer K_master_user | SEC | Oui — analyse code |
| INV-242-05 | L'entropie de la phrase est de 256 bits minimum | SEC | Oui — vecteurs BIP-39 |
| INV-242-06 | La derivation utilise HKDF-SHA3-256 avec domain separation | CRYPTO | Oui — vecteurs |
| INV-242-07 | Le chiffrement de l'enveloppe utilise AES-256-GCM (AEAD) | CRYPTO | Oui — vecteurs |
| INV-242-08 | La verification de phrase utilise un hash sans exposer K_recovery | SEC | Oui — analyse flux |
| INV-242-09 | L'onboarding EXIGE la confirmation complete des 24 mots | UX | Oui — test E2E |
| INV-242-10 | Un changement de device DECLENCHE automatiquement le flux recovery | ARCH | Oui — test E2E |
| INV-242-11 | L'affichage phrase est protege contre les screenshots | SEC | Oui — test iOS |
| INV-242-12 | L'affichage phrase expire apres 120 secondes | SEC | Oui — test timer |
| INV-242-13 | Le rate limiting bloque apres 5 echecs / 15 min | SEC | Oui — test API |
Tests d'acceptation¶
TA-1 — Validite BIP-39¶
La phrase generee est valide BIP-39 : - 24 mots exactement - Chaque mot appartient a la wordlist BIP-39 English - Checksum correct (8 bits SHA-256)
TA-2 — Determinisme derivation¶
A phrase identique et user_id identique, K_recovery est strictement identique (bit-a-bit). Verification via vecteurs de test avec valeurs attendues precalculees.
TA-3 — Chiffrement/dechiffrement round-trip¶
L'envelope peut etre dechiffree avec la phrase originale : 1. Generer phrase → deriver K_recovery → chiffrer K_master → obtenir envelope 2. Deriver K_recovery (meme phrase) → dechiffrer envelope → obtenir K_master 3. K_master originale === K_master dechiffree
TA-4 — Rejet phrase incorrecte¶
Une phrase incorrecte (1 mot different) ne permet PAS de dechiffrer l'envelope : - H_verify ne matche pas → restauration bloquee avant dechiffrement - Meme si bypass H_verify, AEAD echoue (tag invalide)
TA-5 — Verification pre-dechiffrement¶
H_verify permet de detecter une phrase incorrecte AVANT de tenter le dechiffrement : 1. Deriver K_recovery (phrase incorrecte) 2. Calculer H_verify_candidate 3. Comparer avec H_verify backend 4. Mismatch → erreur sans tenter dechiffrement
TA-6 — Absence de logs sensibles¶
K_recovery n'apparait dans aucun log applicatif : - Console.log - Crashlytics / Sentry - Analytics - Network logs - Exception stacktraces
TA-7 — Re-saisie obligatoire onboarding¶
L'onboarding ne peut pas se terminer sans re-saisie complete des 24 mots : - Skip impossible - Validation partielle impossible - Fermeture app → reprise depuis re-saisie
TA-8 — Flux recovery E2E¶
Le flux recovery restaure K_master sur un device vierge : 1. Device A : creer compte → sauvegarder phrase 2. Device B (vierge) : installer app → "Recuperer mon coffre" 3. Saisir phrase → K_master restauree → acces coffre OK
TA-9 — Invalidation ancienne envelope¶
La regeneration invalide l'ancienne envelope : 1. Generer phrase A → envelope A stockee backend 2. Regenerer phrase B → envelope B stockee backend 3. Phrase A ne fonctionne PLUS (H_verify mismatch) 4. Phrase B fonctionne
TA-10 — Performance¶
Les operations crypto n'excedent pas 3 secondes sur iPhone 12+ : - Generation phrase : < 100ms - Derivation K_recovery : < 500ms - Chiffrement envelope : < 100ms - Dechiffrement envelope : < 100ms - Verification H_verify : < 50ms
TA-11 — Protection screenshot¶
L'ecran d'affichage de la phrase est protege contre les screenshots : - secureTextEntry ou equivalent iOS - FLAG_SECURE equivalent - Screenshot capture une image vide ou masquee
TA-12 — Timeout affichage¶
L'affichage de la phrase se masque automatiquement apres 120 secondes : - Countdown visible - Masquage automatique (phrase remplacee par astérisques ou écran vide) - Utilisateur peut re-afficher (avec authentification)
TA-13 — Rate limiting restauration¶
Apres 5 tentatives echouees, le rate limiting bloque : - 6eme tentative → erreur 429 - Attendre 15 minutes → tentatives restaurees
TA-14 — Vecteurs BIP-39 officiels¶
Les vecteurs de test BIP-39 officiels (TREZOR) passent : - Mnemonic → seed correct - Validation checksum - Rejection mots invalides
TA-15 — Portabilite envelope¶
L'envelope generee sur iOS est dechiffrable par les memes primitives sur Android/Web : - Pas de format proprietaire - Nonce inclus dans le ciphertext (standard) - Tag authentification 128 bits en suffixe
TA-16 — Observabilite backend¶
Les evenements de recovery sont traces cote backend : - recovery.envelope.created au premier setup - recovery.restore.attempt a chaque tentative - recovery.restore.success ou failed selon resultat
Livrables¶
- Module
RecoveryServicedans le package crypto client iOS - Fonction
generateMnemonic() → string[] - Fonction
deriveRecoveryKey(mnemonic, userId) → Uint8Array - Fonction
createRecoveryEnvelope(K_recovery, K_master) → { envelope, nonce, tag } - Fonction
restoreFromEnvelope(K_recovery, envelope) → K_master - Fonction
computeVerificationHash(K_recovery, userId) → Uint8Array - Ecran de creation recovery (onboarding)
- Ecran de restauration recovery
- Ecran de regeneration recovery
- Tests unitaires avec vecteurs
- Tests E2E des 3 flux
- Documentation
/docs/crypto/recovery-envelope.md
API Backend (specification)¶
POST /recovery/envelope¶
Stocke la recovery envelope.
Request:
Response: 201 Created
GET /recovery/h_verify/:user_id¶
Recupere le hash de verification.
Response:
GET /recovery/envelope/:user_id¶
Recupere la recovery envelope (apres verification H_verify reussie).
Headers requis: X-H-Verify-Candidate: base64
Response:
Erreurs: - 401 si X-H-Verify-Candidate mismatch - 429 si rate limit exceeded
DELETE /recovery/envelope/:user_id¶
Invalide l'envelope existante (appele avant regeneration).
Auth: Bearer token + biometric proof
Response: 204 No Content
Liens documentaires¶
- 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
Definition of Done¶
- Implementation conforme aux parametres cryptographiques normatifs
- Tests unitaires avec vecteurs BIP-39 officiels validés
- Tests E2E des 3 flux (creation, restauration, regeneration)
- Test de performance < 3s sur iPhone 12+
- Test protection screenshot
- Test timeout affichage
- Test rate limiting
- Aucun log ou fuite de secret (audit console + Sentry)
- Documentation publiee
- Revue securite validee
- Code review approuvee
- Pipeline CI/CD vert