Aller au contenu

PD-34 — Retour d'expérience


📚 Navigation User Story | Document | | | ---------- | -- | | 📋 [Spécification](PD-34-specification.md) | | | 🛠️ [Plan d'implémentation](PD-34-plan.md) | | | ✅ [Critères d'acceptation](PD-34-acceptability.md) | | | 📝 **Retour d'expérience** | *(ce document)* | [← Retour à crypto](../PD-189-epic.md) · [↑ Index User Story](index.md)

1. Résumé exécutif

La User Story PD-34 visait à implémenter la dérivation HKDF-SHA3-256 pour produire K_doc (clé unique par document) depuis K_master_user, avec domain separation via info string normative. L'implémentation est fonctionnelle et fournit l'isolation cryptographique attendue, mais présente 4 écarts : info string non conforme (Kdoc vs K_doc), architecture à 2 niveaux (K_master → K_share → K_doc) au lieu de 1 (K_master → K_doc), validation docId permissive, et hkdfExtract non conforme RFC 5869. Verdict : ACCEPTÉ AVEC RÉSERVES.


2. Points fluides

  • Bibliothèque @noble/hashes : intégration simple, API claire, SHA3-256 natif
  • Architecture modulaire : séparation nette hkdf.ts (primitives) et keys.ts (API hex)
  • Wrappers hex API : deriveKShare(), deriveKDoc() facilitent l'intégration
  • Zeroization systématique : clés intermédiaires effacées après usage
  • Fonction utilitaire uuidToBytes() : conversion UUID → 16 bytes centralisée dans crypto/utils
  • Domain separation effective : K_share ≠ K_doc via salt et info différents
  • Tests de déterminisme : même input → même output validé
  • Chaînage complet : deriveKDocFromMaster() simplifie l'usage courant

3. Points difficiles

Difficulté Contexte
Ambiguïté spec vs plan Spec dit IKM=K_master_user direct, plan introduit K_share intermédiaire
Format info string Hésitation entre :: et _ (constants.ts vs hkdf.ts) non résolue
@noble/hashes API hkdf() fait Extract+Expand ensemble, impossible de séparer proprement
Validation UUID vs string Choix de fallback TextEncoder pour flexibilité mais perd garantie 16 bytes
Re-exports multiples Chaîne hkdf.tskeys.ts → consumers complexifie le debug

4. Hypothèses révélées tardivement

Hypothèse initiale Réalité découverte
Spec et plan sont alignés FAUX — Plan introduit K_share absent de la spec
IKM = K_master_user directement FAUX — Implémentation utilise K_share intermédiaire
Info string normative respectée FAUXKdoc au lieu de K_doc (underscore manquant)
hkdf() permet Extract seul FAUX — @noble/hashes combine Extract+Expand
constants.ts utilisé partout FAUX — hkdf.ts définit ses propres HKDF_CONTEXTS

5. Invariants complexes à implémenter

Invariant Complexité
Unicité K_doc par document Salt = docId impose conversion UUID → 16 bytes cohérente
Hiérarchie 2 niveaux vs 1 Plan demande K_share intermédiaire, spec ne le mentionne pas
Domain separation stricte Contextes différents K_share/K_doc avec même K_master source
Déterminisme cross-platform Même docId → même K_doc sur iOS/Android/Web
Effacement clés intermédiaires K_share doit être zeroize après dérivation K_doc

6. Dette technique

Dette Impact Priorité
Info string divergente HKDF_CONTEXTS.KDOC = "...::Kdoc::..." vs spec "...::K_doc::..." HAUTE
K_share non documentée dans spec Niveau intermédiaire absent de PD-34-specification.md HAUTE
hkdfExtract non conforme Ne produit pas PRK seule, appelle hkdf() complet MOYENNE
Fallback TextEncoder docId non-UUID accepté, perd garantie 16 bytes BASSE
constants.ts ignoré CONTEXT_KDOC correct mais non utilisé par hkdf.ts MOYENNE

7. Risques résiduels

Risque Probabilité Impact Mitigation suggérée
Interop failure si autre client utilise spec exacte (K_doc) Moyenne ÉLEVÉ Aligner hkdf.ts sur constants.ts
Audit RFC 5869 échoue sur hkdfExtract Moyenne MOYEN Documenter comportement ou fix
K_share exposée via API sans nécessité Faible FAIBLE Masquer dans module privé
docId non-UUID produit salt variable Faible MOYEN Logger warning si fallback

8. Améliorations processus

Amélioration Bénéfice attendu
Aligner spec et plan AVANT implémentation Détecter K_share manquant dans spec plus tôt
Importer constants.ts au lieu de redéfinir Éviter divergences info string
Test d'interop avec vecteurs spec Valider output exact avec IKM/salt/info normatifs
Revue croisée spec ↔ code Identifier écarts de naming (Kdoc vs K_doc)
Wrapper hkdfExtract conforme RFC Implémenter via HMAC direct si nécessaire pour audit

9. Enseignements clés

  1. Les divergences plan/spec créent de la dette — Le plan a introduit K_share sans mise à jour de la spec, causant l'écart E-02.

  2. Les constantes centralisées doivent être utiliséesconstants.ts définit CONTEXT_KDOC = "ProbatioVault::K_doc::v1" (correct) mais hkdf.ts définit HKDF_CONTEXTS.KDOC = "ProbatioVault::Kdoc::v1" (incorrect). Pattern identique à PD-33.

  3. Les bibliothèques ont leurs contraintes — @noble/hashes combine Extract+Expand dans hkdf(), rendant hkdfExtract non conforme RFC 5869 telle qu'implémentée.

  4. La flexibilité peut nuire — Le fallback TextEncoder pour docId non-UUID facilite les tests mais introduit un risque d'incohérence en production.

  5. La hiérarchie de clés doit être documentée — L'ajout de K_share (niveau intermédiaire) améliore l'architecture mais doit être reflété dans la spec pour éviter confusion lors d'audits.