Middle
Unde ai stoca datele protejate ale utilizatorului?
sobes.tech AI
Răspuns de la AI
Pentru stocarea datelor protejate ale utilizatorului pe iOS, aș folosi următoarele locații, în funcție de tipul de date și nivelul de securitate:
-
Keychain Services:
- Ideal pentru stocarea unor cantități mici de informații confidențiale, cum ar fi parole, tokenuri de autorizare, chei de criptare.
- Demonul sistem
securitydgestionează keychain-ul și stochează datele într-un mod criptat pe disc. - Suportă diferite niveluri de accesibilitate (de exemplu, disponibil doar când dispozitivul este deblocat).
- Datele sunt sincronizate automat prin iCloud Keychain, dacă este activat.
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) // Șterge înregistrarea existentă return SecItemAdd(query as CFDictionary, nil) // Adaugă înregistrarea nouă } -
Core Data / Realm criptate:
- Pentru stocarea datelor structurate, care necesită criptare la nivel de bază de date.
- Core Data suportă extensii terțe pentru criptare (de exemplu, RNCryptor).
- Realm Database are criptare încorporată a fișierului bazei de date.
- Cheia de criptare trebuie stocată în Keychain.
// Exemplu de inițializare Realm cu criptare import RealmSwift func setupEncryptedRealm() throws { var config = Realm.Configuration() if let key = KeychainHelper.getRealmEncryptionKey() { // Obține cheia din Keychain config.encryptionKey = key } else { // Generează o cheie nouă, o salvează în Keychain și o folosește 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) // Folosește Realm } -
API-uri de protecție a fișierelor:
- Pentru criptarea fișierelor stocate în sistemul de fișiere al aplicației.
- iOS criptează automat fișierele la nivel de sistem de fișiere folosind chei gestionate de Secure Enclave.
- Se pot seta diferite moduri de protecție (de exemplu,
complete,completeUnlessOpen,completeUntilFirstUserAuthentication,none) pentru a controla accesul în funcție de starea de blocare a dispozitivului.
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: "Directorul documentelor nu a fost găsit"]) } let fileURL = documentDirectory.appendingPathComponent(fileName) // Setează modul de protecție let options: Data.WritingOptions = .atomicWrite let protectedOptions: Data.WritingOptions = options.union(.writingWithoutOverwriting) // Exemplu, opțiunile reale de protecție sunt setate prin atributele fișierului sau în info.plist try data.write(to: fileURL, options: options) // Setează atributele de protecție ale sistemului de fișiere (exemplu) var attributes: [FileAttributeKey : Any] = [:] attributes[.protectionKey] = FileProtectionType.complete try fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path) } -
Secure Enclave:
- Procesor hardware, separat de procesorul principal, destinat stocării și procesării cheilor criptografice și datelor.
- Folosit pentru Touch ID / Face ID și alte operațiuni sensibile.
- Cheile stocate în Secure Enclave nu părăsesc niciodată această enclave și nu sunt accesibile procesorului principal sau sistemului de operare.
- Ideal pentru generarea, stocarea și utilizarea cheilor pentru semnare sau criptare, unde protecția împotriva atacurilor software este importantă.
import CryptoKit import LocalAuthentication func generateAndStoreKeyInSecureEnclave() throws -> P256.Signing.PrivateKey { let accessControl = SecAccessControlCreateWithFlags( kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, // Accesibil dacă este setat un cod de acces [.userPresence], // Autentificare utilizator necesară (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, // Cheia va fi permanentă kSecAttrApplicationTag as String: "com.yourapp.signingkey".data(using: .utf8)!, // Etichetă unică kSecAttrAccessControl as String: accessControl ] ] var error: Unmanaged<CFError>? guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else { throw error!.takeRetainedValue() as Error } // Se pot obține cheile din Secure Enclave după etichetă pentru utilizare return try P256.Signing.PrivateKey(rawRepresentation: privateKeyData) // Exemplu, necesită conversie din SecKey în Data }
Alegerea locului de stocare depinde de:
- Dimensiunea datelor (mică vs date structurate).
- Tipul datelor (parolă vs fișier vs cheie criptografică).
- Nivelul de protecție necesar.
- Necesitatea sincronizării între dispozitive (Keychain).
- Necesitatea autentificării utilizatorului pentru acces (Secure Enclave, File Protection).