Sobes.tech
Middle

¿Dónde almacenaría los datos protegidos del usuario?

sobes.tech AI

Respuesta de la IA

Para almacenar datos protegidos del usuario en iOS, utilizaría los siguientes lugares, dependiendo del tipo de datos y del nivel de seguridad:

  1. Keychain Services:

    • Ideal para almacenar pequeñas cantidades de información confidencial, como contraseñas, tokens de autorización, claves de cifrado.
    • El demonio del sistema securityd gestiona el keychain y almacena los datos cifrados en disco.
    • Soporta diferentes niveles de accesibilidad (por ejemplo, solo disponible cuando el dispositivo está desbloqueado).
    • Los datos se sincronizan automáticamente a través de iCloud Keychain, si está habilitado.
    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) // Eliminamos la entrada existente
        return SecItemAdd(query as CFDictionary, nil) // Añadimos la nueva entrada
    }
    
  2. Core Data cifrado / Realm:

    • Para almacenar datos estructurados que requieren cifrado a nivel de base de datos.
    • Core Data soporta extensiones de terceros para cifrado (por ejemplo, RNCryptor).
    • Realm Database tiene cifrado de archivos de base de datos incorporado.
    • La clave de cifrado debe almacenarse en Keychain.
    // Ejemplo de inicialización de Realm con cifrado
    import RealmSwift
    
    func setupEncryptedRealm() throws {
        var config = Realm.Configuration()
        if let key = KeychainHelper.getRealmEncryptionKey() { // Obtenemos la clave de Keychain
            config.encryptionKey = key
        } else {
            // Generamos una nueva clave, la almacenamos en Keychain y la usamos
            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)
        // Usamos Realm
    }
    
  3. APIs de protección de archivos:

    • Para cifrar archivos almacenados en el sistema de archivos de la aplicación.
    • iOS cifra automáticamente los archivos a nivel del sistema de archivos usando claves gestionadas por Secure Enclave.
    • Se pueden establecer diferentes modos de protección (por ejemplo, complete, completeUnlessOpen, completeUntilFirstUserAuthentication, none) para controlar el acceso según el estado del bloqueo del dispositivo.
    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: "Directorio de documentos no encontrado"]) }
    
        let fileURL = documentDirectory.appendingPathComponent(fileName)
    
        // Establecemos el modo de protección
        let options: Data.WritingOptions = .atomicWrite
        let protectedOptions: Data.WritingOptions = options.union(.writingWithoutOverwriting) // Solo un ejemplo, las opciones reales de protección se establecen con atributos del archivo o en info.plist
    
        try data.write(to: fileURL, options: options)
    
        // Establecer atributos de protección del sistema de archivos (ejemplo)
        var attributes: [FileAttributeKey : Any] = [:]
        attributes[.protectionKey] = FileProtectionType.complete
        try fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path)
    }
    
  4. Secure Enclave:

    • Procesador de coprocesador hardware, separado del procesador principal, destinado a almacenar y procesar claves y datos criptográficos.
    • Se usa para Touch ID / Face ID y otras operaciones sensibles.
    • Las claves almacenadas en Secure Enclave nunca salen de ella y no están disponibles para el procesador principal o el sistema operativo.
    • Ideal para generar, almacenar y usar claves para firma o cifrado, donde la protección contra ataques de software es importante.
    import CryptoKit
    import LocalAuthentication
    
    func generateAndStoreKeyInSecureEnclave() throws -> P256.Signing.PrivateKey {
        let accessControl = SecAccessControlCreateWithFlags(
            kCFAllocatorDefault,
            kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, // Disponible cuando se establece contraseña
            [.userPresence], // Requiere autenticación del usuario (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 clave será permanente
                kSecAttrApplicationTag as String: "com.yourapp.signingkey".data(using: .utf8)!, // Etiqueta única
                kSecAttrAccessControl as String: accessControl
            ]
        ]
    
        var error: Unmanaged<CFError>?
        guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
            throw error!.takeRetainedValue() as Error
        }
    
        // Se pueden obtener las claves de Secure Enclave por etiqueta para su uso
        return try P256.Signing.PrivateKey(rawRepresentation: privateKeyData) // Ejemplo, se requiere conversión de SecKey a Data
    }
    

La elección del lugar de almacenamiento depende de:

  • Tamaño de los datos (pequeño vs datos estructurados).
  • Tipo de datos (contraseña vs archivo vs clave criptográfica).
  • Nivel de protección requerido.
  • Necesidad de sincronización entre dispositivos (Keychain).
  • Necesidad de autenticación del usuario para acceder (Secure Enclave, protección de archivos).