iOS'ta Keychain: nedir, mimarisi ve sırlarla çalışma

Yazar: IT Sectr Yayınlanma: 2026-04-04 Okuma süresi: 9 dk

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, Secure Enclave aracılığıyla donanım koruması ile sırları saklamak için şifrelenmiş bir SQLite veritabanıdır.
  • Protection Class, verilerin ne zaman kullanılabilir olduğunu belirler: cihazın kilidi açıldığında, ilk kilit açma işleminden sonra veya her zaman.
  • Access Control List (ACL), biyometrik kimlik doğrulama dahil olmak üzere Keychain öğelerine erişimi kısıtlayan bir mekanizmadır.
  • SecItemAdd ve SecItemCopyMatching, Security framework'ün öğeleri yazmak ve okumak için ana API'leridir.
  • kSecAttrSynchronizable, kullanıcının tüm cihazlarında erişim için iCloud aracılığıyla Keychain senkronizasyonunu etkinleştiren bayraktır.

iOS'ta Keychain Nedir?

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

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.

SecItemAdd ve SecItemCopyMatching

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.

Koruma Sınıfları (Protection Class)

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.

Erişim Kontrol Listeleri (ACL)

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.

Keychain'de Veri Türleri

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.

Kod Örnekleri: Swift'te Keychain ile Çalışma

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.

Token Kaydetme ve Okuma

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.

swift
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)
}

Biyometrik Bağlama ile Kaydetme

Örnek, bir anahtarı biyometriye bağlamak için SecAccessControlCreateWithFlags kullanımını gösterir. Öğeye her erişim Face ID veya Touch ID gerektirecektir.

swift
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)
    }
}

Uygulamalar Arasında Keychain Paylaşımı

Ö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.

swift
// 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)
}

Keychain ile Çalışmak için En İyi Uygulamalar

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

Keychain'e veri kaydedip yeniden başlatmadan sonra okuyabilir miyim?

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.

Kullanıcı çıkışında Keychain nasıl temizlenir?

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 ve kSecAttrAccessControl arasındaki fark nedir?

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.

SecItemCopyMatching neden errSecItemNotFound döndürüyor?

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.

Cihazın Keychain'de biyometriyi destekleyip desteklemediğini nasıl kontrol ederim?

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

  • iOS Keychain, Secure Enclave aracılığıyla şifreleme ve ACL aracılığıyla erişim kontrolü ile sırlar için donanım korumalı bir depodur.
  • Security framework, öğelerle çalışmak için SecItemAdd, SecItemCopyMatching, SecItemUpdate ve SecItemDelete işlevlerini sağlar.
  • Protection Class (kSecAttrAccessible) senaryoya göre seçilir: WhenUnlockedThisDeviceOnly token'lar için standarttır.
  • Biyometri ile ACL (kSecAttrAccessControl), her okuma işlemi için Face ID veya Touch ID gereksinimi ekler.
  • kSecClassGenericPassword vakaların %95'ini kapsar - token'lar, API anahtarları, PIN kodları ve notların depolanması.
  • ThisDeviceOnly sırların iCloud Backup'a kopyalanmasını önler - kimlik doğrulama token'ları için zorunludur.
  • Doğru OSStatus işleme ve gerçek cihazda test etme, güvenilir Keychain kullanımı için temel uygulamalardır.

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.

Projeyi tartış

Ayrıca okuyun