Keychain — är en säker lagringsplats för inloggningsuppgifter i iOS, watchOS, macOS och tvOS som hanterar lösenord, nycklar och certifikat på hårdvarunivå. Till skillnad från UserDefaults krypteras data i Keychain och isoleras av applikationens sandlåda. Enligt Apple Developer Documentation använder Keychain Secure Enclave-mekanismer och hårdvarukryptering AES-256 för att skydda konfidentiell information.
Huvudpunkter
Keychain — är en säker databas i Apples operativsystem, designad för säker lagring av lösenord, kryptografiska nycklar, certifikat och andra konfidentiella data. Keychain dök först upp i Mac OS 8.6 1999 och i iOS — från den första SDK-versionen.
Keychain löser ett grundläggande problem inom mobilutveckling: lagring av hemligheter (tokens, lösenord, krypteringsnycklar) i ett oskyddat filsystem. Till skillnad från UserDefaults eller SQLite lagras data i Keychain i krypterad form och krypteras automatiskt vid skrivning till disk.
Varje iOS-applikation fungerar i en isolerad sandlåda och har endast åtkomst till sin egen keychain. Utvecklaren kan dock konfigurera delad åtkomst till Keychain mellan applikationer från samma utvecklare via keychain access groups. iCloud Keychain-användaren synkroniserar dessutom data mellan enheter via end-to-end-kryptering.
Enligt Apple Security White Paper (2025) använder Keychain hårdvarukryptering AES-256 med en nyckel bunden till enhetens unika identifierare (UID), vilket gör data otillgängliga vid extraktion från enheten.
Keychain fungerar som en skiktad tjänst: applikationen anropar Security framework, som interagerar med securityd-demonen, som hanterar den krypterade SQLite-databasen för Keychain. Varje post krypteras med en separat nyckel, och själva nycklarna skyddas av hårdvarumodulen Secure Enclave på enheter med A7-chip och nyare.
Security framework tillhandahåller ett C-gränssnitt för arbete med Keychain Services. Huvudfunktioner: SecItemAdd (lägg till), SecItemCopyMatching (sök), SecItemUpdate (uppdatera) och SecItemDelete (ta bort). Varje operation tar emot en ordbok med attribut CFDictionaryRef som beskriver typen av begäran.
Data klassificeras enligt klasser: kSecClassGenericPassword (godtyckligt lösenord), kSecClassInternetPassword (lösenord för internettjänst), kSecClassCertificate (certifikat), kSecClassKey (kryptografisk nyckel) och kSecClassIdentity (kombination av nyckel och certifikat).
När ett lösenord sparas skapar applikationen en ordbok med attribut: tjänst, konto, åtkomstnivå, etikett. Security framework överför data till securityd-demonen, som krypterar posten med en enhetsbunden nyckel och sparar i Keychain SQLite. Extrahering sker på liknande sätt: förfrågan baserat på attribut, sökning, dekryptering och återlämning av data.
En viktig egenskap: när applikationen tas bort rensar iOS automatiskt Keychain från poster som skapats av denna applikation (från iOS 10.3+). Vid ominstallation av applikationen är Keychain-data från föregående installation otillgängliga, om inte iCloud Keychain har använts.
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 stöder fem huvudklasser av data, var och en med sin egen uppsättning attribut och tillämpningsområde. Valet av klass avgör vilka söknycklar som är tillgängliga och hur data krypteras.
Klasserna kSecClassGenericPassword och kSecClassInternetPassword är avsedda för lagring av textlösenord. Internetversionen lagrar även serverdata: domän, protokoll, port och autentiseringssökväg. GenericPassword används för lagring av alla lösenord utan koppling till en server.
Vid lagring av internetlösenord kan man ange kSecAttrServer (domän), kSecAttrProtocol (HTTPS, FTP etc.), kSecAttrPort och kSecAttrPath. Detta möjliggör exakt identifiering av posten vid automatisk ifyllning via AutoFill.
Klassen kSecClassKey lagrar symmetriska (AES) och asymmetriska (RSA, EC) nycklar. Klassen kSecClassCertificate — X.509-certifikat. Klassen kSecClassIdentity kombinerar den privata nyckeln och motsvarande certifikat i en post.
För asymmetriska nycklar stöder Keychain attributen: kSecAttrKeyType (RSA, EC), kSecAttrKeySizeInBits (2048, 256), kSecAttrIsPermanent (om de ska sparas i Keychain). För certifikat: kSecAttrLabel (människoläsbart namn), kSecAttrSubject (DN för ägare), kSecAttrIssuer (DN för utfärdare).
| Keychain-klass | Syfte | Datatyp |
|---|---|---|
| kSecClassGenericPassword | Applösenord | Data (NSString) |
| kSecClassInternetPassword | Serverlösenord | Data + serverattribut |
| kSecClassCertificate | X.509-certifikat | SecCertificate |
| kSecClassKey | Kryptografisk nyckel | SecKey |
| kSecClassIdentity | Nyckel + certifikat | SecIdentity |
Huvudgränssnittet för interaktion med Keychain i inbyggd iOS-kod — funktionerna i Security framework. För Swift och Objective-C finns ett C-gränssnitt tillgängligt, inslaget i bekväma funktioner.
Funktionen SecItemAdd lägger till ett nytt element i Keychain. Indata tar emot en ordbok med klass, data och attribut. Returnerar status errSecSuccess (0) eller felkod. Funktionen SecItemCopyMatching utför sökning baserat på attribut och returnerar hittade data.
För sökning används flaggan kSecReturnData — om den är true returnerar funktionen postens innehåll. Flaggan kSecMatchLimit bestämmer antalet resultat: kSecMatchLimitOne (ett) eller kSecMatchLimitAll (alla).
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 gör det möjligt att ändra attribut eller data för en befintlig post. SecItemDelete tar bort alla poster som matchar den angivna ordboken. Vid borttagning är det viktigt att ange tillräckligt med attribut för att inte av misstag ta bort andras poster i delad 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)
}
Varje Keychain-post har attributet kSecAttrAccessible, som bestämmer när data är tillgängliga för läsning. Detta är kritiskt för säkerheten: fel åtkomstnivå kan göra data sårbara eller omvänt otillgängliga vid rätt tillfälle.
kSecAttrAccessibleWhenUnlocked — data är endast tillgängliga när enheten är upplåst. kSecAttrAccessibleAfterFirstUnlock — tillgängliga efter första upplåsning efter omstart. kSecAttrAccessibleAlways — alltid tillgängliga (rekommenderas inte). Postfixet ThisDeviceOnly förbjuder överföring av data via säkerhetskopia.
På enheter med Secure Enclave kan Keychain-krypteringsnyckeln ytterligare skyddas med biometri: kSecAccessControlBiometryCurrentSet eller kSecAccessControlUserPresence. Detta lägger till ett Face ID- eller Touch ID-krav för varje läsoperation.
iCloud Keychain synkroniserar poster mellan Apple-enheter via end-to-end-kryptering. Apple har inte tillgång till dekrypterade data. För att aktivera synkronisering, lägg till attributet kSecAttrSynchronizable med värdet kCFBooleanTrue.
Viktigt: synkroniserade poster kan inte innehålla attributet ThisDeviceOnly, eftersom de måste vara tillgängliga på andra enheter. Vid förlust av alla enheter återställs iCloud Keychain via en återställningskod eller iCloud-säkerhetsnyckel.
För autentiseringstokens använd kSecAttrAccessibleWhenUnlockedThisDeviceOnly — data är endast tillgängliga på upplåst enhet och kopieras inte till säkerhetskopia. För certifikat som måste vara tillgängliga för bakgrundsuppgifter, använd kSecAttrAccessibleAfterFirstUnlock. Använd aldrig kSecAttrAccessibleAlways för konfidentiella data.
Det rekommenderas att alltid lägga till postfixet ThisDeviceOnly för data som inte kräver synkronisering. Detta förhindrar oavsiktlig kopiering av hemligheter till iCloud eller iTunes-säkerhetskopia, där de kan extraheras med analysverktyg. För kritiska data, kombinera tillgänglighet med kSecAccessControlUserPresence — detta lägger till ett biometri- eller kodkrav för dekryptering av posten.
Vid användning av iCloud Keychain bör du tänka på att synkroniserade poster är tillgängliga på alla användarens enheter: om en angripare får åtkomst till en enhet kan data äventyras på alla. För isolerade hemligheter, använd ThisDeviceOnly.
Vanliga frågor
UserDefaults lagrar data i öppen form i en .plist-fil, tillgänglig vid IPA-analys. Keychain krypterar varje post separat, använder hårdvarukryptering och stöder åtkomstnivåer, biometri och synkronisering via iCloud.
Vid varje start på iOS-simulatorn rensas Keychain. På en verklig enhet, ta bort applikationen — iOS tar bort alla Keychain-poster från denna utvecklare. För selektiv rensning, anropa SecItemDelete med lämpliga attribut.
Ja, via keychain access groups. Applikationer måste ha samma team-ID i signaturen och entitlements med samma keychain-access-groups. Utvecklaren konfigurerar delad åtkomst i Xcode Capabilities.
Apple dokumenterar ingen strikt gräns, men i praktiken rekommenderas att inte överskrida 1–4 KB per post. För stora volymer, använd filkryptering och lagring av nyckeln i Keychain, och själva data i Documents.
Efter jailbreak minskar Keychains skydd, eftersom angriparen får root-åtkomst och kan läsa Keychain SQLite direkt. För kritiska data, använd extra kryptering med en nyckel som erhållits från servern.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också