Keychain — είναι ένα ασφαλές αποθετήριο διαπιστευτηρίων σε iOS, watchOS, macOS και tvOS που διαχειρίζεται κωδικούς πρόσβασης, κλειδιά και πιστοποιητικά σε επίπεδο υλικού. Σε αντίθεση με το UserDefaults, τα δεδομένα στο Keychain κρυπτογραφούνται και απομονώνονται από το sandbox της εφαρμογής. Σύμφωνα με το Apple Developer Documentation, το Keychain χρησιμοποιεί μηχανισμούς Secure Enclave και κρυπτογράφηση υλικού AES-256 για την προστασία εμπιστευτικών πληροφοριών.
Κύρια σημεία
Keychain — είναι μια ασφαλής βάση δεδομένων του λειτουργικού συστήματος Apple, σχεδιασμένη για την ασφαλή αποθήκευση κωδικών πρόσβασης, κρυπτογραφικών κλειδιών, πιστοποιητικών και άλλων εμπιστευτικών δεδομένων. Το Keychain εμφανίστηκε για πρώτη φορά στο Mac OS 8.6 το 1999 και στο iOS — από την πρώτη έκδοση SDK.
Το Keychain λύνει ένα θεμελιώδες πρόβλημα ανάπτυξης κινητών: την αποθήκευση μυστικών (token, κωδικών πρόσβασης, κλειδιών κρυπτογράφησης) σε μη προστατευμένο σύστημα αρχείων. Σε αντίθεση με το UserDefaults ή το SQLite, τα δεδομένα στο Keychain αποθηκεύονται σε κρυπτογραφημένη μορφή και κρυπτογραφούνται αυτόματα κατά την εγγραφή στο δίσκο.
Κάθε εφαρμογή iOS λειτουργεί σε απομονωμένο sandbox και έχει πρόσβαση μόνο στο δικό της keychain. Ωστόσο, ο προγραμματιστής μπορεί να ρυθμίσει κοινόχρηστη πρόσβαση στο Keychain μεταξύ εφαρμογών του ίδιου προγραμματιστή μέσω keychain access groups. Ο χρήστης iCloud Keychain επιπλέον συγχρονίζει δεδομένα μεταξύ συσκευών μέσω κρυπτογράφησης end-to-end.
Σύμφωνα με το Apple Security White Paper (2025), το Keychain χρησιμοποιεί κρυπτογράφηση υλικού AES-256 με κλειδί δεσμευμένο στο μοναδικό αναγνωριστικό συσκευής (UID), καθιστώντας τα δεδομένα μη προσβάσιμα κατά την εξαγωγή από τη συσκευή.
Το Keychain λειτουργεί ως υπηρεσία επιπέδων: η εφαρμογή καλεί το Security framework, το οποίο αλληλεπιδρά με τον δαίμονα securityd, που διαχειρίζεται την κρυπτογραφημένη βάση SQLite του Keychain. Κάθε εγγραφή κρυπτογραφείται με ξεχωριστό κλειδί και τα ίδια τα κλειδιά προστατεύονται από την ενότητα υλικού Secure Enclave σε συσκευές με τσιπ A7 και νεότερες.
Το Security framework παρέχει διεπαφή C για εργασία με το Keychain Services. Κύριες συναρτήσεις: SecItemAdd (προσθήκη), SecItemCopyMatching (αναζήτηση), SecItemUpdate (ενημέρωση) και SecItemDelete (διαγραφή). Κάθε λειτουργία λαμβάνει ένα λεξικό χαρακτηριστικών CFDictionaryRef που περιγράφει τον τύπο αιτήματος.
Τα δεδομένα ταξινομούνται σύμφωνα με κλάσεις: kSecClassGenericPassword (τυχαίος κωδικός πρόσβασης), kSecClassInternetPassword (κωδικός πρόσβασης για υπηρεσία διαδικτύου), kSecClassCertificate (πιστοποιητικό), kSecClassKey (κρυπτογραφικό κλειδί) και kSecClassIdentity (συνδυασμός κλειδιού και πιστοποιητικού).
Κατά την αποθήκευση κωδικού πρόσβασης, η εφαρμογή δημιουργεί ένα λεξικό με χαρακτηριστικά: υπηρεσία, λογαριασμός, επίπεδο πρόσβασης, ετικέτα. Security framework μεταφέρει τα δεδομένα στον δαίμονα securityd, ο οποίος κρυπτογραφεί την εγγραφή με κλειδί δεσμευμένο στη συσκευή και την αποθηκεύει στο Keychain SQLite. Η εξαγωγή γίνεται παρόμοια: αίτημα βάσει χαρακτηριστικών, αναζήτηση, αποκρυπτογράφηση και επιστροφή δεδομένων.
Ένα σημαντικό χαρακτηριστικό: κατά τη διαγραφή της εφαρμογής, το iOS αυτόματα καθαρίζει το Keychain από εγγραφές που δημιουργήθηκαν από αυτήν την εφαρμογή (από iOS 10.3+). Κατά την επανεγκατάσταση της εφαρμογής, τα δεδομένα Keychain από την προηγούμενη εγκατάσταση είναι μη προσβάσιμα, εκτός αν χρησιμοποιήθηκε iCloud Keychain.
import Security
func savePassword(service: String, account: String, password: Data) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: account,
kSecValueData as String: password,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]
SecItemAdd(query as CFDictionary, nil)
}
Το Keychain υποστηρίζει πέντε κύριες κλάσεις δεδομένων, κάθε μία με το δικό της σύνολο χαρακτηριστικών και τομέα εφαρμογής. Από την επιλογή κλάσης εξαρτάται ποια κλειδιά αναζήτησης είναι διαθέσιμα και πώς κρυπτογραφούνται τα δεδομένα.
Οι κλάσεις kSecClassGenericPassword και kSecClassInternetPassword προορίζονται για αποθήκευση κωδικών πρόσβασης κειμένου. Η έκδοση Internet επιπλέον αποθηκεύει δεδομένα διακομιστή: τομέα, πρωτόκολλο, θύρα και διαδρομή αυθεντικοποίησης. Το GenericPassword χρησιμοποιείται για αποθήκευση οποιωνδήποτε κωδικών πρόσβασης χωρίς σύνδεση με διακομιστή.
Κατά την αποθήκευση κωδικού πρόσβασης διαδικτύου μπορούν να καθοριστούν kSecAttrServer (τομέας), kSecAttrProtocol (HTTPS, FTP κ.λπ.), kSecAttrPort και kSecAttrPath. Αυτό επιτρέπει την ακριβή αναγνώριση της εγγραφής κατά την αυτόματη συμπλήρωση μέσω AutoFill.
Η κλάση kSecClassKey αποθηκεύει συμμετρικά (AES) και ασύμμετρα (RSA, EC) κλειδιά. Η κλάση kSecClassCertificate — πιστοποιητικά X.509. Η κλάση kSecClassIdentity συνδυάζει το ιδιωτικό κλειδί και το αντίστοιχο πιστοποιητικό σε μία εγγραφή.
Για ασύμμετρα κλειδιά, το Keychain υποστηρίζει χαρακτηριστικά: kSecAttrKeyType (RSA, EC), kSecAttrKeySizeInBits (2048, 256), kSecAttrIsPermanent (αν θα αποθηκευτεί στο Keychain). Για πιστοποιητικά: kSecAttrLabel (όνομα αναγνώσιμο από άνθρωπο), kSecAttrSubject (DN κατόχου), kSecAttrIssuer (DN εκδότη).
| Κλάση Keychain | Σκοπός | Τύπος δεδομένων |
|---|---|---|
| kSecClassGenericPassword | Κωδικός εφαρμογής | Data (NSString) |
| kSecClassInternetPassword | Κωδικός διακομιστή | Data + χαρακτηριστικά διακομιστή |
| kSecClassCertificate | Πιστοποιητικό X.509 | SecCertificate |
| kSecClassKey | Κρυπτογραφικό κλειδί | SecKey |
| kSecClassIdentity | Κλειδί + πιστοποιητικό | SecIdentity |
Η κύρια διεπαφή αλληλεπίδρασης με το Keychain στον εγγενή κώδικα iOS — οι συναρτήσεις του Security framework. Για Swift και Objective-C είναι διαθέσιμη μία διεπαφή C, τυλιγμένη σε βολικές συναρτήσεις.
Η συνάρτηση SecItemAdd προσθέτει ένα νέο στοιχείο στο Keychain. Στην είσοδο λαμβάνει ένα λεξικό με κλάση, δεδομένα και χαρακτηριστικά. Επιστρέφει κατάσταση errSecSuccess (0) ή κωδικό σφάλματος. Η συνάρτηση SecItemCopyMatching εκτελεί αναζήτηση βάσει χαρακτηριστικών και επιστρέφει τα δεδομένα που βρέθηκαν.
Για αναζήτηση χρησιμοποιείται η σημαία kSecReturnData — αν είναι true, η συνάρτηση επιστρέφει το περιεχόμενο της εγγραφής. Η σημαία kSecMatchLimit καθορίζει τον αριθμό αποτελεσμάτων: kSecMatchLimitOne (ένα) ή kSecMatchLimitAll (όλα).
func readPassword(service: String, account: String) -> Data? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: account,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
guard status == errSecSuccess else { return nil }
return item as? Data
}
SecItemUpdate επιτρέπει την αλλαγή χαρακτηριστικών ή δεδομένων υπάρχουσας εγγραφής. SecItemDelete διαγράφει όλες τις εγγραφές που αντιστοιχούν στο μεταδιδόμενο λεξικό. Κατά τη διαγραφή είναι σημαντικό να καθοριστούν επαρκή χαρακτηριστικά για να μην διαγραφούν κατά λάθος εγγραφές άλλων στο shared keychain.
func deletePassword(service: String, account: String) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: account
]
SecItemDelete(query as CFDictionary)
}
Κάθε εγγραφή Keychain έχει το χαρακτηριστικό kSecAttrAccessible, το οποίο καθορίζει πότε τα δεδομένα είναι διαθέσιμα για ανάγνωση. Αυτό είναι κρίσιμο για την ασφάλεια: λάθος επίπεδο πρόσβασης μπορεί να καταστήσει τα δεδομένα ευάλωτα ή, αντίθετα, μη προσβάσιμα την κατάλληλη στιγμή.
kSecAttrAccessibleWhenUnlocked — τα δεδομένα είναι διαθέσιμα μόνο όταν η συσκευή είναι ξεκλείδωτη. kSecAttrAccessibleAfterFirstUnlock — διαθέσιμα μετά το πρώτο ξεκλείδωμα μετά από επανεκκίνηση. kSecAttrAccessibleAlways — πάντα διαθέσιμα (δεν συνιστάται). Το επίθημα ThisDeviceOnly απαγορεύει τη μεταφορά δεδομένων μέσω αντιγράφου ασφαλείας.
Σε συσκευές με Secure Enclave, το κλειδί κρυπτογράφησης Keychain μπορεί επιπλέον να προστατευτεί με βιομετρικά: kSecAccessControlBiometryCurrentSet ή kSecAccessControlUserPresence. Αυτό προσθέτει απαίτηση Face ID ή Touch ID για κάθε λειτουργία ανάγνωσης.
iCloud Keychain συγχρονίζει εγγραφές μεταξύ συσκευών Apple μέσω κρυπτογράφησης end-to-end. Η Apple δεν έχει πρόσβαση στα αποκρυπτογραφημένα δεδομένα. Για ενεργοποίηση συγχρονισμού, προσθέστε το χαρακτηριστικό kSecAttrSynchronizable με τιμή kCFBooleanTrue.
Σημαντικό: οι συγχρονισμένες εγγραφές δεν μπορούν να περιέχουν το χαρακτηριστικό ThisDeviceOnly, επειδή πρέπει να είναι διαθέσιμες σε άλλες συσκευές. Σε περίπτωση απώλειας όλων των συσκευών, το iCloud Keychain αποκαθίσταται μέσω κωδικού ανάκτησης ή εφεδρικού κλειδιού iCloud.
Για token αυθεντικοποίησης χρησιμοποιήστε kSecAttrAccessibleWhenUnlockedThisDeviceOnly — τα δεδομένα είναι διαθέσιμα μόνο σε ξεκλείδωτη συσκευή και δεν αντιγράφονται στο αντίγραφο ασφαλείας. Για πιστοποιητικά που πρέπει να είναι διαθέσιμα για εργασίες παρασκηνίου, χρησιμοποιήστε kSecAttrAccessibleAfterFirstUnlock. Μην χρησιμοποιείτε ποτέ kSecAttrAccessibleAlways για εμπιστευτικά δεδομένα.
Συνιστάται να προσθέτετε πάντα το επίθημα ThisDeviceOnly για δεδομένα που δεν απαιτούν συγχρονισμό. Αυτό αποτρέπει την τυχαία αντιγραφή μυστικών στο iCloud ή iTunes backup, όπου μπορούν να εξαχθούν με εργαλεία ανάλυσης. Για κρίσιμα δεδομένα, συνδυάστε τη διαθεσιμότητα με kSecAccessControlUserPresence — αυτό προσθέτει απαίτηση βιομετρικών ή κωδικού για αποκρυπτογράφηση της εγγραφής.
Κατά τη χρήση iCloud Keychain, λάβετε υπόψη ότι οι συγχρονισμένες εγγραφές είναι διαθέσιμες σε όλες τις συσκευές του χρήστη: εάν ένας εισβολέας αποκτήσει πρόσβαση σε μία συσκευή, τα δεδομένα μπορεί να διακυβευτούν σε όλες. Για απομονωμένα μυστικά, χρησιμοποιήστε ThisDeviceOnly.
Συχνές ερωτήσεις
UserDefaults αποθηκεύει δεδομένα σε ανοιχτή μορφή στο αρχείο .plist, προσβάσιμο κατά την ανάλυση IPA. Το Keychain κρυπτογραφεί κάθε εγγραφή ξεχωριστά, χρησιμοποιεί κρυπτογράφηση υλικού και υποστηρίζει επίπεδα πρόσβασης, βιομετρικά και συγχρονισμό μέσω iCloud.
Σε κάθε εκκίνηση στον προσομοιωτή iOS, το Keychain καθαρίζεται. Σε πραγματική συσκευή, διαγράψτε την εφαρμογή — το iOS θα διαγράψει όλες τις εγγραφές Keychain αυτού του προγραμματιστή. Για επιλεκτικό καθαρισμό, καλέστε το SecItemDelete με τα κατάλληλα χαρακτηριστικά.
Ναι, μέσω keychain access groups. Οι εφαρμογές πρέπει να έχουν το ίδιο team ID στην υπογραφή και entitlements με το ίδιο keychain-access-groups. Ο προγραμματιστής ρυθμίζει την κοινόχρηστη πρόσβαση στο Xcode Capabilities.
Η Apple δεν τεκμηριώνει αυστηρό όριο, αλλά στην πράξη συνιστάται να μην υπερβαίνετε τα 1–4 KB ανά εγγραφή. Για μεγάλους όγκους, χρησιμοποιήστε κρυπτογράφηση αρχείων και αποθήκευση κλειδιού στο Keychain, και τα ίδια τα δεδομένα — στο Documents.
Μετά από jailbreak, η προστασία του Keychain μειώνεται, καθώς ο εισβολέας αποκτά πρόσβαση root και μπορεί να διαβάσει απευθείας το Keychain SQLite. Για κρίσιμα δεδομένα, χρησιμοποιήστε πρόσθετη κρυπτογράφηση με κλειδί που λαμβάνεται από τον διακομιστή.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης