Keychain, iOS'ta parolaları, kriptografik anahtarları, sertifikaları ve gizli notları güvenli bir şekilde saklamak için tasarlanmış güvenli bir depolama alanıdır. Apple Security Documentation (2025)'a göre Keychain, A7 çip ve daha yeni tüm cihazlarda Secure Enclave aracılığıyla donanım şifrelemesi kullanır. iOS Keychain mimarisini anlamak, her geliştiricinin uygulama token'larını ve sırlarını doğru şekilde saklaması için gereklidir.
Önemli Noktalar
iOS Keychain, Apple işletim sistemine yerleşik, gizli verileri depolamak için güvenli bir mekanizmadır. UserDefaults veya normal dosyaların aksine Keychain, tüm öğeleri donanım düzeyinde şifreler ve güvenlik politikalarına dayalı ayrıntılı erişim kontrolü sağlar.
Keychain, iOS 2.0'da tanıtıldı ve o zamandan beri önemli değişiklikler geçirdi: iOS 7, Secure Enclave aracılığıyla donanım anahtarı desteği ekledi, iOS 9, Access Groups aracılığıyla uygulamalar arasında Keychain paylaşımını başlattı, iOS 13, LAContext aracılığıyla biyometrik bağlama desteği ekledi. Apple WWDC Session (2024)'a göre, App Store'daki ilk 100 iOS uygulamasının %90'ından fazlası kimlik doğrulama token'larını saklamak için Keychain kullanmaktadır.
Mimari olarak Keychain, uygulama sandbox'ının dışında bulunan şifrelenmiş bir SQLite veritabanıdır. Her öğe (SecItem), ayrı bir anahtarla şifrelenir ve bu anahtar da Secure Enclave donanım anahtarı tarafından korunur. Sistem hizmeti Securityd, uygulama yetkilendirmelerine ve istenen koruma sınıfına göre Keychain'e erişimi yönetir.
Keychain'in diğer depolama yöntemlerine göre önemli bir avantajı: veriler işletim sistemi tarafından otomatik olarak şifrelenir ve şifresi çözülür. Geliştiricinin manuel olarak şifreleme uygulaması gerekmez - doğru parametrelerle SecItemAdd'i çağırmak yeterlidir. iOS, Access Groups doğru yapılandırıldığında Keychain'deki verilerin diğer uygulamalar tarafından okunamayacağını garanti eder.
Keychain mimarisi birkaç seviye içerir: fiziksel (Secure Enclave), sistem (Security.framework), uygulama (SecItem* API) ve mantıksal (Access Groups, Protection Classes). Her seviyeyi anlamak, sır depolamayı doğru şekilde tasarlamaya yardımcı olur.
Keychain ile çalışmak için ana API, Security framework işlevleridir: eklemek için SecItemAdd, okumak için SecItemCopyMatching, güncellemek için SecItemUpdate ve silmek için SecItemDelete. Her işlev, aranacak veya kaydedilecek öğenin niteliklerini tanımlayan bir sorgu sözlüğü alır.
Temel sorgu nitelikleri: kSecClass - öğe türü (kSecClassGenericPassword, kSecClassKey, kSecClassCertificate), kSecAttrAccount - sınıf içindeki benzersiz tanımlayıcı, kSecValueData - kaydedilen veriler (Data), kSecAttrAccessible - koruma sınıfı. SecItemCopyMatching, kSecReturnData bayrağı ile öğe verilerini, kSecMatchLimit ile sonuç sayısını döndürür.
Önemli: tüm işlevler bir OSStatus döndürür. Başarılı bir işlem errSecSuccess (0) döndürür. Hatalar: errSecItemNotFound (-25300) - öğe bulunamadı, errSecDuplicateItem (-25299) - öğe zaten mevcut, errSecAuthFailed (-25293) - biyometrik kimlik doğrulama başarısız. Geliştirici her durumu doğru şekilde ele almalıdır.
Protection Class, Keychain'deki verilerin ne zaman okunmaya uygun olduğunu belirleyen kSecAttrAccessible niteliğidir. iOS, farklı kullanılabilirlik ve güvenlik seviyelerine sahip altı koruma sınıfını destekler.
Çoğu senaryo için önerilen sınıf kSecAttrAccessibleWhenUnlockedThisDeviceOnly'dir: veriler yalnızca cihazın kilidi açıldığında kullanılabilir ve iCloud Backup'a kopyalanmaz. Yeniden başlatmadan sonra kullanılabilir olması gereken veriler için (ancak yalnızca ilk kilit açma işleminden sonra), kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly kullanın. Her erişimde biyometrik kimlik doğrulama gerektiren kritik veriler için, kSecAttrAccessibleWhenUnlockedThisDeviceOnly'yi biyometri gerektiren bir ACL ile birleştirin.
ThisDeviceOnly soneki olmayan sınıflar (kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAfterFirstUnlock) iCloud Backup'a kopyalamaya izin verir. Bu, kullanıcı için uygundur ancak güvenliği azaltır - veriler yedekten geri yüklenebilir. Kimlik doğrulama token'ları için her zaman ThisDeviceOnly kullanın.
Access Control List (ACL), kullanıcı kimlik doğrulamasına dayalı olarak bir Keychain öğesi üzerindeki işlemleri kısıtlayan bir mekanizmadır. ACL, SecAccessControlCreateWithFlags aracılığıyla ayarlanır ve bir öğe kaydedilirken kSecAttrAccessControl niteliğine iletilir.
Desteklenen bayraklar: kSecAccessControlUserPresence - herhangi bir kimlik doğrulama (Face ID, Touch ID veya parola), kSecAccessControlBiometryCurrentSet - yalnızca biyometri (şu anda kayıtlı parmak izleri veya yüz), kSecAccessControlDevicePasscode - yalnızca parola. ACL her işlem için geçerlidir: bir öğeyi okumak, güncellemek ve silmek de kimlik doğrulama gerektirir.
iOS 15+'te, Apple Watch için kSecAccessControlWatch bayrağı ortaya çıktı - eşleştirilmiş bir saat aracılığıyla kimlik doğrulamaya izin verir. ACL birleştirilebilir: örneğin, kSecAccessControlUserPresence veya kSecAccessControlBiometryAny isteğe bağlı parola (.or yönelimi) ile.
iOS Keychain, her biri kendi veri türü için tasarlanmış dört ana öğe sınıfını (kSecClass) destekler. Doğru sınıfı seçmek, organizasyonu ve öğe aramayı basitleştirir.
kSecClassGenericPassword - genel parola: en sık kullanılan sınıf. Benzersiz bir anahtarla (kSecAttrAccount) rastgele ikili verileri (Data) depolar. Token'lar, API anahtarları, PIN kodları için uygundur. Kullanım için ek yetkilendirme gerektirmez.
kSecClassInternetPassword - internet parolası: bir ağ kaynağıyla ilişkili verileri depolar. Ek nitelikler: kSecAttrServer (sunucu alan adı), kSecAttrProtocol (https, ftp), kSecAttrPort, kSecAttrAuthenticationType. iOS, AutoFill aracılığıyla bu tür parolaları otomatik olarak doldurabilir.
kSecClassKey - kriptografik anahtar: şifreleme anahtarlarını (AES, RSA, EC) depolamak için. Anahtar, Data olarak değil SecKeyRef olarak depolanır. kSecClassCertificate - dijital sertifikaları depolamak ve doğrulamak için X.509 sertifikası. Her iki sınıf da kriptografik işlemlerin anlaşılmasını ve doğru nitelik yapılandırmasını gerektirir.
Pratikte, mobil uygulamalarda Keychain kullanımının %95'i, kimlik doğrulama token'larını depolamak için kSecClassGenericPassword ve özel şifreleme anahtarlarını depolamak için kSecClassKey tarafından karşılanır. kSecClassCertificate nadiren kullanılır - genellikle kendi PKI'sine sahip kurumsal uygulamalarda.
Security framework kullanarak Swift'te Keychain ile çalışmanın pratik örneklerine bakalım. Her örnek, hata işleme ve doğru Protection Class yapılandırmasını içerir.
Temel bir örnek, WhenUnlockedThisDeviceOnly koruması ile Keychain'de bir kimlik doğrulama token'ı kaydeder. Anahtar (kSecAttrAccount) hizmet tanımlayıcısıdır, veriler (kSecValueData) Data formatındaki token'dır.
import Security
enum KeychainError: Error {
case unexpectedStatus(OSStatus)
}
func saveToken(token: String, service: String) throws {
let data = Data(token.utf8)
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: "auth_token",
kSecValueData as String: data,
kSecAttrAccessible as String:
kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
SecItemDelete(query as CFDictionary)
let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else {
throw KeychainError.unexpectedStatus(status)
}
}
func readToken(service: String) throws -> String {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: "auth_token",
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var result: AnyObject?
let status = SecItemCopyMatching(
query as CFDictionary, &result
)
guard status == errSecSuccess,
let data = result as? Data else {
throw KeychainError.unexpectedStatus(status)
}
return String(decoding: data, as: UTF8.self)
}
Örnek, bir anahtarı biyometriye bağlamak için SecAccessControlCreateWithFlags kullanımını gösterir. Öğeye her erişim Face ID veya Touch ID gerektirecektir.
import LocalAuthentication
func saveWithBiometry(data: Data, key: String) throws {
let accessControl = SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.biometryCurrentSet,
nil
)
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecValueData as String: data,
kSecAttrAccessControl as String: accessControl as Any
]
SecItemDelete(query as CFDictionary)
let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else {
throw KeychainError.unexpectedStatus(status)
}
}
Örnek, aynı geliştiricinin uygulamaları arasında paylaşılan Keychain erişimi için bir Access Group yapılandırmasını gösterir. keychain-access-groups yetkilendirmesi gerektirir.
// Capabilities: Keychain Sharing etkin
// App IDs: group.com.example.shared
func saveSharedToken(token: Data) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "shared_token",
kSecValueData as String: token,
kSecAttrAccessGroup as String:
"group.com.example.shared",
kSecAttrAccessible as String:
kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
SecItemAdd(query as CFDictionary, nil)
}
iOS Keychain'in doğru kullanımı, yaygın güvenlik açıklarını ve veri kaybını önleyen birkaç temel kurala uymayı gerektirir.
Tüm kimlik doğrulama sırları için ThisDeviceOnly kullanın: kSecAttrAccessibleWhenUnlockedThisDeviceOnly, token'ların iCloud Backup'a gitmemesini sağlar. Bir saldırgan yedekleme erişimi elde ederse, bu bayrağa sahip Keychain verileri kullanılamaz olacaktır. İstisna, kullanıcının tüm cihazlarında kullanılabilir olması gereken verilerdir (örneğin, özel hizmetler için şifreleme anahtarları), bunlar için kSecAttrAccessibleWhenUnlocked'u kSecAttrSynchronizable ile birlikte kullanın.
Ham parolaları saklamayın - karma veya oturum token'ları saklayın. Apple Security Guide (2025), kullanıcı parolasının Keychain'de asla düz metin olarak saklanmamasını önerir. Bunun yerine, OAuth 2.0 aracılığıyla başarılı kimlik doğrulamadan sonra sunucudan alınan yenileme token'ını kaydedin. Parola yalnızca token'ı almak için kullanılır ve hemen bellekten kaldırılır.
Keychain hatalarını doğru şekilde ele alın: her Keychain işlemi, kontrol edilmesi gereken bir OSStatus döndürür. Özellikle errSecItemNotFound (token süresi doldu veya silindi) ve errSecAuthFailed (biyometri başarısız) durumlarına dikkat edin. İlk durumda, uygulama yeni kimlik doğrulama istemelidir; ikinci durumda, kullanıcıya alternatif bir yöntem (parola) gösterilmelidir. Asla errSecItemNotFound durumunu görmezden gelmeyin - nil okumaya çalışırken uygulama çöker.
Keychain'i gerçek bir cihazda test edin: simülatörde Secure Enclave bulunmaz ve biyometrik ACL'leri desteklemez. Her zaman senaryoları kontrol edin: ilk başlatma, yedekten geri yükleme, cihaz parolası değişikliği, uygulama silme ve yeniden yükleme. Gerçek bir cihazda, uygulama silindiğinde Keychain kalıcı olur, ancak yalnızca kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly bayrağı kullanılmamışsa - bu bayrak parola kaldırıldığında temizlenir.
Keychain işlemlerinin sayısını en aza indirin: her okuma veya yazma işlemi, iş parçacığını engelleyebilen sistem hizmeti Securityd'ye bir çağrıdır. Oturum süresi boyunca okunan token'ları bellekte önbelleğe alın ve yalnızca uygulama yeniden başlatıldığında veya kimlik doğrulama hatasında (sunucudan 401) Keychain'e yeniden erişin. iOS, cihaz kilitlendiğinde Keychain'i otomatik olarak kilitler, bu nedenle biyometrik istekle LAContext aracılığıyla okuma planlayın.
Sıkça Sorulan Sorular
Evet, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly veya kSecAttrAccessibleAfterFirstUnlock koruma sınıfını kullanın. Veriler, yeniden başlatmadan sonraki ilk cihaz kilidi açma işleminden sonra kullanılabilir olacaktır. Uygulama başlatmada otomatik erişim için (kilit açmayı beklemeden) kSecAttrAccessibleAlways kullanın, ancak bu güvenliği azaltır.
Her veri türü için kSecClass içeren bir sorguyla SecItemDelete çağrısı yapın. Tüm uygulama öğelerinin tamamen temizlenmesi için şunu çalıştırın: SecItemDelete([kSecClass as String: kSecClassGenericPassword] as CFDictionary). kSecClassKey, kSecClassCertificate ve kSecClassInternetPassword için tekrarlayın.
kSecAttrAccessible verilerin ne zaman kullanılabilir olduğunu belirler (kilit açıldığında, ilk kilit açmadan sonra vb.). kSecAttrAccessControl kimlerin erişebileceğini belirler (biyometri, parola, herhangi bir kimlik doğrulama). Birleştirilirler: önce Protection Class, sonra ACL. Örneğin, veriler yalnızca kilit açıldığında VE yalnızca Face ID'den sonra kullanılabilir.
Nedenleri: öğe hiç kaydedilmedi, parola kaldırıldığında öğe silindi (kSecAttrAccessibleWhenPasscodeSet kullanıldıysa), uygulama yeniden yüklendi (Keychain kalıcıdır ancak yeni bir cihazda yedekten geri yüklenmez), Access Group veya geliştirici ekibi tanımlayıcısı değişti. kSecAttrService ve kSecAttrAccount'u kontrol edin.
LocalAuthentication'dan LAContext kullanın: context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) çağrısı yapın. true döndürürse - cihaz Touch ID veya Face ID'yi destekler. Keychain ACL için biometryCurrentSet bayrağını (yalnızca mevcut biyometrik veriler) veya biometryAny'yi (önceden kaydedilmiş herhangi bir veri) kullanın.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun