Keychain est un stockage sécurisé d'identifiants dans iOS, watchOS, macOS et tvOS qui gère les mots de passe, les clés et les certificats au niveau matériel. Contrairement à UserDefaults, les données dans Keychain sont chiffrées et isolées par sandbox de l'application. Selon Apple Developer Documentation, Keychain utilise les mécanismes Secure Enclave et le chiffrement matériel AES-256 pour protéger les informations confidentielles.
Points clés
Keychain est une base de données sécurisée du système d'exploitation Apple conçue pour le stockage sécurisé des mots de passe, des clés cryptographiques, des certificats et d'autres données sensibles. Keychain est apparu pour la première fois dans Mac OS 8.6 en 1999, et sur iOS — depuis la toute première version du SDK.
Keychain résout un problème fondamental du développement mobile : stocker les secrets (tokens, mots de passe, clés de chiffrement) dans un système de fichiers non sécurisé. Contrairement à UserDefaults ou SQLite, les données dans Keychain sont stockées chiffrées et sont automatiquement chiffrées lors de l'écriture sur le disque.
Chaque application iOS fonctionne dans un sandbox isolé et a accès uniquement à son propre keychain. Cependant, le développeur peut configurer un accès partagé à Keychain entre les applications du même développeur via keychain access groups. L'iCloud Keychain de l'utilisateur synchronise en outre les données entre les appareils via un chiffrement de bout en bout.
Selon Apple Security White Paper (2025), Keychain utilise un chiffrement matériel AES-256 avec une clé liée à l'identifiant unique de l'appareil (UID), rendant les données inaccessibles lors de l'extraction de l'appareil.
Keychain fonctionne comme un service en couches : l'application accède au Security framework, qui communique avec le démon securityd qui gère la base de données SQLite chiffrée de Keychain. Chaque enregistrement est chiffré avec une clé séparée, et les clés elles-mêmes sont protégées par le module matériel Secure Enclave sur les appareils avec puce A7 et plus récents.
Le Security framework fournit une interface C pour travailler avec Keychain Services. Fonctions principales : SecItemAdd (ajouter), SecItemCopyMatching (rechercher), SecItemUpdate (mettre à jour) et SecItemDelete (supprimer). Chaque opération accepte un dictionnaire d'attributs CFDictionaryRef décrivant le type de requête.
Les données sont classifiées par classes : kSecClassGenericPassword (mot de passe arbitraire), kSecClassInternetPassword (mot de passe de service Internet), kSecClassCertificate (certificat), kSecClassKey (clé cryptographique) et kSecClassIdentity (paire clé-certificat).
Lors de la sauvegarde d'un mot de passe, l'application crée un dictionnaire avec des attributs : service, compte, niveau d'accès, étiquette. Le Security framework transmet les données au démon securityd, qui chiffre l'enregistrement avec une clé liée à l'appareil et le stocke dans la base SQLite de Keychain. La récupération fonctionne de manière similaire : requête par attributs, recherche, déchiffrement et retour des données.
Une caractéristique importante : lors de la suppression d'une application, iOS efface automatiquement les enregistrements Keychain créés par cette application (depuis iOS 10.3+). Lors de la réinstallation de l'application, les données Keychain de l'installation précédente ne sont pas disponibles sauf si iCloud Keychain a été utilisé.
import Security
func savePassword(service: String, account: String, password: Data) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: account,
kSecValueData as String: password,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]
SecItemAdd(query as CFDictionary, nil)
}
Keychain prend en charge cinq classes principales de données, chacune avec son propre ensemble d'attributs et domaine d'application. Le choix de la classe détermine quelles clés de recherche sont disponibles et comment les données sont chiffrées.
Les classes kSecClassGenericPassword et kSecClassInternetPassword sont conçues pour stocker des mots de passe textuels. La version Internet stocke en plus les données du serveur : domaine, protocole, port et chemin d'authentification. GenericPassword est utilisé pour stocker tout mot de passe sans liaison au serveur.
Lors de la sauvegarde d'un mot de passe Internet, vous pouvez spécifier kSecAttrServer (domaine), kSecAttrProtocol (HTTPS, FTP, etc.), kSecAttrPort et kSecAttrPath. Cela permet d'identifier précisément l'enregistrement lors du remplissage automatique via AutoFill.
La classe kSecClassKey stocke les clés symétriques (AES) et asymétriques (RSA, EC). La classe kSecClassCertificate stocke les certificats X.509. La classe kSecClassIdentity combine une clé privée et son certificat correspondant en un seul enregistrement.
Pour les clés asymétriques, Keychain prend en charge les attributs : kSecAttrKeyType (RSA, EC), kSecAttrKeySizeInBits (2048, 256), kSecAttrIsPermanent (conserver dans Keychain). Pour les certificats : kSecAttrLabel (nom lisible), kSecAttrSubject (DN du propriétaire), kSecAttrIssuer (DN de l'émetteur).
| Classe Keychain | Objectif | Type de donnée |
|---|---|---|
| kSecClassGenericPassword | Mot de passe d'application | Data (NSString) |
| kSecClassInternetPassword | Mot de passe serveur | Data + attributs serveur |
| kSecClassCertificate | Certificat X.509 | SecCertificate |
| kSecClassKey | Clé cryptographique | SecKey |
| kSecClassIdentity | Clé + certificat | SecIdentity |
L'interface principale pour interagir avec Keychain dans le code natif iOS sont les fonctions du Security framework. Pour Swift et Objective-C, une seule interface C est disponible, enveloppée dans des fonctions pratiques.
La fonction SecItemAdd ajoute un nouvel élément à Keychain. Elle prend en entrée un dictionnaire avec la classe, les données et les attributs. Retourne le statut errSecSuccess (0) ou un code d'erreur. La fonction SecItemCopyMatching effectue une recherche par attributs et retourne les données trouvées.
Pour la recherche, on utilise le drapeau kSecReturnData — si true, la fonction retourne le contenu de l'enregistrement. Le drapeau kSecMatchLimit détermine le nombre de résultats : kSecMatchLimitOne (un) ou kSecMatchLimitAll (tous).
func readPassword(service: String, account: String) -> Data? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: account,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
guard status == errSecSuccess else { return nil }
return item as? Data
}
SecItemUpdate permet de modifier les attributs ou les données d'un enregistrement existant. SecItemDelete supprime tous les enregistrements correspondant au dictionnaire passé. Lors de la suppression, il est important de spécifier suffisamment d'attributs pour ne pas supprimer accidentellement les enregistrements d'autres dans le keychain partagé.
func deletePassword(service: String, account: String) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: account
]
SecItemDelete(query as CFDictionary)
}
Chaque enregistrement Keychain possède l'attribut kSecAttrAccessible, qui détermine quand les données sont disponibles en lecture. Ceci est crucial pour la sécurité : un mauvais niveau d'accès peut rendre les données vulnérables ou, au contraire, indisponibles au moment nécessaire.
kSecAttrAccessibleWhenUnlocked — données disponibles uniquement lorsque l'appareil est déverrouillé. kSecAttrAccessibleAfterFirstUnlock — disponibles après le premier déverrouillage après redémarrage. kSecAttrAccessibleAlways — toujours disponibles (déconseillé). Le suffixe ThisDeviceOnly empêche le transfert de données via la sauvegarde.
Sur les appareils avec Secure Enclave, la clé de chiffrement de Keychain peut être en outre protégée par biométrie : kSecAccessControlBiometryCurrentSet ou kSecAccessControlUserPresence. Cela ajoute une exigence Face ID ou Touch ID pour chaque opération de lecture.
iCloud Keychain synchronise les enregistrements entre les appareils Apple via un chiffrement de bout en bout. Apple n'a pas accès aux données déchiffrées. Pour activer la synchronisation, ajoutez l'attribut kSecAttrSynchronizable avec la valeur kCFBooleanTrue.
Important : les enregistrements synchronisés ne peuvent pas contenir l'attribut ThisDeviceOnly, car ils doivent être disponibles sur d'autres appareils. En cas de perte de tous les appareils, iCloud Keychain peut être restauré via un code de récupération ou une clé de récupération iCloud.
Pour les tokens d'authentification, utilisez kSecAttrAccessibleWhenUnlockedThisDeviceOnly — données disponibles uniquement lorsque l'appareil est déverrouillé et non copiées dans la sauvegarde. Pour les certificats qui doivent être disponibles pour les tâches en arrière-plan, utilisez kSecAttrAccessibleAfterFirstUnlock. N'utilisez jamais kSecAttrAccessibleAlways pour les données sensibles.
Il est recommandé d'ajouter toujours le suffixe ThisDeviceOnly pour les données ne nécessitant pas de synchronisation. Cela évite la copie accidentelle de secrets dans iCloud ou iTunes backup, où ils pourraient être extraits par des outils d'analyse. Pour les données critiques, combinez l'accessibilité avec kSecAccessControlUserPresence — cela ajoute une exigence biométrique ou de code pour le déchiffrement de l'enregistrement.
Lors de l'utilisation d'iCloud Keychain, gardez à l'esprit que les enregistrements synchronisés sont disponibles sur tous les appareils de l'utilisateur : si un attaquant accède à un appareil, les données peuvent être compromises sur tous. Pour les secrets isolés, utilisez ThisDeviceOnly.
Questions fréquentes
UserDefaults stocke les données en texte clair dans un fichier .plist, accessible lors de l'analyse de l'IPA. Keychain chiffre chaque enregistrement séparément, utilise le chiffrement matériel et prend en charge les niveaux d'accès, la biométrie et la synchronisation via iCloud.
À chaque lancement du simulateur iOS, Keychain est effacé. Sur un appareil réel, supprimez l'application — iOS supprimera tous les enregistrements Keychain de ce développeur. Pour un effacement sélectif, appelez SecItemDelete avec les attributs appropriés.
Oui, via keychain access groups. Les applications doivent avoir le même team ID dans le profil de provisionnement et des entitlements avec les mêmes keychain-access-groups. Le développeur configure l'accès partagé dans Xcode Capabilities.
Apple ne documente pas de limite stricte, mais en pratique il est recommandé de ne pas dépasser 1–4 Ko par enregistrement. Pour des volumes plus importants, utilisez le chiffrement de fichiers et stockez la clé dans Keychain, tandis que les données elles-mêmes dans Documents.
Sur un appareil jailbreaké, la protection de Keychain est réduite car l'attaquant obtient un accès root et peut lire la base SQLite de Keychain directement. Pour les données critiques, utilisez un chiffrement supplémentaire avec une clé obtenue du serveur.
Résumé
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.
Lisez aussi