Keychain sur iOS : définition, architecture et travail avec les secrets

Auteur : IT Sectr Publié le : 2026-04-04 Temps de lecture : 9 min

Keychain est un stockage sécurisé sur iOS conçu pour sauvegarder en toute sécurité des mots de passe, des clés cryptographiques, des certificats et des notes confidentielles. Selon Apple Security Documentation (2025), Keychain utilise un chiffrement matériel via Secure Enclave sur tous les appareils équipés d'une puce A7 et plus récents. Comprendre l'architecture de iOS Keychain est essentiel pour chaque développeur afin de stocker correctement les jetons et les secrets de l'application.

Points clés

  • iOS Keychain est une base de données SQLite chiffrée pour stocker des secrets avec une protection matérielle via Secure Enclave.
  • Protection Class détermine quand les données sont disponibles : lorsque l'appareil est déverrouillé, après le premier déverrouillage, ou toujours.
  • Access Control List (ACL) est un mécanisme pour restreindre l'accès aux éléments Keychain, y compris l'authentification biométrique.
  • SecItemAdd et SecItemCopyMatching sont les principales API du framework Security pour écrire et lire des éléments.
  • kSecAttrSynchronizable est le flag qui permet la synchronisation Keychain via iCloud pour un accès sur tous les appareils de l'utilisateur.

Qu'est-ce que Keychain sur iOS ?

iOS Keychain est un mécanisme sécurisé pour stocker des données confidentielles, intégré au système d'exploitation d'Apple. Contrairement à UserDefaults ou aux fichiers ordinaires, Keychain chiffre tous les éléments au niveau matériel et fournit un contrôle d'accès fin basé sur des politiques de sécurité.

Keychain a été introduit dans iOS 2.0 et a depuis subi des changements significatifs : iOS 7 a ajouté la prise en charge des clés matérielles via Secure Enclave, iOS 9 a introduit le partage Keychain entre applications via Access Groups, iOS 13 a ajouté la prise en charge de la liaison biométrique via LAContext. Selon Apple WWDC Session (2024), plus de 90% des applications iOS dans le top 100 de l'App Store utilisent Keychain pour stocker les jetons d'authentification.

Architecturalement, Keychain est une base de données SQLite chiffrée située en dehors du sandbox de l'application. Chaque élément (SecItem) est chiffré avec une clé séparée qui, à son tour, est protégée par la clé matérielle Secure Enclave. Le service système Securityd gère l'accès à Keychain en fonction des entitlements de l'application et de la classe de protection demandée.

Un avantage important de Keychain par rapport aux autres méthodes de stockage : les données sont automatiquement chiffrées et déchiffrées par l'OS. Le développeur n'a pas besoin d'implémenter manuellement la cryptographie - il suffit d'appeler SecItemAdd avec les bons paramètres. iOS garantit que les données de Keychain ne peuvent pas être lues par d'autres applications (lorsque les Access Groups sont correctement configurés).

Architecture de Keychain

L'architecture Keychain comprend plusieurs niveaux : physique (Secure Enclave), système (Security.framework), application (API SecItem*) et logique (Access Groups, Protection Classes). Comprendre chaque niveau aide à concevoir correctement le stockage des secrets.

SecItemAdd et SecItemCopyMatching

L'API principale pour travailler avec Keychain sont les fonctions du framework Security : SecItemAdd pour ajouter, SecItemCopyMatching pour lire, SecItemUpdate pour mettre à jour et SecItemDelete pour supprimer. Chaque fonction prend un dictionnaire query qui décrit les attributs de l'élément à rechercher ou à sauvegarder.

Attributs clés de query : kSecClass - type d'élément (kSecClassGenericPassword, kSecClassKey, kSecClassCertificate), kSecAttrAccount - identifiant unique au sein de la classe, kSecValueData - données sauvegardées (Data), kSecAttrAccessible - classe de protection. SecItemCopyMatching avec le flag kSecReturnData retourne les données de l'élément, avec kSecMatchLimit - le nombre de résultats.

Important : toutes les fonctions retournent un OSStatus. Une opération réussie retourne errSecSuccess (0). Erreurs : errSecItemNotFound (-25300) - élément non trouvé, errSecDuplicateItem (-25299) - l'élément existe déjà, errSecAuthFailed (-25293) - échec de l'authentification biométrique. Le développeur doit traiter chaque statut correctement.

Classes de protection (Protection Class)

Protection Class est l'attribut kSecAttrAccessible qui détermine quand les données dans Keychain sont disponibles pour la lecture. iOS prend en charge six classes de protection avec différents niveaux de disponibilité et de sécurité.

La classe recommandée pour la plupart des scénarios est kSecAttrAccessibleWhenUnlockedThisDeviceOnly : les données sont uniquement disponibles lorsque l'appareil est déverrouillé et ne sont pas copiées dans iCloud Backup. Pour les données qui doivent être disponibles après redémarrage (mais seulement après le premier déverrouillage), utilisez kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly. Pour les données critiques nécessitant une authentification biométrique à chaque accès, combinez kSecAttrAccessibleWhenUnlockedThisDeviceOnly avec une ACL exigeant la biométrie.

Les classes sans le suffixe ThisDeviceOnly (kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAfterFirstUnlock) permettent la copie dans iCloud Backup. C'est pratique pour l'utilisateur mais réduit la sécurité - les données peuvent être restaurées à partir de la sauvegarde. Pour les jetons d'authentification, utilisez toujours ThisDeviceOnly.

Listes de contrôle d'accès (ACL)

Access Control List (ACL) est un mécanisme qui restreint les opérations sur un élément Keychain en fonction de l'authentification de l'utilisateur. L'ACL est définie via SecAccessControlCreateWithFlags et transmise à l'attribut kSecAttrAccessControl lors de la sauvegarde d'un élément.

Flags pris en charge : kSecAccessControlUserPresence - toute authentification (Face ID, Touch ID ou code d'accès), kSecAccessControlBiometryCurrentSet - biométrie uniquement (empreintes digitales ou visage actuellement enregistrés), kSecAccessControlDevicePasscode - code d'accès uniquement. L'ACL s'applique à chaque opération : la lecture, la mise à jour et la suppression d'un élément nécessitent également une authentification.

Sur iOS 15+, le flag kSecAccessControlWatch est apparu - pour Apple Watch, qui permet l'authentification via une montre jumelée. L'ACL peut être combinée : par exemple, kSecAccessControlUserPresence ou kSecAccessControlBiometryAny avec un code d'accès optionnel (orientation .or).

Types de données dans Keychain

iOS Keychain prend en charge quatre classes principales d'éléments (kSecClass), chacune conçue pour son propre type de données. Choisir la bonne classe simplifie l'organisation et la recherche d'éléments.

kSecClassGenericPassword - mot de passe générique : la classe la plus utilisée. Stocke des données binaires arbitraires (Data) avec une clé unique (kSecAttrAccount). Adapté aux jetons, clés API, codes PIN. Ne nécessite pas d'entitlements supplémentaires pour être utilisé.

kSecClassInternetPassword - mot de passe Internet : stocke les données associées à une ressource réseau. Attributs supplémentaires : kSecAttrServer (domaine du serveur), kSecAttrProtocol (https, ftp), kSecAttrPort, kSecAttrAuthenticationType. iOS peut remplir automatiquement ces mots de passe via AutoFill.

kSecClassKey - clé cryptographique : pour stocker des clés de chiffrement (AES, RSA, EC). La clé est stockée comme SecKeyRef, pas comme Data. kSecClassCertificate - certificat X.509 pour stocker et vérifier des certificats numériques. Les deux classes nécessitent une compréhension des opérations cryptographiques et une configuration correcte des attributs.

Dans la pratique, 95% des cas d'utilisation de Keychain dans les applications mobiles sont couverts par kSecClassGenericPassword pour stocker les jetons d'authentification et kSecClassKey pour stocker les clés de chiffrement privées. kSecClassCertificate est rarement utilisé - généralement dans les applications d'entreprise avec leur propre PKI.

Exemples de code : travailler avec Keychain en Swift

Examinons des exemples pratiques de travail avec Keychain en Swift utilisant le framework Security. Chaque exemple inclut la gestion des erreurs et la configuration correcte de la Protection Class.

Sauvegarder et lire un jeton

Un exemple de base sauvegarde un jeton d'authentification dans Keychain avec la protection WhenUnlockedThisDeviceOnly. La clé (kSecAttrAccount) est l'identifiant du service, les données (kSecValueData) sont le jeton au format Data.

swift
import Security

enum KeychainError: Error {
    case unexpectedStatus(OSStatus)
}

func saveToken(token: String, service: String) throws {
    let data = Data(token.utf8)
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrService as String: service,
        kSecAttrAccount as String: "auth_token",
        kSecValueData as String: data,
        kSecAttrAccessible as String:
            kSecAttrAccessibleWhenUnlockedThisDeviceOnly
    ]
    SecItemDelete(query as CFDictionary)
    let status = SecItemAdd(query as CFDictionary, nil)
    guard status == errSecSuccess else {
        throw KeychainError.unexpectedStatus(status)
    }
}

func readToken(service: String) throws -> String {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrService as String: service,
        kSecAttrAccount as String: "auth_token",
        kSecReturnData as String: true,
        kSecMatchLimit as String: kSecMatchLimitOne
    ]
    var result: AnyObject?
    let status = SecItemCopyMatching(
        query as CFDictionary, &result
    )
    guard status == errSecSuccess,
        let data = result as? Data else {
        throw KeychainError.unexpectedStatus(status)
    }
    return String(decoding: data, as: UTF8.self)
}

Sauvegarder avec liaison biométrique

L'exemple montre l'utilisation de SecAccessControlCreateWithFlags pour lier une clé à la biométrie. Chaque accès à l'élément nécessitera Face ID ou Touch ID.

swift
import LocalAuthentication

func saveWithBiometry(data: Data, key: String) throws {
    let accessControl = SecAccessControlCreateWithFlags(
        nil,
        kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
        .biometryCurrentSet,
        nil
    )

    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: key,
        kSecValueData as String: data,
        kSecAttrAccessControl as String: accessControl as Any
    ]

    SecItemDelete(query as CFDictionary)
    let status = SecItemAdd(query as CFDictionary, nil)
    guard status == errSecSuccess else {
        throw KeychainError.unexpectedStatus(status)
    }
}

Partage Keychain entre applications

L'exemple montre la configuration d'un Access Group pour l'accès partagé à Keychain entre applications du même développeur. Nécessite l'entitlement keychain-access-groups.

swift
// Capabilities: Keychain Sharing activé
// App IDs: group.com.example.shared

func saveSharedToken(token: Data) {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: "shared_token",
        kSecValueData as String: token,
        kSecAttrAccessGroup as String:
            "group.com.example.shared",
        kSecAttrAccessible as String:
            kSecAttrAccessibleWhenUnlockedThisDeviceOnly
    ]
    SecItemAdd(query as CFDictionary, nil)
}

Bonnes pratiques pour travailler avec Keychain

L'utilisation correcte de iOS Keychain nécessite de suivre plusieurs règles clés qui préviennent les vulnérabilités courantes et la perte de données.

Utilisez ThisDeviceOnly pour tous les secrets d'authentification : kSecAttrAccessibleWhenUnlockedThisDeviceOnly garantit que les jetons ne finissent pas dans iCloud Backup. Si un attaquant accède à la sauvegarde, les données Keychain avec ce flag ne seront pas disponibles. L'exception concerne les données qui doivent être disponibles sur tous les appareils de l'utilisateur (par exemple, les clés de chiffrement pour des services propriétaires), pour lesquelles utilisez kSecAttrAccessibleWhenUnlocked avec kSecAttrSynchronizable.

Ne stockez pas les mots de passe en clair - stockez des hachages ou des jetons de session. Le Apple Security Guide (2025) recommande de ne jamais enregistrer le mot de passe de l'utilisateur dans Keychain en texte clair. Enregistrez plutôt le jeton d'actualisation reçu du serveur après une authentification réussie via OAuth 2.0. Le mot de passe est uniquement utilisé pour obtenir le jeton et est immédiatement supprimé de la mémoire.

Traitez correctement les erreurs Keychain : chaque opération Keychain retourne un OSStatus qui doit être vérifié. Portez une attention particulière à errSecItemNotFound (jeton expiré ou supprimé) et errSecAuthFailed (échec biométrique). Dans le premier cas, l'application doit demander une nouvelle authentification ; dans le second, montrer à l'utilisateur une méthode alternative (code d'accès). N'ignorez jamais le statut errSecItemNotFound - cela provoquera un crash lors de la tentative de lecture de nil.

Testez Keychain sur un appareil réel : le simulateur n'a pas de Secure Enclave et ne prend pas en charge les ACL biométriques. Vérifiez toujours les scénarios : premier lancement, restauration depuis une sauvegarde, changement de mot de passe de l'appareil, suppression et réinstallation de l'application. Sur un appareil réel, Keychain persiste lors de la suppression de l'application, mais seulement si le flag kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly n'a pas été utilisé, qui est effacé lorsque le code d'accès est supprimé.

Minimisez le nombre d'opérations Keychain : chaque opération de lecture ou d'écriture est un appel au service système Securityd, qui peut bloquer le thread. Mettez en cache les jetons lus en mémoire pendant la session et accédez à nouveau à Keychain uniquement lors du redémarrage de l'application ou d'une erreur d'authentification (401 du serveur). iOS verrouille automatiquement Keychain lorsque l'appareil est verrouillé, planifiez donc la lecture via LAContext avec une demande biométrique.

Foire aux questions

Puis-je sauvegarder des données dans Keychain et les lire après un redémarrage ?

Oui, utilisez la classe de protection kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly ou kSecAttrAccessibleAfterFirstUnlock. Les données seront disponibles après le premier déverrouillage de l'appareil suite à un redémarrage. Pour un accès automatique au lancement de l'application (sans attendre le déverrouillage), utilisez kSecAttrAccessibleAlways, mais cela réduit la sécurité.

Comment effacer Keychain lors de la déconnexion de l'utilisateur ?

Appelez SecItemDelete avec une requête contenant kSecClass pour chaque type de données. Pour un nettoyage complet de tous les éléments de l'application, exécutez : SecItemDelete([kSecClass as String: kSecClassGenericPassword] as CFDictionary). Répétez pour kSecClassKey, kSecClassCertificate et kSecClassInternetPassword.

Quelle est la différence entre kSecAttrAccessible et kSecAttrAccessControl ?

kSecAttrAccessible détermine quand les données sont disponibles (au déverrouillage, après le premier déverrouillage, etc.). kSecAttrAccessControl détermine qui peut y accéder (biométrie, code d'accès, toute authentification). Ils se combinent : d'abord Protection Class, puis ACL. Par exemple, les données sont disponibles uniquement au déverrouillage ET seulement après Face ID.

Pourquoi SecItemCopyMatching retourne-t-il errSecItemNotFound ?

Raisons : l'élément n'a jamais été sauvegardé, l'élément a été supprimé lors de la suppression du code d'accès (si kSecAttrAccessibleWhenPasscodeSet a été utilisé), l'application a été réinstallée (Keychain persiste mais n'est pas restauré depuis la sauvegarde sur un nouvel appareil), le Access Group ou l'identifiant d'équipe du développeur a changé. Vérifiez kSecAttrService et kSecAttrAccount.

Comment vérifier si l'appareil prend en charge la biométrie dans Keychain ?

Utilisez LAContext de LocalAuthentication : appelez context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil). S'il retourne true, l'appareil prend en charge Touch ID ou Face ID. Pour l'ACL Keychain, utilisez le flag biometryCurrentSet (uniquement les données biométriques actuelles) ou biometryAny (toute donnée enregistrée précédemment).

Résumé

  • iOS Keychain est un stockage protégé par matériel pour les secrets avec chiffrement via Secure Enclave et contrôle d'accès via ACL.
  • Security framework fournit les fonctions SecItemAdd, SecItemCopyMatching, SecItemUpdate et SecItemDelete pour travailler avec les éléments.
  • Protection Class (kSecAttrAccessible) est choisie selon le scénario : WhenUnlockedThisDeviceOnly est la norme pour les jetons.
  • ACL avec biométrie (kSecAttrAccessControl) ajoute une exigence Face ID ou Touch ID pour chaque opération de lecture.
  • kSecClassGenericPassword couvre 95% des cas - stockage de jetons, clés API, codes PIN et notes.
  • ThisDeviceOnly empêche la copie des secrets dans iCloud Backup - obligatoire pour les jetons d'authentification.
  • Traitement correct d'OSStatus et tests sur un appareil réel sont des pratiques essentielles pour une utilisation fiable de Keychain.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi