Sobes.tech
Middle

Onde armazenaria os dados protegidos do utilizador?

sobes.tech IA

Resposta da IA

Para armazenar dados protegidos do utilizador no iOS, utilizaria os seguintes locais, dependendo do tipo de dados e do nível de segurança:

  1. Keychain Services:

    • Ideal para armazenar pequenas quantidades de informações confidenciais, como palavras-passe, tokens de autorização, chaves de encriptação.
    • O demon do sistema securityd gere o keychain e armazena os dados encriptados no disco.
    • Suporta diferentes níveis de acessibilidade (por exemplo, disponível apenas quando o dispositivo está desbloqueado).
    • Os dados sincronizam-se automaticamente através do iCloud Keychain, se estiver ativado.
    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) // Elimina a entrada existente
        return SecItemAdd(query as CFDictionary, nil) // Adiciona a nova entrada
    }
    
  2. Core Data encriptado / Realm:

    • Para armazenar dados estruturados que requerem encriptação ao nível da base de dados.
    • Core Data suporta extensões de terceiros para encriptação (por exemplo, RNCryptor).
    • Realm Database tem encriptação de ficheiros de base de dados incorporada.
    • A chave de encriptação deve ser armazenada no Keychain.
    // Exemplo de inicialização do Realm com encriptação
    import RealmSwift
    
    func setupEncryptedRealm() throws {
        var config = Realm.Configuration()
        if let key = KeychainHelper.getRealmEncryptionKey() { // Obtém a chave do Keychain
            config.encryptionKey = key
        } else {
            // Gera uma nova chave, armazena-a no Keychain e usa-a
            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)
        // Usa o Realm
    }
    
  3. APIs de Proteção de Ficheiros:

    • Para encriptar ficheiros armazenados no sistema de ficheiros da aplicação.
    • iOS encripta automaticamente os ficheiros ao nível do sistema de ficheiros usando chaves geridas pelo Secure Enclave.
    • Pode definir diferentes modos de proteção (por exemplo, complete, completeUnlessOpen, completeUntilFirstUserAuthentication, none) para controlar o acesso consoante o estado do bloqueio do 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: "Diretório de documentos não encontrado"]) }
    
        let fileURL = documentDirectory.appendingPathComponent(fileName)
    
        // Define o modo de proteção
        let options: Data.WritingOptions = .atomicWrite
        let protectedOptions: Data.WritingOptions = options.union(.writingWithoutOverwriting) // Apenas um exemplo, as opções reais de proteção são definidas por atributos do ficheiro ou no info.plist
    
        try data.write(to: fileURL, options: options)
    
        // Define atributos de proteção do sistema de ficheiros (exemplo)
        var attributes: [FileAttributeKey : Any] = [:]
        attributes[.protectionKey] = FileProtectionType.complete
        try fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path)
    }
    
  4. Secure Enclave:

    • Coprocesso de hardware separado do processador principal, destinado a armazenar e processar chaves e dados criptográficos.
    • Usado para Touch ID / Face ID e outras operações sensíveis.
    • As chaves armazenadas no Secure Enclave nunca saem dele e não estão acessíveis ao processador principal ou ao sistema operativo.
    • Ideal para gerar, armazenar e usar chaves para assinatura ou encriptação, onde a proteção contra ataques de software é importante.
    import CryptoKit
    import LocalAuthentication
    
    func generateAndStoreKeyInSecureEnclave() throws -> P256.Signing.PrivateKey {
        let accessControl = SecAccessControlCreateWithFlags(
            kCFAllocatorDefault,
            kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, // Disponível quando a palavra-passe está definida
            [.userPresence], // Requer autenticação do utilizador (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, // A chave 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
        }
    
        // Pode obter chaves do Secure Enclave pela etiqueta para uso
        return try P256.Signing.PrivateKey(rawRepresentation: privateKeyData) // Exemplo, requer conversão de SecKey para Data
    }
    

A escolha do local de armazenamento depende de:

  • Tamanho dos dados (pequeno vs dados estruturados).
  • Tipo de dados (palavra-passe vs ficheiro vs chave criptográfica).
  • Nível de proteção requerido.
  • Necessidade de sincronização entre dispositivos (Keychain).
  • Necessidade de autenticação do utilizador para acesso (Secure Enclave, Proteção de Ficheiros).