Keychain in iOS: Was es ist, Architektur und Arbeit mit Geheimnissen

Autor: IT Sectr Veröffentlicht: 2026-04-04 Lesezeit: 9 Min.

Keychain ist ein sicherer Speicher in iOS, der zum sicheren Aufbewahren von Passwörtern, kryptografischen Schlüsseln, Zertifikaten und vertraulichen Notizen entwickelt wurde. Laut Apple Security Documentation (2025) verwendet Keychain Hardwareverschlüsselung über Secure Enclave auf allen Geräten mit A7-Chip und neuer. Die Architektur von iOS Keychain zu verstehen ist für jeden Entwickler unerlässlich, um Anwendungs-Tokens und Geheimnisse richtig zu speichern.

Wichtigste Erkenntnisse

  • iOS Keychain ist eine verschlüsselte SQLite-Datenbank zum Speichern von Geheimnissen mit Hardwareschutz über Secure Enclave.
  • Protection Class bestimmt, wann Daten verfügbar sind: bei entsperrtem Gerät, nach dem ersten Entsperren oder immer.
  • Access Control List (ACL) ist ein Mechanismus zur Einschränkung des Zugriffs auf Keychain-Elemente, einschließlich biometrischer Authentifizierung.
  • SecItemAdd und SecItemCopyMatching sind die wichtigsten APIs des Security Frameworks zum Schreiben und Lesen von Elementen.
  • kSecAttrSynchronizable ist das Flag, das die Keychain-Synchronisierung über iCloud für den Zugriff auf allen Benutzergeräten ermöglicht.

Was ist Keychain in iOS?

iOS Keychain ist ein sicherer Mechanismus zum Speichern vertraulicher Daten, der in das Apple-Betriebssystem integriert ist. Anders als UserDefaults oder normale Dateien verschlüsselt Keychain alle Elemente auf Hardwareebene und bietet eine fein abgestufte Zugriffskontrolle basierend auf Sicherheitsrichtlinien.

Keychain wurde in iOS 2.0 eingeführt und hat seitdem bedeutende Änderungen erfahren: iOS 7 fügte Hardware-Schlüsselunterstützung über Secure Enclave hinzu, iOS 9 führte die Keychain-Freigabe zwischen Apps über Access Groups ein, iOS 13 fügte biometrische Bindung über LAContext hinzu. Laut Apple WWDC Session (2024) verwenden über 90% der iOS-Apps in den Top 100 des App Store Keychain zum Speichern von Authentifizierungs-Tokens.

Architektonisch ist Keychain eine verschlüsselte SQLite-Datenbank, die sich außerhalb des Anwendungs-Sandbox befindet. Jedes Element (SecItem) wird mit einem separaten Schlüssel verschlüsselt, der wiederum durch den Secure-Enclave-Hardwareschlüssel geschützt ist. Der Systemdienst Securityd verwaltet den Zugriff auf Keychain basierend auf den Berechtigungen der Anwendung und der angeforderten Schutzklasse.

Ein wichtiger Vorteil von Keychain gegenüber anderen Speichermethoden: Daten werden automatisch vom Betriebssystem verschlüsselt und entschlüsselt. Der Entwickler muss keine Kryptografie manuell implementieren - einfach SecItemAdd mit den richtigen Parametern aufrufen. iOS garantiert, dass andere Anwendungen die Daten aus Keychain nicht lesen können (bei korrekt konfigurierten Access Groups).

Keychain-Architektur

Die Keychain-Architektur umfasst mehrere Ebenen: physisch (Secure Enclave), System (Security.framework), Anwendung (SecItem*-API) und logisch (Access Groups, Protection Classes). Das Verständnis jeder Ebene hilft, die Speicherung von Geheimnissen richtig zu entwerfen.

SecItemAdd und SecItemCopyMatching

Die wichtigste API für die Arbeit mit Keychain sind die Funktionen des Security Frameworks: SecItemAdd zum Hinzufügen, SecItemCopyMatching zum Lesen, SecItemUpdate zum Aktualisieren und SecItemDelete zum Löschen. Jede Funktion nimmt ein Query-Wörterbuch entgegen, das die Attribute des zu suchenden oder zu speichernden Elements beschreibt.

Wichtige Query-Attribute: kSecClass - Elementtyp (kSecClassGenericPassword, kSecClassKey, kSecClassCertificate), kSecAttrAccount - eindeutige Kennung innerhalb der Klasse, kSecValueData - gespeicherte Daten (Data), kSecAttrAccessible - Schutzklasse. SecItemCopyMatching mit dem Flag kSecReturnData gibt die Elementdaten zurück, mit kSecMatchLimit - die Anzahl der Ergebnisse.

Wichtig: Alle Funktionen geben einen OSStatus zurück. Eine erfolgreiche Operation gibt errSecSuccess (0) zurück. Fehler: errSecItemNotFound (-25300) - Element nicht gefunden, errSecDuplicateItem (-25299) - Element existiert bereits, errSecAuthFailed (-25293) - biometrische Authentifizierung fehlgeschlagen. Der Entwickler muss jeden Status korrekt behandeln.

Schutzklassen (Protection Class)

Protection Class ist das Attribut kSecAttrAccessible, das bestimmt, wann Daten in Keychain zum Lesen verfügbar sind. iOS unterstützt sechs Schutzklassen mit unterschiedlichen Verfügbarkeits- und Sicherheitsstufen.

Die empfohlene Klasse für die meisten Szenarien ist kSecAttrAccessibleWhenUnlockedThisDeviceOnly: Daten sind nur bei entsperrtem Gerät verfügbar und werden nicht in iCloud Backup kopiert. Für Daten, die nach einem Neustart verfügbar sein sollen (aber erst nach dem ersten Entsperren), verwenden Sie kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly. Für kritische Daten, die bei jedem Zugriff biometrische Authentifizierung erfordern, kombinieren Sie kSecAttrAccessibleWhenUnlockedThisDeviceOnly mit einer ACL, die Biometrie erfordert.

Klassen ohne das Suffix ThisDeviceOnly (kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAfterFirstUnlock) erlauben das Kopieren in iCloud Backup. Dies ist bequem für den Benutzer, reduziert aber die Sicherheit - Daten können aus dem Backup wiederhergestellt werden. Für Authentifizierungs-Tokens verwenden Sie immer ThisDeviceOnly.

Zugriffskontrolllisten (ACL)

Access Control List (ACL) ist ein Mechanismus, der Operationen an einem Keychain-Element basierend auf der Benutzerauthentifizierung einschränkt. ACL wird über SecAccessControlCreateWithFlags festgelegt und beim Speichern eines Elements an das Attribut kSecAttrAccessControl übergeben.

Unterstützte Flags: kSecAccessControlUserPresence - jede Authentifizierung (Face ID, Touch ID oder Passcode), kSecAccessControlBiometryCurrentSet - nur Biometrie (aktuell registrierte Fingerabdrücke oder Gesicht), kSecAccessControlDevicePasscode - nur Passcode. ACL gilt für jede Operation: Lesen, Aktualisieren und Löschen eines Elements erfordern ebenfalls eine Authentifizierung.

Ab iOS 15+ erschien das Flag kSecAccessControlWatch - für Apple Watch, das die Authentifizierung über eine gekoppelte Uhr ermöglicht. ACL kann kombiniert werden: zum Beispiel kSecAccessControlUserPresence oder kSecAccessControlBiometryAny mit optionalem Passcode (Ausrichtung .or).

Datentypen in Keychain

iOS Keychain unterstützt vier Hauptelementklassen (kSecClass), die jeweils für ihren eigenen Datentyp entwickelt wurden. Die richtige Klassenwahl vereinfacht die Organisation und die Suche nach Elementen.

kSecClassGenericPassword - generisches Passwort: die am häufigsten verwendete Klasse. Speichert beliebige binäre Daten (Data) mit einem eindeutigen Schlüssel (kSecAttrAccount). Geeignet für Tokens, API-Schlüssel, PIN-Codes. Erfordert keine zusätzlichen Berechtigungen zur Nutzung.

kSecClassInternetPassword - Internet-Passwort: speichert Daten, die mit einer Netzwerkressource verbunden sind. Zusätzliche Attribute: kSecAttrServer (Serverdomäne), kSecAttrProtocol (https, ftp), kSecAttrPort, kSecAttrAuthenticationType. iOS kann solche Passwörter automatisch über AutoFill ausfüllen.

kSecClassKey - kryptografischer Schlüssel: zum Speichern von Verschlüsselungsschlüsseln (AES, RSA, EC). Der Schlüssel wird als SecKeyRef gespeichert, nicht als Data. kSecClassCertificate - X.509-Zertifikat zum Speichern und Überprüfen digitaler Zertifikate. Beide Klassen erfordern Verständnis kryptografischer Operationen und korrekte Attributkonfiguration.

In der Praxis werden 95% der Keychain-Nutzung in mobilen Apps durch kSecClassGenericPassword zum Speichern von Authentifizierungs-Tokens und kSecClassKey zum Speichern privater Verschlüsselungsschlüssel abgedeckt. kSecClassCertificate wird selten verwendet - typischerweise in Unternehmens-Apps mit eigenem PKI.

Codebeispiele: Arbeiten mit Keychain in Swift

Sehen wir uns praktische Beispiele für die Arbeit mit Keychain in Swift unter Verwendung des Security Frameworks an. Jedes Beispiel enthält Fehlerbehandlung und korrekte Konfiguration der Protection Class.

Speichern und Lesen eines Tokens

Ein einfaches Beispiel speichert ein Authentifizierungs-Token in Keychain mit WhenUnlockedThisDeviceOnly-Schutz. Der Schlüssel (kSecAttrAccount) ist der Dienstkennung, die Daten (kSecValueData) sind das Token im Data-Format.

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

Speichern mit biometrischer Bindung

Das Beispiel demonstriert die Verwendung von SecAccessControlCreateWithFlags, um einen Schlüssel an die Biometrie zu binden. Jeder Zugriff auf das Element erfordert Face ID oder Touch ID.

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

Keychain-Freigabe zwischen Apps

Das Beispiel zeigt die Konfiguration einer Access Group für den gemeinsamen Keychain-Zugriff zwischen Apps desselben Entwicklers. Erfordert die Berechtigung keychain-access-groups.

swift
// Capabilities: Keychain Sharing aktiviert
// 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)
}

Bewährte Methoden für die Arbeit mit Keychain

Die korrekte Verwendung von iOS Keychain erfordert die Einhaltung mehrerer wichtiger Regeln, die häufige Sicherheitslücken und Datenverlust verhindern.

Verwenden Sie ThisDeviceOnly für alle Authentifizierungsgeheimnisse: kSecAttrAccessibleWhenUnlockedThisDeviceOnly stellt sicher, dass Tokens nicht in iCloud Backup landen. Wenn ein Angreifer Zugriff auf das Backup erhält, sind Keychain-Daten mit diesem Flag nicht verfügbar. Die Ausnahme sind Daten, die auf allen Benutzergeräten verfügbar sein sollen (z.B. Verschlüsselungsschlüssel für proprietäre Dienste), für die Sie kSecAttrAccessibleWhenUnlocked mit kSecAttrSynchronizable verwenden.

Speichern Sie keine Rohpasswörter - speichern Sie Hashes oder Sitzungs-Tokens. Der Apple Security Guide (2025) empfiehlt, das Benutzerpasswort niemals im Klartext in Keychain zu speichern. Speichern Sie stattdessen das Refresh-Token, das nach erfolgreicher Authentifizierung über OAuth 2.0 vom Server empfangen wurde. Das Passwort wird nur zum Abrufen des Tokens verwendet und sofort aus dem Arbeitsspeicher entfernt.

Behandeln Sie Keychain-Fehler korrekt: Jede Keychain-Operation gibt einen OSStatus zurück, der überprüft werden muss. Besondere Aufmerksamkeit gilt errSecItemNotFound (Token abgelaufen oder gelöscht) und errSecAuthFailed (Biometrie fehlgeschlagen). Im ersten Fall sollte die App eine neue Authentifizierung anfordern; im zweiten Fall dem Benutzer eine alternative Methode (Passcode) anzeigen. Ignorieren Sie niemals den Status errSecItemNotFound - dies führt zu einem Absturz beim Versuch, nil zu lesen.

Testen Sie Keychain auf einem echten Gerät: Der Simulator hat kein Secure Enclave und unterstützt keine biometrischen ACLs. Überprüfen Sie immer die Szenarien: Erster Start, Wiederherstellung aus Backup, Gerätepasswortänderung, Löschen und Neuinstallation der App. Auf einem echten Gerät bleibt Keychain beim Löschen der App erhalten, aber nur wenn das Flag kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly nicht verwendet wurde, das beim Entfernen des Passcodes gelöscht wird.

Minimieren Sie die Anzahl der Keychain-Operationen: Jeder Lese- oder Schreibvorgang ist ein Aufruf des Systemdienstes Securityd, der den Thread blockieren kann. Zwischenspeichern Sie gelesene Tokens für die Sitzungsdauer im Arbeitsspeicher und greifen Sie nur beim Neustart der App oder bei Authentifizierungsfehlern (401 vom Server) erneut auf Keychain zu. iOS sperrt Keychain automatisch, wenn das Gerät gesperrt wird. Planen Sie daher das Lesen über LAContext mit einer biometrischen Anfrage.

Häufig gestellte Fragen

Kann ich Daten in Keychain speichern und nach einem Neustart lesen?

Ja, verwenden Sie die Schutzklasse kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly oder kSecAttrAccessibleAfterFirstUnlock. Die Daten sind nach dem ersten Geräteentsperren nach einem Neustart verfügbar. Für automatischen Zugriff beim App-Start (ohne auf Entsperren zu warten) verwenden Sie kSecAttrAccessibleAlways, aber dies reduziert die Sicherheit.

Wie lösche ich Keychain beim Benutzer-Logout?

Rufen Sie SecItemDelete mit einer Abfrage auf, die kSecClass für jeden Datentyp enthält. Zur vollständigen Löschung aller App-Elemente führen Sie aus: SecItemDelete([kSecClass as String: kSecClassGenericPassword] as CFDictionary). Wiederholen Sie für kSecClassKey, kSecClassCertificate und kSecClassInternetPassword.

Was ist der Unterschied zwischen kSecAttrAccessible und kSecAttrAccessControl?

kSecAttrAccessible bestimmt, wann Daten verfügbar sind (beim Entsperren, nach erstem Entsperren usw.). kSecAttrAccessControl bestimmt, wer darauf zugreifen kann (Biometrie, Passcode, jede Authentifizierung). Sie werden kombiniert: zuerst Protection Class, dann ACL. Zum Beispiel sind Daten nur beim Entsperren UND nur nach Face ID verfügbar.

Warum gibt SecItemCopyMatching errSecItemNotFound zurück?

Gründe: Das Element wurde nie gespeichert, das Element wurde beim Entfernen des Passcodes gelöscht (wenn kSecAttrAccessibleWhenPasscodeSet verwendet wurde), die App wurde neu installiert (Keychain bleibt erhalten, wird aber auf einem neuen Gerät nicht aus dem Backup wiederhergestellt), die Access Group oder die Entwicklerteam-Kennung hat sich geändert. Überprüfen Sie kSecAttrService und kSecAttrAccount.

Wie überprüfe ich, ob das Gerät Biometrie in Keychain unterstützt?

Verwenden Sie LAContext aus LocalAuthentication: rufen Sie context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) auf. Wenn true zurückgegeben wird - unterstützt das Gerät Touch ID oder Face ID. Für Keychain-ACL verwenden Sie das Flag biometryCurrentSet (nur aktuelle biometrische Daten) oder biometryAny (alle zuvor registrierten).

Zusammenfassung

  • iOS Keychain ist ein hardwaregeschützter Speicher für Geheimnisse mit Verschlüsselung über Secure Enclave und Zugriffskontrolle über ACL.
  • Security Framework bietet die Funktionen SecItemAdd, SecItemCopyMatching, SecItemUpdate und SecItemDelete für die Arbeit mit Elementen.
  • Protection Class (kSecAttrAccessible) wird basierend auf dem Szenario gewählt: WhenUnlockedThisDeviceOnly ist der Standard für Tokens.
  • ACL mit Biometrie (kSecAttrAccessControl) fügt eine Face-ID- oder Touch-ID-Anforderung für jeden Lesevorgang hinzu.
  • kSecClassGenericPassword deckt 95% der Fälle ab - Speichern von Tokens, API-Schlüsseln, PIN-Codes und Notizen.
  • ThisDeviceOnly verhindert das Kopieren von Geheimnissen in iCloud Backup - obligatorisch für Authentifizierungs-Tokens.
  • Korrekte OSStatus-Behandlung und Tests auf einem echten Gerät sind wesentliche Praktiken für eine zuverlässige Keychain-Nutzung.

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch