How do you generate and store a Themis key pair on iOS?
Explanation & Code
Answer:
Generate the pair with TSKeyGen, then persist only the private key in the Keychain with a restrictive accessibility class and hand the public key to the server during enrolment. The private key must never reach UserDefaults, a plist, a log line, or an analytics event.
TSKeyGen(algorithm: .EC) returns 256-bit elliptic-curve keys, which are the sensible default — smaller and faster than the RSA option, with no practical security tradeoff. Store the raw Data rather than a Base64 string where you can; if the API forces Base64, remember the encoding adds no protection.
For a device-bound key you can go further and wrap the Themis private key with a Secure Cell sealed under a Keychain item that requires biometric presence, so the key is only usable after a successful Face ID or Touch ID check.
Code Example:
import themis
import Security
func enrol() throws -> Data {
guard let pair = TSKeyGen(algorithm: .EC) else { throw CryptoError.keygen }
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "client.private.key",
kSecValueData as String: pair.privateKey as Data,
// Never syncs to iCloud, unavailable until after first unlock.
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
]
SecItemDelete(query as CFDictionary)
guard SecItemAdd(query as CFDictionary, nil) == errSecSuccess else {
throw CryptoError.keychain
}
return pair.publicKey as Data // send to the server
}
Key Points:
- Prefer
.ECover.RSA— smaller keys, faster operations. ...ThisDeviceOnlyaccessibility keeps the key out of iCloud Keychain and encrypted backups.- Keychain items survive app deletion; clear them on first launch if you want a fresh key per install.
Rate your understanding: