Aller au contenu

PD-97 — Implémenter le chiffrement client-side zero-knowledge (iOS)


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

Références

  • EPIC : MOBILE-IOS
  • JIRA : PD-97
  • Repo(s) concernés : mobile-ios

Objectif

Implémenter, côté application iOS, un pipeline cryptographique client-side strictement zero-knowledge, permettant le chiffrement et le déchiffrement des documents sans jamais exposer de clé ou de donnée en clair au backend ou à un tiers.

Cette User Story établit le socle cryptographique iOS de ProbatioVault.

Description fonctionnelle

L'application iOS doit être capable d'exécuter localement l'ensemble des opérations cryptographiques nécessaires à la protection des documents utilisateurs.

Le pipeline client-side doit permettre :

  • la dérivation d'une clé de chiffrement à partir du mot de passe utilisateur ;
  • la génération et l'utilisation d'une clé maître utilisateur locale ;
  • la dérivation déterministe de clés spécifiques à chaque document ;
  • le chiffrement et le déchiffrement authentifié des fichiers ;
  • la vérification stricte de l'intégrité et du contexte des données chiffrées.

À aucun moment :

  • une clé,
  • un mot de passe,
  • ou un document en clair ne doit quitter l'appareil iOS.

Périmètre

Inclus

  • Implémentation native iOS d'un mécanisme de dérivation de clé à partir du mot de passe utilisateur (Argon2id).
  • Génération et utilisation locale de la clé maître utilisateur.
  • Protection de la clé maître via une enveloppe chiffrée locale.
  • Dérivation de clés documentaires indépendantes par document.
  • Chiffrement et déchiffrement authentifié des fichiers.
  • Validation systématique de l'intégrité cryptographique.
  • Exécution des opérations cryptographiques hors thread UI.
  • Effacement en mémoire des buffers sensibles après usage.
  • Tests cryptographiques basés sur des vecteurs officiels.
  • Mesures de performance sur terminaux iOS cibles.
  • Documentation du comportement cryptographique côté iOS.

Exclu

  • Implémentation Android, Web ou Desktop.
  • Authentification SRP-6a côté backend.
  • Proxy Re-Encryption (PRE).
  • Gestion des clés serveur ou HSM.
  • Synchronisation ou sauvegarde des clés hors de l'appareil.
  • Architecture cryptographique globale (traitée ailleurs).

Contraintes

  • Sécurité
  • Aucune clé ne doit être transmise au backend.
  • Aucun plaintext ne doit apparaître dans les logs applicatifs.
  • Toute altération des données chiffrées doit entraîner un rejet strict.
  • Les buffers sensibles doivent être effacés dès qu'ils ne sont plus nécessaires.
  • Les paramètres cryptographiques sont figés et non modifiables par l'utilisateur.

  • Conformité cryptographique

  • Utilisation exclusive d'algorithmes standardisés et reconnus.
  • Respect strict des paramètres définis par les spécifications ProbatioVault.
  • Validation obligatoire via vecteurs de test officiels.

  • Performance

  • Les opérations coûteuses doivent être exécutées hors du thread principal.
  • Le chiffrement de fichiers volumineux ne doit pas bloquer l'interface.
  • Les performances doivent rester compatibles avec une UX mobile acceptable.

  • Compatibilité iOS

  • Implémentation conforme aux capacités cryptographiques iOS.
  • Compatibilité avec la version iOS cible de l'application.

Hypothèses

  • Le mot de passe utilisateur est déjà disponible côté client iOS au moment de la dérivation.
  • Les mécanismes de stockage sécurisé des clés locales sont traités par d'autres User Stories.
  • Les paramètres cryptographiques sont définis et figés dans les spécifications ProbatioVault.
  • Les bibliothèques cryptographiques utilisées respectent les exigences de sécurité du projet.

Diagrammes

Diagramme d'états — Cycle de vie des clés cryptographiques

Le pipeline cryptographique traverse plusieurs états, de la saisie du mot de passe jusqu'au chiffrement/déchiffrement du document. Chaque transition correspond à une opération cryptographique déterministe et irréversible.

Invariants : Aucune clé, mot de passe ou donnée en clair ne quitte l'appareil (zero-knowledge strict). Les buffers sensibles sont effacés après usage (zeroization).

stateDiagram-v2
    [*] --> PasswordAvailable : Utilisateur saisit<br/>le mot de passe

    PasswordAvailable --> KEncryptionDerived : Argon2id<br/>(RFC 9106)
    note right of KEncryptionDerived
        Dérivation déterministe
        Paramètres figés (non modifiables)
    end note

    KEncryptionDerived --> KMasterUnlocked : Déchiffrement<br/>enveloppe K_master
    KEncryptionDerived --> KMasterGenerated : Première utilisation :<br/>génération K_master (CSPRNG)

    KMasterGenerated --> EnvelopeCreated : Chiffrement K_master<br/>dans enveloppe locale
    EnvelopeCreated --> KMasterUnlocked : Enveloppe stockée

    KMasterUnlocked --> KDocDerived : HKDF<br/>(RFC 5869)<br/>par document

    KDocDerived --> DocumentEncrypted : AES-256-GCM encrypt<br/>(NIST SP 800-38D)
    KDocDerived --> DocumentDecrypted : AES-256-GCM decrypt<br/>+ vérification tag

    DocumentEncrypted --> BuffersZeroized : Effacement mémoire<br/>(zeroize)
    DocumentDecrypted --> BuffersZeroized : Effacement mémoire<br/>(zeroize)

    BuffersZeroized --> [*]

Diagramme de séquence — Chiffrement d'un document (flux nominal)

Ce diagramme détaille les interactions entre les composants lors du chiffrement d'un document. Le backend ne reçoit jamais de clé ni de donnée en clair.

Invariants : IV unique par chiffrement (12 bytes, CSPRNG). Tag GCM 16 bytes (128 bits). Format sortie : IV || Ciphertext || AuthTag. Opérations cryptographiques exécutées hors thread UI.

sequenceDiagram
    participant User as Utilisateur
    participant UI as UI (Main Thread)
    participant Crypto as Module Crypto<br/>(Background Thread)
    participant Store as Stockage Local<br/>(Keychain)
    participant Backend as Backend<br/>(ne voit jamais<br/>les clés/plaintext)

    User->>UI: Sélectionne document<br/>à protéger

    UI->>Crypto: encryptDocument(plaintext, docId)
    activate Crypto

    Note over Crypto: Hors thread UI<br/>(pas de freeze)

    Crypto->>Store: Récupérer enveloppe K_master
    Store-->>Crypto: enveloppe chiffrée

    Crypto->>Crypto: Argon2id(password) → K_encryption
    Crypto->>Crypto: Déchiffrer enveloppe → K_master
    Crypto->>Crypto: HKDF(K_master, docId) → K_doc

    Crypto->>Crypto: Générer IV (12 bytes, CSPRNG)
    Crypto->>Crypto: AES-256-GCM encrypt(K_doc, IV, plaintext)

    Note over Crypto: Zeroize K_encryption,<br/>K_master, K_doc, plaintext

    Crypto-->>UI: IV || Ciphertext || AuthTag (16 bytes)
    deactivate Crypto

    UI->>Backend: Upload ciphertext<br/>(aucune clé transmise)
    Backend-->>UI: Confirmation stockage

    UI-->>User: Document protégé

Diagramme de séquence — Déchiffrement d'un document (flux nominal)

Invariants : Toute altération des données chiffrées entraîne un rejet strict (vérification tag GCM). Le plaintext n'apparaît jamais dans les logs.

sequenceDiagram
    participant User as Utilisateur
    participant UI as UI (Main Thread)
    participant Crypto as Module Crypto<br/>(Background Thread)
    participant Store as Stockage Local<br/>(Keychain)
    participant Backend as Backend

    User->>UI: Demande accès document

    UI->>Backend: Télécharger ciphertext
    Backend-->>UI: IV || Ciphertext || AuthTag

    UI->>Crypto: decryptDocument(ciphertext, docId)
    activate Crypto

    Crypto->>Store: Récupérer enveloppe K_master
    Store-->>Crypto: enveloppe chiffrée

    Crypto->>Crypto: Argon2id(password) → K_encryption
    Crypto->>Crypto: Déchiffrer enveloppe → K_master
    Crypto->>Crypto: HKDF(K_master, docId) → K_doc

    Crypto->>Crypto: Extraire IV (12 premiers bytes)
    Crypto->>Crypto: AES-256-GCM decrypt(K_doc, IV, ciphertext)

    alt Tag GCM valide
        Crypto-->>UI: plaintext
        Note over Crypto: Zeroize K_encryption,<br/>K_master, K_doc
        UI-->>User: Document affiché
    else Tag GCM invalide (altération détectée)
        Crypto-->>UI: Erreur : intégrité compromise
        Note over Crypto: Zeroize tous buffers<br/>(y compris partiels)
        UI-->>User: Rejet strict :<br/>document corrompu
    end
    deactivate Crypto

Liens documentaires

  • Architecture :
  • Architecture Cryptographique Client iOS
  • EPIC :
  • MOBILE-IOS
  • Sécurité :
  • Spécifications Techniques ProbatioVault — v2.1
  • RFC 9106 (Argon2)
  • RFC 5869 (HKDF)
  • NIST SP 800-38D (AES-GCM)