2. 平台原生安全存储API选型
移动端与桌面端操作系统各自提供了专用的安全存储接口,用于处理密钥、令牌、证书等敏感数据。直接使用这些原生 API 而非自行实现加密存储,能有效降低密钥管理漏洞与侧信道攻击的风险。本章对四大主流平台的原生方案进行技术对比,帮助开发者在跨平台组件中做出合理选型。
2.1 选型决策框架
选择安全存储 API 时需从以下维度评估:
- 加密机制:是否依赖硬件安全模块(HSM/TEE/SE);
- 数据粒度:支持键值对、二进制 blob 还是结构化记录;
- 跨进程访问:是否允许同一设备上的多个应用共享;
- 备份与迁移:数据是否随系统备份导出,影响安全边界;
- 平台耦合度:是否要求特定的系统版本或硬件特性。
2.2 各平台 API 详解
2.2.1 Android · EncryptedSharedPreferences
Android 从 API 23 起在 AndroidX Security 库中提供 EncryptedSharedPreferences,底层使用 AES-256 GCM 加密键值,密钥由 Android Keystore 保管。
典型初始化代码:
MasterKey masterKey = new MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
SharedPreferences prefs = EncryptedSharedPreferences.create(
context,
"secure_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
prefs.edit().putString("access_", ).apply();
适用场景:应用内小型键值对存储(OAuth 、session ID、设备指纹);多进程场景需谨慎,默认不跨进程共享。
常见错误:
- 使用
commit()而非apply()导致 UI 线程阻塞; - 未处理
KeyStoreException(如锁屏密码变更导致密钥不可用); - 在 API 23 以下设备直接调用,未做兼容。
2.2.2 iOS · Keychain Services
iOS Keychain 使用硬件加密引擎,数据以加密记录形式存储在安全隔区(Secure Enclave)管理的区域,iOS 10.3 后支持 iCloud 同步。
写入操作示例(Swift):
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "com.app.account.",
kSecValueData as String: tokenData,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
let status = SecItemAdd(query as CFDictionary, nil)
if status != errSecSuccess && status != errSecDuplicateItem {
// 错误处理
}
适用场景:密码、密钥、证书、持久化会话;需要 iCloud 同步时使用 kSecAttrSynchronizable;跨应用共享通过 Keychain Access Group 实现。
性能优化:避免频繁读写单条大记录;使用 kSecUseDataProtectionKeychain 属性启用文件级保护以降低 I/O 开销。
2.2.3 Windows · Credential Manager
Windows 凭据管理器将数据加密存储在用户配置文件中,支持 Web 凭据和通用凭据两种类型,加密依赖于 DPAPI。
写入 API(Win32):
CREDENTIAL cred = {0};
cred.Type = CRED_TYPE_GENERIC;
cred.TargetName = L"MyApp/SecureKey";
cred.CredentialBlobSize = (DWORD)dataSize;
cred.CredentialBlob = (LPBYTE)data;
cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
BOOL result = CredWrite(&cred, 0);
适用场景:Windows 桌面应用和服务;企业环境中与 Active Directory 集成;不支持跨平台移动端共享。
常见错误:
- 未检查
CredWrite返回值和GetLastError(); CredentialBlobSize设置错误导致截断;- 使用
CRED_PERSIST_SESSION导致凭据在注销后丢失。
2.2.4 Linux · secret-tool (libsecret)
Linux 通过 D-Bus 服务 secret-service 提供安全存储,命令行工具 secret-tool 和 libsecret 库封装了与 GNOME Keyring / KDE Wallet 的交互。
命令行存储示例:
secret-tool store --label="MyApp " service myapp access_
读取示例:
secret-tool lookup service myapp access_
libsecret C API 示例片段:
SecretSchema schema = {
"com.myapp.secret",
SECRET_SCHEMA_NONE,
{
{ "service", SECRET_SCHEMA_ATTRIBUTE_STRING },
{ "", SECRET_SCHEMA_ATTRIBUTE_STRING },
}
};
gchar *password = secret_password_lookup_sync(
&schema, NULL, NULL,
"service", "myapp",
"", "access_",
NULL);
适用场景:Linux 桌面和嵌入式应用;需要与 GNOME/KDE 环境集成;密钥存储依赖桌面环境的密钥环守护进程。
2.3 API 能力对比表
| 维度 | Android EncryptedSP | iOS Keychain | Windows CredMan | Linux libsecret |
|---|---|---|---|---|
| 硬件依赖 | Keystore(TEE/SE) | Secure Enclave | DPAPI(TPM) | 无硬件要求 |
| 加密算法 | AES-256 GCM | AES-256 + SHA-512 | 3DES/AES | AES-256 GCM |
| 数据模型 | 键值对 | 分层记录 + ACL | 凭据 Blob | 键值属性 |
| 跨进程 | 不支持 | Access Group | 支持 | D-Bus 共享 |
| 备份行为 | 跟随应用备份 | 可选 iCloud | 不自动备份 | 跟随密钥环备份 |
| 最低 API 版本 | API 23+ | iOS 9+ | Vista+ | GLib 2.44+ |
2.4 选型决策流程
下图展示了在组件内集成敏感数据持久化时的平台 API 推荐选型路径:
2.5 常见错误与调试方法
| 平台 | 常见错误 | 调试手段 |
|---|---|---|
| Android | KeyStoreException: KeyStore not initialized | 检查 Keystore 实例化是否在后台线程;确认设备锁屏状态 |
| iOS | errSecItemNotFound | 确认查询参数(kSecAttrAccount)完全匹配写入时的值;检查 Access Group 权限 |
| Windows | ERROR_NOT_FOUND (1168) | 使用 CredEnumerate 枚举所有凭据验证目标名称;检查应用程序清单中 supportedOS 配置 |
| Linux | GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown | 确认 secret-service 守护进程(gnome-keyring-daemon)正在运行;检查 DBUS_SESSION_BUS_ADDRESS 环境变量 |
SecureStorageProvider 接口,并在单元测试中注入 mock 实现。这样可以在不依赖实际安全硬件的情况下验证业务逻辑。