Sobes.tech
Middle

Où stockeriez-vous les données protégées de l'utilisateur?

sobes.tech IA

Réponse de l'IA

Pour stocker les données protégées de l'utilisateur sur iOS, j'utiliserais les emplacements suivants, en fonction du type de données et du niveau de sécurité :

  1. Keychain Services :

    • Idéal pour stocker de petites quantités d'informations confidentielles, telles que mots de passe, jetons d'autorisation, clés de chiffrement.
    • Le démon système securityd gère le keychain et stocke les données chiffrées sur le disque.
    • Supporte différents niveaux d'accessibilité (par exemple, disponible uniquement lorsque l'appareil est déverrouillé).
    • Les données se synchronisent automatiquement via iCloud Keychain, si activé.
    import Foundation
    import Security
    
    func savePassword(service: String, account: String, password: String) -> OSStatus {
        let data = password.data(using: .utf8)!
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrService as String: service,
            kSecAttrAccount as String: account,
            kSecValueData as String: data
        ]
    
        SecItemDelete(query as CFDictionary) // Supprimer l'entrée existante
        return SecItemAdd(query as CFDictionary, nil) // Ajouter la nouvelle
    }
    
  2. Core Data chiffré / Realm :

    • Pour stocker des données structurées nécessitant un chiffrement au niveau de la base de données.
    • Core Data supporte des extensions tierces pour le chiffrement (par exemple, RNCryptor).
    • Realm Database possède un chiffrement intégré des fichiers de base de données.
    • La clé de chiffrement doit être stockée dans le Keychain.
    // Exemple d'initialisation de Realm avec chiffrement
    import RealmSwift
    
    func setupEncryptedRealm() throws {
        var config = Realm.Configuration()
        if let key = KeychainHelper.getRealmEncryptionKey() { // Récupère la clé depuis le Keychain
            config.encryptionKey = key
        } else {
            // Génère une nouvelle clé, la stocke dans le Keychain et l'utilise
            let newKey = NSMutableData(length: 64)!
            _ = SecRandomCopyBytes(kSecRandomDefault, newKey.length, newKey.mutableBytes)
            KeychainHelper.saveRealmEncryptionKey(key: newKey as Data)
            config.encryptionKey = newKey as Data
        }
    
        let realm = try Realm(configuration: config)
        // Utiliser Realm
    }
    
  3. API de protection de fichiers :

    • Pour chiffrer les fichiers stockés dans le système de fichiers de l'application.
    • iOS chiffre automatiquement les fichiers au niveau du système de fichiers à l'aide de clés gérées par Secure Enclave.
    • Il est possible de définir différents modes de protection (par exemple, complete, completeUnlessOpen, completeUntilFirstUserAuthentication, none) pour contrôler l'accès en fonction de l'état du verrouillage de l'appareil.
    func saveProtectedDataToFile(data: Data, fileName: String) throws {
        let fileManager = FileManager.default
        let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
        guard let documentDirectory = urls.first else { throw NSError(domain: "MyApp", code: 1, userInfo: [NSLocalizedDescriptionKey: "Répertoire de documents non trouvé"]) }
    
        let fileURL = documentDirectory.appendingPathComponent(fileName)
    
        // Définir le mode de protection
        let options: Data.WritingOptions = .atomicWrite
        let protectedOptions: Data.WritingOptions = options.union(.writingWithoutOverwriting) // Juste un exemple, les options réelles de protection sont définies par des attributs de fichier ou dans info.plist
    
        try data.write(to: fileURL, options: options)
    
        // Définir les attributs de protection du système de fichiers (exemple)
        var attributes: [FileAttributeKey : Any] = [:]
        attributes[.protectionKey] = FileProtectionType.complete
        try fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path)
    }
    
  4. Secure Enclave :

    • Coprocesseur matériel, séparé du processeur principal, destiné à stocker et traiter des clés et données cryptographiques.
    • Utilisé pour Touch ID / Face ID et d'autres opérations sensibles.
    • Les clés stockées dans le Secure Enclave ne quittent jamais celle-ci et ne sont pas accessibles au processeur principal ou au système d'exploitation.
    • Idéal pour générer, stocker et utiliser des clés pour la signature ou le chiffrement, où la protection contre les attaques logicielles est importante.
    import CryptoKit
    import LocalAuthentication
    
    func generateAndStoreKeyInSecureEnclave() throws -> P256.Signing.PrivateKey {
        let accessControl = SecAccessControlCreateWithFlags(
            kCFAllocatorDefault,
            kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, // Disponible lorsque le mot de passe est défini
            [.userPresence], // Nécessite l'authentification de l'utilisateur (Touch ID / Face ID)
            nil
        )!
    
        let attributes: [String: Any] = [
            kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
            kSecAttrKeySizeInBits as String: 256,
            kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
            kSecPrivateKeyAttrs as String: [
                kSecAttrIsPermanent as String: true, // La clé sera permanente
                kSecAttrApplicationTag as String: "com.yourapp.signingkey".data(using: .utf8)!, // Étiquette unique
                kSecAttrAccessControl as String: accessControl
            ]
        ]
    
        var error: Unmanaged<CFError>?
        guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
            throw error!.takeRetainedValue() as Error
        }
    
        // La clé peut être récupérée du Secure Enclave par l'étiquette pour utilisation
        return try P256.Signing.PrivateKey(rawRepresentation: privateKeyData) // Exemple, nécessite conversion de SecKey en Data
    }
    

Le choix de l'emplacement de stockage dépend de :

  • La taille des données (petite vs données structurées).
  • Le type de données (mot de passe vs fichier vs clé cryptographique).
  • Le niveau de protection requis.
  • La nécessité de synchronisation entre appareils (Keychain).
  • La nécessité d'authentification de l'utilisateur pour l'accès (Secure Enclave, protection de fichiers).