Developer guide on keychain for iOS
Learn how to securely store passwords with Apple's Keychain API.
23 Jan 2023 · 4 min read
Apple's Keychain Services API allows us to store sensitive user data like passwords, credit card information or certificates in an encrypted database.
Let's see how to do that.

Saving keychain items
To store a secret in the keychain, the first step is to define a query.
A query consists of key-value pairs containing:
- the type of the keychain item
- the sensitive data we would like to store
- attributes which help us to identify the item later
For example, a query to store a password might look as follows:
let query: [CFString: Any] = [kSecClass: kSecClassGenericPassword,kSecAttrAccount: username,kSecValueData: passwordData]
In the example above, we create a dictionary with 3 key-value pairs:
The kSecClass key indicates the keychain item type, in our case a password. Other available item types are:
- kSecClassInternetPassword to store Internet passwords.
- kSecClassCertificate to store certificates.
- kSecClassKey to store cryptographic keys.
- kSecClassIdentity to store identities.
The kSecAttrAccount key is used to define the item's account name, in our case the username. Each keychain type defines a different set of attributes we can provide to be able to identify the item later, to store additional information together with the password or to configure some options.
For example, we can use the kSecAttrAccessible key to set the conditions under which an app can access the password, for example by setting it to kSecAttrAccessibleWhenUnlocked will only grant access when the device is unlocked.
By using the kSecValueData key, we provide the password we'd like to store in form of a Data type.
With the query in place, we can use the SecItemAdd(_:_:) method to create and store the keychain item:
let status = SecItemAdd(query as CFDictionary, nil)guard status == errSecSuccess else {throw KeychainError.errorWithStatus(status)}
The SecItemAdd(_:_:) method returns a status code which we can use to check if the process was successfull.
Retrieving keychain items
To retrieve the password from the keychain, we use the same query approach we used to save it:
let query: [CFString: Any] = [kSecClass: kSecClassGenericPassword,kSecAttrAccount: username,kSecReturnData: true]
After creating the query, we can use the SecItemCopyMatching(_:_:) method to get the password data.
var result: CFTypeRef?let status = SecItemCopyMatching(query as CFDictionary, &result)guard status != errSecItemNotFound else { throw KeychainError.noPassword }guard status == errSecSuccess else { throw KeychainError.errorWithStatus(status) }guard let passwordData = result as? Data else { throw KeychainError.unexpectedPasswordData }
The only thing left to do is to convert the data back to a String type:
String(data: passwordData, encoding: String.Encoding.utf8)
Updating and deleting keychain items
Updating and deleting keychain items works with the same query pattern we used before.
To update a password, we can use the SecItemUpdate(_:_:) method and the SecItemDelete(_:) method to delete it.
Conclusion
When using the Keychain Services API, we need to interact with C code, which can be hard to use and understand. It would be great to see Apple providing a more simplified API in the future. For now, we could use a third party library such as KeychainAccess to get a more simplified API.

Newsletter
Like to support my work?
Say hi
Related tags
Articles with related topics
Latest articles and tips