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:
-
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
securitydgere 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 } -
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 } -
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) } -
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).