Middle
Kde byste uchovávali chráněná uživatelská data?
sobes.tech AI
Odpověď od AI
Pro ukládání chráněných uživatelských dat na iOS bych použil následující místa v závislosti na typu dat a úrovni zabezpečení:
-
Keychain Services:
- Ideální pro ukládání malého objemu důvěrných informací, jako jsou hesla, autorizační tokeny, šifrovací klíče.
- Systémový démon
securitydspravuje keychain a ukládá data zašifrovaná na disku. - Podporuje různé úrovně dostupnosti (například dostupné pouze při odemknutém zařízení).
- Data se automaticky synchronizují přes iCloud Keychain, pokud je povoleno.
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) // Odstraní existující záznam return SecItemAdd(query as CFDictionary, nil) // Přidá nový záznam } -
Encrypted Core Data / Realm:
- Pro ukládání strukturovaných dat, která vyžadují šifrování na úrovni databáze.
- Core Data podporuje externí rozšíření pro šifrování (například RNCryptor).
- Realm Database má vestavěné šifrování souboru databáze.
- Šifrovací klíč by měl být uložen v Keychain.
// Příklad inicializace Realm s šifrováním import RealmSwift func setupEncryptedRealm() throws { var config = Realm.Configuration() if let key = KeychainHelper.getRealmEncryptionKey() { // Získání klíče z Keychain config.encryptionKey = key } else { // Generování nového klíče, uložení do Keychain a použití 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) // Použití Realm } -
File Protection APIs:
- Pro šifrování souborů uložených v souborovém systému aplikace.
- iOS automaticky šifruje soubory na úrovni souborového systému pomocí klíčů spravovaných Secure Enclave.
- Lze nastavit různé režimy ochrany (například
complete,completeUnlessOpen,completeUntilFirstUserAuthentication,none) pro řízení přístupu v závislosti na stavu zamčení zařízení.
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: "Dokumentární adresář nenalezen"]) } let fileURL = documentDirectory.appendingPathComponent(fileName) // Nastavení režimu ochrany let options: Data.WritingOptions = .atomicWrite let protectedOptions: Data.WritingOptions = options.union(.writingWithoutOverwriting) // Příklad, skutečné možnosti ochrany jsou nastaveny atributy souboru nebo v info.plist try data.write(to: fileURL, options: options) // Nastavení atributů ochrany souborového systému (příklad) var attributes: [FileAttributeKey : Any] = [:] attributes[.protectionKey] = FileProtectionType.complete try fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path) } -
Secure Enclave:
- Hardwarový koprocesor, oddělený od hlavního procesoru, určený pro ukládání a zpracování kryptografických klíčů a dat.
- Používá se pro Touch ID / Face ID a další citlivé operace.
- Klíče uložené v Secure Enclave nikdy neopouštějí jeho prostředí a nejsou dostupné hlavnímu procesoru nebo operačnímu systému.
- Ideální pro generování, ukládání a používání klíčů pro podpis nebo šifrování, kde je důležitá ochrana před softwarovými útoky.
import CryptoKit import LocalAuthentication func generateAndStoreKeyInSecureEnclave() throws -> P256.Signing.PrivateKey { let accessControl = SecAccessControlCreateWithFlags( kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, // Přístupné při nastaveném hesle [.userPresence], // Vyžaduje autentizaci uživatele (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, // Klíč bude trvalý kSecAttrApplicationTag as String: "com.yourapp.signingkey".data(using: .utf8)!, // Unikátní štítek kSecAttrAccessControl as String: accessControl ] ] var error: Unmanaged<CFError>? guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else { throw error!.takeRetainedValue() as Error } // Klíče lze získat z Secure Enclave podle štítku pro použití return try P256.Signing.PrivateKey(rawRepresentation: privateKeyData) // Příklad, je třeba převést z SecKey na Data }
Výběr místa ukládání závisí na:
- Velikosti dat (malé objemy vs strukturovaná data).
- Typu dat (heslo vs soubor vs kryptografický klíč).
- Požadované úrovně ochrany.
- Potřeby synchronizace mezi zařízeními (Keychain).
- Potřeby autentizace uživatele pro přístup (Secure Enclave, File Protection).