Sobes.tech
Middle

Gde biste čuvali zaštićene podatke korisnika?

sobes.tech АИ

Одговор од АИ

Za čuvanje zaštićenih korisničkih podataka na iOS-u, koristio bih sledeća mesta u zavisnosti od tipa podataka i nivoa sigurnosti:

  1. Keychain Services:

    • Idealan za čuvanje malih količina poverljivih informacija, kao što su lozinke, tokeni za autorizaciju, šifrovani ključevi.
    • Sistemski demon securityd upravlja keychain-om i čuva podatke u šifrovanom obliku na disku.
    • Podržava različite nivoe dostupnosti (na primer, dostupno samo kada je uređaj otključan).
    • Podaci se automatski sinhronizuju putem iCloud Keychain-a ako je uključeno.
    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) // Briše postojeći zapis
        return SecItemAdd(query as CFDictionary, nil) // Dodaje novi zapis
    }
    
  2. Encrypted Core Data / Realm:

    • Za skladištenje strukturiranih podataka koji zahtevaju šifrovanje na nivou baze podataka.
    • Core Data podržava spoljne ekstenzije za šifrovanje (na primer, RNCryptor).
    • Realm Database ima ugrađeno šifrovanje fajla baze podataka.
    • Ključ šifrovanja treba čuvati u Keychain-u.
    // Primer inicijalizacije Realm sa šifrovanjem
    import RealmSwift
    
    func setupEncryptedRealm() throws {
        var config = Realm.Configuration()
        if let key = KeychainHelper.getRealmEncryptionKey() { // Dobijanje ključa iz Keychain-a
            config.encryptionKey = key
        } else {
            // Generisanje novog ključa, čuvanje u Keychain i korišćenje
            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)
        // Korišćenje Realm-a
    }
    
  3. File Protection APIs:

    • Za šifrovanje fajlova koji se čuvaju u fajl sistemu aplikacije.
    • iOS automatski šifruje fajlove na nivou fajl sistema pomoću ključeva koje upravlja Secure Enclave.
    • Mogu se postaviti različiti režimi zaštite (na primer, complete, completeUnlessOpen, completeUntilFirstUserAuthentication, none) za kontrolu pristupa u zavisnosti od stanja zaključavanja uređaja.
    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: "Direktorijum za dokumente nije pronađen"]) }
    
        let fileURL = documentDirectory.appendingPathComponent(fileName)
    
        // Postavljanje režima zaštite
        let options: Data.WritingOptions = .atomicWrite
        let protectedOptions: Data.WritingOptions = options.union(.writingWithoutOverwriting) // Samo primer, stvarne opcije zaštite se postavljaju atributima fajla ili u info.plist
    
        try data.write(to: fileURL, options: options)
    
        // Postavljanje atributa zaštite fajl sistema (primer)
        var attributes: [FileAttributeKey : Any] = [:]
        attributes[.protectionKey] = FileProtectionType.complete
        try fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path)
    }
    
  4. Secure Enclave:

    • Hardverski koprocesor, odvojen od glavnog procesora, namenjen za čuvanje i obradu kriptografskih ključeva i podataka.
    • Koristi se za Touch ID / Face ID i druge osetljive operacije.
    • Ključevi koji se čuvaju u Secure Enclave nikada ne napuštaju njegovu sredinu i nisu dostupni glavnom procesoru ili operativnom sistemu.
    • Idealan je za generisanje, čuvanje i korišćenje ključeva za potpisivanje ili šifrovanje, gde je zaštita od softverskih napada važna.
    import CryptoKit
    import LocalAuthentication
    
    func generateAndStoreKeyInSecureEnclave() throws -> P256.Signing.PrivateKey {
        let accessControl = SecAccessControlCreateWithFlags(
            kCFAllocatorDefault,
            kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, // Dostupno kada je postavljen lozinka
            [.userPresence], // Potreban je autentikacija korisnika (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, // Ključ će biti trajni
                kSecAttrApplicationTag as String: "com.yourapp.signingkey".data(using: .utf8)!, // Jedinstveni tag
                kSecAttrAccessControl as String: accessControl
            ]
        ]
    
        var error: Unmanaged<CFError>?
        guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
            throw error!.takeRetainedValue() as Error
        }
    
        // Ključeve iz Secure Enclave možete dobiti putem taga za korišćenje
        return try P256.Signing.PrivateKey(rawRepresentation: privateKeyData) // Primer, potrebno je konvertovanje iz SecKey u Data
    }
    

Izbor mesta za skladištenje zavisi od:

  • Veličine podataka (mali obim vs strukturirani podaci).
  • Tipova podataka (lozinka vs fajl vs kriptografski ključ).
  • Zahtevanog nivoa zaštite.
  • Potrebe za sinhronizacijom između uređaja (Keychain).
  • Potrebe za autentikacijom korisnika za pristup (Secure Enclave, File Protection).