Middle
Πού θα αποθηκεύατε τα προστατευμένα δεδομένα του χρήστη;
sobes.tech AI
Απάντηση από AI
Για την αποθήκευση των προστατευμένων δεδομένων χρήστη σε iOS, θα χρησιμοποιούσα τα ακόλουθα μέρη, ανάλογα με τον τύπο των δεδομένων και το επίπεδο ασφαλείας:
-
Keychain Services:
- Ιδανικό για την αποθήκευση μικρών ποσοτήτων εμπιστευτικών πληροφοριών, όπως κωδικούς πρόσβασης, tokens αυθεντικοποίησης, κλειδιά κρυπτογράφησης.
- Ο διακομιστής
securitydδιαχειρίζεται το keychain και αποθηκεύει δεδομένα σε κρυπτογραφημένη μορφή στον δίσκο. - Υποστηρίζει διάφορα επίπεδα προσβασιμότητας (π.χ., διαθέσιμο μόνο όταν η συσκευή είναι ξεκλείδωτη).
- Τα δεδομένα συγχρονίζονται αυτόματα μέσω iCloud Keychain, εάν είναι ενεργοποιημένο.
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) // Διαγράφει την υπάρχουσα εγγραφή return SecItemAdd(query as CFDictionary, nil) // Προσθέτει νέα εγγραφή } -
Κρυπτογραφημένα Core Data / Realm:
- Για την αποθήκευση δομημένων δεδομένων που απαιτούν κρυπτογράφηση σε επίπεδο βάσης δεδομένων.
- Το Core Data υποστηρίζει εξωτερικές επεκτάσεις για κρυπτογράφηση (π.χ., RNCryptor).
- Η βάση δεδομένων Realm διαθέτει ενσωματωμένη κρυπτογράφηση αρχείου.
- Το κλειδί κρυπτογράφησης πρέπει να αποθηκεύεται στο Keychain.
// Παράδειγμα αρχικοποίησης Realm με κρυπτογράφηση import RealmSwift func setupEncryptedRealm() throws { var config = Realm.Configuration() if let key = KeychainHelper.getRealmEncryptionKey() { // Λαμβάνουμε το κλειδί από το Keychain config.encryptionKey = key } else { // Δημιουργούμε νέο κλειδί, το αποθηκεύουμε στο Keychain και το χρησιμοποιούμε 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) // Χρησιμοποιούμε το Realm } -
API προστασίας αρχείων:
- Για κρυπτογράφηση αρχείων που αποθηκεύονται στο σύστημα αρχείων της εφαρμογής.
- Το iOS κρυπτογραφεί αυτόματα τα αρχεία σε επίπεδο συστήματος αρχείων με κλειδιά που διαχειρίζεται το Secure Enclave.
- Μπορούν να οριστούν διάφοροι τρόποι προστασίας (π.χ.,
complete,completeUnlessOpen,completeUntilFirstUserAuthentication,none) για τον έλεγχο πρόσβασης ανάλογα με την κατάσταση κλειδώματος της συσκευής.
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: "Δεν βρέθηκε ο φάκελος εγγράφων"]) } let fileURL = documentDirectory.appendingPathComponent(fileName) // Ορίζουμε τον τρόπο προστασίας let options: Data.WritingOptions = .atomicWrite let protectedOptions: Data.WritingOptions = options.union(.writingWithoutOverwriting) // Παράδειγμα, οι πραγματικές επιλογές προστασίας ορίζονται με τα χαρακτηριστικά αρχείου ή στο info.plist try data.write(to: fileURL, options: options) // Ορίζουμε τα χαρακτηριστικά προστασίας του συστήματος αρχείων (παράδειγμα) var attributes: [FileAttributeKey : Any] = [:] attributes[.protectionKey] = FileProtectionType.complete try fileManager.setAttributes(attributes, ofItemAtPath: fileURL.path) } -
Secure Enclave:
- Υλικό-επεξεργαστής, απομονωμένος από τον κύριο επεξεργαστή, προορισμένος για την αποθήκευση και επεξεργασία κρυπτογραφικών κλειδιών και δεδομένων.
- Χρησιμοποιείται για Touch ID / Face ID και άλλες ευαίσθητες λειτουργίες.
- Τα κλειδιά που αποθηκεύονται στο Secure Enclave ποτέ δεν φεύγουν από αυτό και δεν είναι διαθέσιμα στον κύριο επεξεργαστή ή το λειτουργικό σύστημα.
- Ιδανικό για τη δημιουργία, αποθήκευση και χρήση κλειδιών για υπογραφή ή κρυπτογράφηση, όπου η προστασία από λογισμικό επιθέσεις είναι σημαντική.
import CryptoKit import LocalAuthentication func generateAndStoreKeyInSecureEnclave() throws -> P256.Signing.PrivateKey { let accessControl = SecAccessControlCreateWithFlags( kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, // Διαθέσιμο όταν έχει οριστεί κωδικός [.userPresence], // Απαιτείται αυθεντικοποίηση χρήστη (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, // Το κλειδί θα είναι μόνιμο kSecAttrApplicationTag as String: "com.yourapp.signingkey".data(using: .utf8)!, // Μοναδική ετικέτα kSecAttrAccessControl as String: accessControl ] ] var error: Unmanaged<CFError>? guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else { throw error!.takeRetainedValue() as Error } // Μπορείτε να λάβετε τα κλειδιά από το Secure Enclave μέσω της ετικέτας για χρήση return try P256.Signing.PrivateKey(rawRepresentation: privateKeyData) // Παράδειγμα, απαιτεί μετατροπή από SecKey σε Data }
Η επιλογή του χώρου αποθήκευσης εξαρτάται από:
- Το μέγεθος των δεδομένων (μικρό όγκο vs δομημένα δεδομένα).
- Τον τύπο των δεδομένων (κωδικός πρόσβασης vs αρχείο vs κρυπτογραφικό κλειδί).
- Το απαιτούμενο επίπεδο προστασίας.
- Την ανάγκη συγχρονισμού μεταξύ συσκευών (Keychain).
- Την ανάγκη αυθεντικοποίησης χρήστη για πρόσβαση (Secure Enclave, File Protection).