Keychain Services Implementation
Keychain Services Implementation
The iOS Keychain provides secure storage for passwords, tokens, and other sensitive data. Proper implementation ensures data remains protected even if the device is compromised.
Secure Keychain Operations:
import Security
import LocalAuthentication
class KeychainManager {
// Save sensitive data with biometric protection
func saveToBiometricKeychain(data: Data, identifier: String) -> Bool {
// Create access control with biometric requirement
var error: Unmanaged<CFError>?
guard let accessControl = SecAccessControlCreateWithFlags(
kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
[.biometryCurrentSet, .privateKeyUsage],
&error
) else {
return false
}
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: identifier,
kSecValueData as String: data,
kSecAttrAccessControl as String: accessControl,
kSecUseAuthenticationContext as String: LAContext()
]
// Delete any existing item
SecItemDelete(query as CFDictionary)
// Add new item
let status = SecItemAdd(query as CFDictionary, nil)
return status == errSecSuccess
}
// Retrieve data with proper error handling
func retrieveFromKeychain(identifier: String) -> Data? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: identifier,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne,
kSecUseOperationPrompt as String: "Authenticate to access your data"
]
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
guard status == errSecSuccess,
let data = result as? Data else {
return nil
}
return data
}
// Generate and store cryptographic keys
func generateSecureKey(identifier: String) -> SecKey? {
let attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits as String: 256,
kSecPrivateKeyAttrs as String: [
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: identifier.data(using: .utf8)!,
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
]
]
var error: Unmanaged<CFError>?
let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error)
return privateKey
}
}