Middle
Dove conserveresti i dati protetti dell'utente?
sobes.tech AI
Risposta dell'AI
Per memorizzare i dati protetti dell'utente su iOS, utilizzerei i seguenti luoghi, a seconda del tipo di dati e del livello di sicurezza:
-
Keychain Services:
- Ideale per memorizzare piccole quantità di informazioni riservate, come password, token di autorizzazione, chiavi di crittografia.
- Il demone di sistema
securitydgestisce il keychain e memorizza i dati in forma crittografata sul disco. - Supporta diversi livelli di accessibilità (ad esempio, disponibile solo quando il dispositivo è sbloccato).
- I dati vengono sincronizzati automaticamente tramite iCloud Keychain, se abilitato.
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 la voce esistente return SecItemAdd(query as CFDictionary, nil) // Aggiunge la nuova voce } -
Core Data crittografato / Realm:
- Per memorizzare dati strutturati che richiedono crittografia a livello di database.
- Core Data supporta estensioni di terze parti per la crittografia (ad esempio, RNCryptor).
- Realm Database ha la crittografia integrata del file di database.
- La chiave di crittografia deve essere memorizzata nel Keychain.
// Esempio di inizializzazione di Realm con crittografia import RealmSwift func setupEncryptedRealm() throws { var config = Realm.Configuration() if let key = KeychainHelper.getRealmEncryptionKey() { // Ottieni la chiave dal Keychain config.encryptionKey = key } else { // Genera una nuova chiave, salvala nel Keychain e usala 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 Realm } -
API di Protezione File:
- Per crittografare i file memorizzati nel filesystem dell'app.
- iOS crittografa automaticamente i file a livello di filesystem usando chiavi gestite dal Secure Enclave.
- È possibile impostare diversi modi di protezione (ad esempio,
complete,completeUnlessOpen,completeUntilFirstUserAuthentication,none) per controllare l'accesso in base allo stato di blocco 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: "Directory dei documenti non trovata"]) } let fileURL = documentDirectory.appendingPathComponent(fileName) // Imposta il modo di protezione let options: Data.WritingOptions = .atomicWrite let protectedOptions: Data.WritingOptions = options.union(.writingWithoutOverwriting) // Solo un esempio, le opzioni di protezione reali sono impostate tramite attributi del file o in info.plist try data.write(to: fileURL, options: options) // Imposta attributi di protezione del filesystem (esempio) var attributes: [FileAttributeKey : Any] = [:] attributes[.protectionKey] = FileProtectionType.complete try fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path) } -
Secure Enclave:
- Coprocessore hardware, separato dal processore principale, destinato a memorizzare e processare chiavi e dati crittografici.
- Utilizzato per Touch ID / Face ID e altre operazioni sensibili.
- Le chiavi memorizzate nel Secure Enclave non ne escono mai e non sono accessibili al processore principale o al sistema operativo.
- Ideale per generare, memorizzare e usare chiavi per firma o crittografia, dove la protezione da attacchi software è importante.
import CryptoKit import LocalAuthentication func generateAndStoreKeyInSecureEnclave() throws -> P256.Signing.PrivateKey { let accessControl = SecAccessControlCreateWithFlags( kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, // Disponibile quando è impostata la password [.userPresence], // È richiesta l'autenticazione dell'utente (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 chiave sarà permanente kSecAttrApplicationTag as String: "com.yourapp.signingkey".data(using: .utf8)!, // Etichetta unica kSecAttrAccessControl as String: accessControl ] ] var error: Unmanaged<CFError>? guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else { throw error!.takeRetainedValue() as Error } // È possibile ottenere le chiavi dal Secure Enclave tramite l'etichetta per l'uso return try P256.Signing.PrivateKey(rawRepresentation: privateKeyData) // Esempio, è richiesta la conversione da SecKey a Data }
La scelta del luogo di memorizzazione dipende da:
- Dimensione dei dati (piccola vs dati strutturati).
- Tipo di dati (password vs file vs chiave crittografica).
- Livello di protezione richiesto.
- Necessità di sincronizzazione tra dispositivi (Keychain).
- Necessità di autenticazione dell'utente per l'accesso (Secure Enclave, Protezione File).