Sobes.tech
Middle

Kur glabātu lietotāja aizsargātos datus?

sobes.tech AI

Atbilde no AI

iOS drošības datu glabāšanas vietas izvēle ir atkarīga no datu veida un drošības līmeņa:

  1. Keychain Services:

    • Ideāli piemērots neliela apjoma konfidenciālas informācijas glabāšanai, piemēram, paroles, autorizācijas žetoni, šifrēšanas atslēgas.
    • Sistēmas demons securityd pārvalda keychain un glabā datus šifrētā veidā uz diska.
    • Atbalsta dažādus pieejamības līmeņus (piemēram, pieejams tikai ierīces atbloķēšanas laikā).
    • Dati automātiski sinhronizējas caur iCloud Keychain, ja tas ir aktivizēts.
    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) // Dzēš esošo ierakstu
        return SecItemAdd(query as CFDictionary, nil) // Pievieno jaunu ierakstu
    }
    
  2. Encrypted Core Data / Realm:

    • Piemērots strukturētu datu glabāšanai, kas prasa šifrēšanu datu bāzes līmenī.
    • Core Data atbalsta trešo pušu paplašinājumus šifrēšanai (piemēram, RNCryptor).
    • Realm datu bāzei ir iebūvēta faila šifrēšana.
    • Šifrēšanas atslēga jāglabā Keychain.
    // Realm šifrēšanas piemērs
    import RealmSwift
    
    func setupEncryptedRealm() throws {
        var config = Realm.Configuration()
        if let key = KeychainHelper.getRealmEncryptionKey() { // Iegūst atslēgu no Keychain
            config.encryptionKey = key
        } else {
            // Ģenerē jaunu atslēgu, saglabā un izmanto
            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)
        // Izmanto Realm
    }
    
  3. File Protection APIs:

    • Failu šifrēšanai, kas tiek glabāti lietotnes failu sistēmā.
    • iOS automātiski šifrē failus līmeņa failu sistēmā, izmantojot Secure Enclave pārvaldītās atslēgas.
    • Var iestatīt dažādus aizsardzības režīmus (piemēram, complete, completeUnlessOpen, completeUntilFirstUserAuthentication, none), atkarībā no ierīces bloķēšanas stāvokļa.
    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: "Dokumentu mape nav atrasta"])
    
        let fileURL = documentDirectory.appendingPathComponent(fileName)
    
        // Iestatīt aizsardzības režīmu
        let options: Data.WritingOptions = .atomicWrite
        let protectedOptions: Data.WritingOptions = options.union(.writingWithoutOverwriting) // Piemērs, reālas opcijas tiek iestatītas ar faila atribūtiem vai info.plist
    
        try data.write(to: fileURL, options: options)
    
        // Faila sistēmas atribūtu iestatīšana (piemērs)
        var attributes: [FileAttributeKey : Any] = [:]
        attributes[.protectionKey] = FileProtectionType.complete
        try fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path)
    }
    
  4. Secure Enclave:

    • Aparatūras kopprocesors, atdalīts no galvenā procesora, paredzēts kriptogrāfisko atslēgu un datu glabāšanai un apstrādei.
    • Izmanto Touch ID / Face ID un citas jutīgas operācijas.
    • Atslēgas, kas glabājas Secure Enclave, nekad neiziet no tās un nav pieejamas galvenajam procesoram vai operētājsistēmai.
    • Ideāli piemērots raktu ģenerēšanai, glabāšanai un izmantošanai parakstīšanai vai šifrēšanai, kur svarīga ir programmatūras uzbrukumu aizsardzība.
    import CryptoKit
    import LocalAuthentication
    
    func generateAndStoreKeyInSecureEnclave() throws -> P256.Signing.PrivateKey {
        let accessControl = SecAccessControlCreateWithFlags(
            kCFAllocatorDefault,
            kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, // Pieejams tikai ar paroli
            [.userPresence], // Nepieciešama lietotāja autentifikācija (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, // Atslēga būs pastāvīga
                kSecAttrApplicationTag as String: "com.yourapp.signingkey".data(using: .utf8)!, // Unikāls marķētājs
                kSecAttrAccessControl as String: accessControl
            ]
        ]
    
        var error: Unmanaged<CFError>?
        guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
            throw error!.takeRetainedValue() as Error
        }
    
        // Var iegūt atslēgas no Secure Enclave pēc marķētāja izmantošanas
        return try P256.Signing.PrivateKey(rawRepresentation: privateKeyData) // Piemērs, nepieciešama pārvēršana no SecKey uz Data
    }
    

Izvēle ir atkarīga no:

  • Datu apjoma (mazs vs strukturēti dati)
  • Datu veida (parole vs fails vs kriptogrāfiska atslēga)
  • Aizsardzības līmeņa
  • Sinhronizācijas nepieciešamības starp ierīcēm (Keychain)
  • Lietotāja autentifikācijas nepieciešamības (Secure Enclave, File Protection)