Aller au contenu

PD-98 — Stockage sécurisé de K_master dans le Keychain iOS


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

Références

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

Objectif

Permettre le stockage local sécurisé de la clé maître utilisateur (K_master) dans le Keychain iOS, de manière non exportable, non synchronisable et accessible uniquement lorsque l'appareil est déverrouillé, afin de garantir la confidentialité et l'intégrité du modèle cryptographique côté client.

Description fonctionnelle

L'application iOS doit stocker la clé maître utilisateur (K_master) dans le Keychain du système, en s'appuyant sur les mécanismes de sécurité natifs d'iOS.

La clé stockée :

  • n'est accessible que lorsque l'appareil est déverrouillé ;
  • est liée exclusivement au device courant ;
  • ne peut pas être exportée, synchronisée ou restaurée sur un autre appareil ;
  • peut être lue, supprimée ou vérifiée par l'application dans le cadre de ses flux normaux (initialisation, déverrouillage, logout).

Aucune information sensible liée à K_master ne doit être exposée dans les logs, l'interface utilisateur ou les traces techniques.

Diagrammes

Cycle de vie de K_master dans le Keychain

K_master traverse trois etats sur le device. Les transitions sont declenchees par les operations CRUD du service keychainStorage. Les contraintes de securite (non-exportabilite, non-synchronisation) s'appliquent a l'etat STORED.

stateDiagram-v2
    [*] --> ABSENT : premier lancement

    ABSENT --> STORED : storeMasterKey(kMaster)\n[Contrainte : WHEN_UNLOCKED_THIS_DEVICE_ONLY]
    STORED --> ABSENT : deleteMasterKey()\n[logout / reset utilisateur]
    STORED --> STORED : storeMasterKey(kMaster)\n[ecrasement idempotent]

    STORED --> INACCESSIBLE : appareil verrouille
    INACCESSIBLE --> STORED : appareil deverrouille

    ABSENT --> ABSENT : deleteMasterKey()\n[idempotent — pas d'erreur]

    note right of STORED
        - Lie au device courant (ThisDeviceOnly)
        - Non exportable, non synchronisable
        - Accessible uniquement device deverrouille
        Ref : Contraintes Securite, Conformite iOS
    end note

    note right of INACCESSIBLE
        getMasterKey() → DEVICE_LOCKED
        Ref : Contraintes Securite
    end note

Flux de stockage et lecture de K_master

Le diagramme ci-dessous detaille les interactions entre l'application, le service de stockage Keychain et le Keychain iOS natif lors des operations de stockage (store) et de lecture (get). Les validations de taille (32 bytes / 256 bits) et l'encodage Base64 sont realises par le service avant tout acces au Keychain.

sequenceDiagram
    participant App as Application iOS
    participant KS as keychainStorage
    participant SS as expo-secure-store
    participant KC as iOS Keychain

    note over App,KC: --- Stockage de K_master ---

    App->>KS: storeMasterKey(kMaster: Uint8Array)
    KS->>KS: valider taille == 32 bytes
    alt taille invalide
        KS-->>App: KeychainError.INVALID_KEY_SIZE
    end
    KS->>KS: uint8ToBase64(kMaster)
    KS->>SS: setItemAsync(key, b64, options)
    note right of SS: options.keychainAccessible =<br/>WHEN_UNLOCKED_THIS_DEVICE_ONLY
    SS->>KC: SecItemAdd / SecItemUpdate
    KC-->>SS: OSStatus
    SS-->>KS: void | error
    alt erreur Keychain
        KS->>KS: mapError(error)
        KS-->>App: KeychainError
    end
    KS->>KS: clearBuffer(b64)
    KS-->>App: KeychainResult<void>

    note over App,KC: --- Lecture de K_master ---

    App->>KS: getMasterKey()
    KS->>SS: getItemAsync(key, options)
    SS->>KC: SecItemCopyMatching
    alt appareil verrouille
        KC-->>SS: errSecInteractionNotAllowed
        SS-->>KS: error
        KS-->>App: KeychainError.DEVICE_LOCKED
    end
    alt cle absente
        KC-->>SS: errSecItemNotFound
        SS-->>KS: null
        KS-->>App: KeychainError.NOT_FOUND
    end
    KC-->>SS: b64 data
    SS-->>KS: b64 string
    KS->>KS: base64ToUint8(b64)
    KS->>KS: valider taille == 32 bytes
    KS->>KS: clearBuffer(b64)
    KS-->>App: KeychainResult<Uint8Array>

Périmètre

Inclus

  • Stockage de K_master dans le Keychain iOS.
  • Accessibilité limitée à l'état "appareil déverrouillé".
  • Non-migrabilité de la clé vers un autre appareil.
  • Lecture sécurisée de K_master par l'application.
  • Suppression explicite de K_master (logout, reset utilisateur).
  • Vérification de la présence d'une clé stockée.
  • Gestion fonctionnelle des erreurs liées à l'accès Keychain.
  • Documentation du mécanisme et de ses limites de sécurité.

Exclu

  • Implémentation Android ou autre plateforme.
  • Synchronisation via iCloud / Keychain partagé.
  • Stockage de secours (fallback) dans un autre mécanisme local.
  • Gestion multi-comptes ou multi-profils.
  • Exposition ou export de K_master sous quelque forme que ce soit.

Contraintes

  • Sécurité
  • K_master ne doit jamais être stockée en clair hors du Keychain.
  • La clé ne doit jamais être loggée, encodée ou affichée.
  • L'attribut "ThisDeviceOnly" doit empêcher toute restauration sur un autre device.
  • Aucun mécanisme de stockage alternatif ne doit être utilisé en cas d'échec.

  • Conformité iOS

  • Utilisation exclusive des mécanismes Keychain supportés par iOS.
  • Respect des attributs de sécurité fournis par le système.
  • Compatibilité avec la version iOS cible de l'application.

  • UX

  • Les erreurs d'accès à la clé doivent être traduites en messages compréhensibles.
  • Les mécanismes biométriques existants peuvent être utilisés sans modifier le parcours utilisateur.

  • Robustesse

  • Les opérations de lecture et suppression doivent être idempotentes.
  • L'effacement mémoire des buffers utilisés est réalisé au mieux après usage.

Hypothèses

  • L'application iOS dispose déjà d'un flux de création et d'utilisation de K_master.
  • Les bibliothèques utilisées permettent l'accès aux attributs Keychain requis.
  • Le modèle cryptographique suppose une seule clé maître par profil local.
  • Les mécanismes biométriques (Face ID / Touch ID) sont optionnels et déjà gérés ailleurs dans l'application.

Liens documentaires

  • Architecture :
  • Mobile iOS Security Architecture
  • EPIC :
  • MOBILE-IOS
  • Sécurité :
  • Modèle de gestion des clés côté client
  • Documentation Keychain iOS (Apple)