Middle
Kur saugotumėte naudotojo apsaugotus duomenis?
sobes.tech AI
Atsakymas iš AI
iOS saugojimo saugių duomenų vietos pasirinkimas priklauso nuo duomenų tipo ir saugumo lygio:
-
Keychain Services:
- Idealiai tinka mažo kiekio konfidencialios informacijos saugojimui, pvz., slaptažodžiams, autorizacijos ženkliukams, šifravimo raktams.
- Sisteminis demonas
securitydvaldo keychain ir saugo duomenis šifruotame formate diske. - Palaiko įvairius prieinamumo lygius (pvz., prieinama tik įrenginio atrakintame režime).
- Duomenys automatiškai sinchronizuojami per iCloud Keychain, jei įjungta.
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) // Ištrina esamą įrašą return SecItemAdd(query as CFDictionary, nil) // Prideda naują įrašą } -
Encrypted Core Data / Realm:
- Tinka struktūruotų duomenų saugojimui, reikalaujančių šifravimo bazės lygyje.
- Core Data palaiko trečiųjų šalių plėtinius šifravimui (pvz., RNCryptor).
- Realm duomenų bazė turi įmontuotą failo šifravimą.
- Šifravimo raktas turi būti saugomas Keychain.
// Realm šifravimo pavyzdys import RealmSwift func setupEncryptedRealm() throws { var config = Realm.Configuration() if let key = KeychainHelper.getRealmEncryptionKey() { // Gauti raktą iš Keychain config.encryptionKey = key } else { // Sugeneruoti naują raktą, išsaugoti ir naudoti 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) // Naudoti Realm } -
File Protection APIs:
- Failų šifravimui, saugomam programos failų sistemoje.
- iOS automatiškai šifruoja failus failų sistemos lygyje, naudojant Secure Enclave valdomas raktus.
- Gali būti nustatyti įvairūs apsaugos režimai (pvz.,
complete,completeUnlessOpen,completeUntilFirstUserAuthentication,none) priklausomai nuo įrenginio užrakinimo būsenos.
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: "Dokumento katalogas nerastas"]) let fileURL = documentDirectory.appendingPathComponent(fileName) // Nustatyti apsaugos režimą let options: Data.WritingOptions = .atomicWrite let protectedOptions: Data.WritingOptions = options.union(.writingWithoutOverwriting) // Pavyzdys, tikrosios apsaugos parinktys nustatomos failo atributais arba info.plist try data.write(to: fileURL, options: options) // Failo sistemos atributų nustatymas (pavyzdys) var attributes: [FileAttributeKey : Any] = [:] attributes[.protectionKey] = FileProtectionType.complete try fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path) } -
Secure Enclave:
- Aparatinis papildomas procesorius, atskirtas nuo pagrindinio procesoriaus, skirtas saugoti ir apdoroti kriptografinius raktus ir duomenis.
- Naudojamas Touch ID / Face ID ir kitų jautrių operacijų atlikimui.
- Raktai, saugomi Secure Enclave, niekada neišvyksta iš jos ir nėra prieinami pagrindiniam procesoriui ar operacinei sistemai.
- Idealiai tinka generuoti, saugoti ir naudoti raktus parašui ar šifravimui, kai svarbi programinės įrangos atakų apsauga.
import CryptoKit import LocalAuthentication func generateAndStoreKeyInSecureEnclave() throws -> P256.Signing.PrivateKey { let accessControl = SecAccessControlCreateWithFlags( kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, // Prieinama tik su slaptažodžiu [.userPresence], // Reikalaujama naudotojo autentifikacijos (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, // Raktas bus nuolatinis kSecAttrApplicationTag as String: "com.yourapp.signingkey".data(using: .utf8)!, // Unikalus žymeklis kSecAttrAccessControl as String: accessControl ] ] var error: Unmanaged<CFError>? guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else { throw error!.takeRetainedValue() as Error } // Galima gauti raktus iš Secure Enclave pagal žymeklį naudojimui return try P256.Signing.PrivateKey(rawRepresentation: privateKeyData) // Pavyzdys, reikalinga konversija iš SecKey į Data }
Pasirinkimas priklauso nuo:
- Duomenų dydžio (mažas kiekis vs struktūruoti duomenys)
- Duomenų tipo (slaptažodis vs failas vs kriptografinis raktas)
- Reikalingo saugumo lygio
- Sinchronizacijos tarp įrenginių poreikio (Keychain)
- Naudotojo autentifikacijos poreikio (Secure Enclave, File Protection)