跳到主要内容

Keychain

问题

Keychain 的原理是什么?如何安全存储敏感信息?

答案

Keychain vs UserDefaults

KeychainUserDefaults
加密✅ 系统硬件加密❌ 明文
删除 App 后⚠️ 数据保留数据删除
访问控制可设置生物识别
性能较慢(加密解密)
适用密码、Token、证书设置、偏好

使用 Security 框架

class KeychainManager {
static func save(key: String, data: Data) -> Bool {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecValueData as String: data
]
SecItemDelete(query as CFDictionary) // 先删除旧值
let status = SecItemAdd(query as CFDictionary, nil)
return status == errSecSuccess
}

static func load(key: String) -> Data? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
return status == errSecSuccess ? result as? Data : nil
}

static func delete(key: String) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key
]
SecItemDelete(query as CFDictionary)
}
}

// 存储 Token
let token = "eyJhbGciOiJIUzI1NiJ9..."
KeychainManager.save(key: "accessToken", data: token.data(using: .utf8)!)
推荐使用封装库

原生 Keychain API 基于 C 语言字典,使用繁琐。推荐使用 KeychainAccess 等封装库。


常见面试问题

Q1: 删除 App 后 Keychain 数据还在吗?

答案:默认情况下 Keychain 数据在 App 删除后仍然保留(直到 Keychain 条目被显式删除或设备重置)。如果需要随 App 删除,可以在首次启动时检查并清理。

Q2: Keychain 可以在 App 之间共享数据吗?

答案:可以。通过 Keychain Access Groups(需要在 Entitlements 中配置相同的 group),同一开发者的不同 App 可以共享 Keychain 数据。

相关链接