三、Keystore 系统架构与能力边界
Android Keystore 是系统级密钥管理基础设施,通过分层架构将密钥生命周期与硬件安全模块(HSM)绑定。理解其架构层次、不可导出性机制及与软件 Keystore 的界限,是安全蓝牙数据加密的前提。
3.1 硬件安全模块(HSM)
Android 设备通常集成两种硬件安全模块:
- TEE(Trusted Execution Environment):基于 ARM TrustZone 或类似技术,在 CPU 内部划分安全世界与普通世界。密钥运算在安全世界隔离执行,即使内核被攻破也无法窃取密钥材料。
- SE(Secure Element):独立安全芯片(如 eSE、SIM 卡 SE),具备防篡改物理封装,常用于支付和认证场景。Android StrongBox Keymaster 是 SE 的典型实现。
建议:蓝牙数据加密应优先使用 TEE 支持的 KeyStore 实例。仅在需要最高安全等级(如配对证书签名)时使用 StrongBox,但需注意其并发性能和密钥槽位限制。
3.2 密钥不可导出性(Key Unavailability)
Android KeyStore 保证:
- 密钥材料一旦生成,应用层永远无法获取明文密钥字节。
getEncoded()或getPublicKey()仅返回公钥或元数据,私钥/密钥字节直接返回null。- 硬件支持的密钥在 TEE/SE 内生成并保留,系统重启后仍持久化,但导出请求会由 HAL 层拦截。
- 软件 Keystore 类型(不推荐)才允许通过 Provider 获取密钥字节,但会触发安全警告。
常见错误:开发者在导出对称密钥时调用
key.getEncoded() 期望得到字节数组,但在硬件 Keystore 下始终返回 null。正确做法是使用 KeyStore.SecretKeyEntry 并仅执行加密/解密操作,而非导出密钥。
// 错误示例:尝试导出硬件密钥字节
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey("bt_enc_key", null);
byte[] rawKey = key.getEncoded(); // 始终为 null if hardware-backed
// 正确做法:直接使用密钥对象执行操作
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encrypted = cipher.doFinal(plaintext);
3.3 Android KeyStore vs 软件 Keystore
| 对比维度 | Android KeyStore(硬件) | 软件 Keystore(如 Bouncy Castle) |
|---|---|---|
| 密钥隔离 | 硬件隔离(TEE/SE),应用不可读 | 进程内存,可能被 dump |
| 不可导出性 | 强制:私钥/密钥字节永远不可导出 | 可导出,依赖开发者保护 |
| 密钥生成 | KeyGenParameterSpec 指定用途,硬件生成 | KeyPairGenerator 直接生成字节 |
| 算法支持 | 受限但安全(AES/RSA/EC/等,见 3.4) | 所有 JCA 算法 |
| 性能 | 硬件运算慢(尤其对称密钥操作) | 软件运算快 |
| 适用场景 | 蓝牙配对密钥、长生命周期密钥 | 短期会话密钥、非安全场景 |
决策指南:对于蓝牙数据加密,应始终创建
KeyGenParameterSpec.Builder 时设置 setIsStrongBoxBacked(boolean) 选择硬件支持。仅当目标设备不支持硬件 Keystore(API 23 以下)时回退到软件 Keystore,并明确记录安全风险。
3.4 支持算法列表
Android KeyStore 支持的算法取决于设备硬件(Keymaster 版本)和 API 级别。以下为常见可用算法(API 28+ 典型支持):
| 算法类型 | 具体算法 | Keymaster 要求 | 蓝牙场景用途 |
|---|---|---|---|
| 对称加密 | AES/GCM/NoPadding (128/256) | Keymaster 1+ | 蓝牙数据传输加密 |
| AES/CTR/NoPadding | Keymaster 1+ | 可替代 GCM(需自行处理 IV) | |
| 非对称加密 | RSA/ECB/PKCS1Padding (2048+) | Keymaster 1+ | 蓝牙配对密钥交换 |
| EC (P-256, P-384, P-521) | Keymaster 2+ | ECDH 密钥协商 | |
| ECIES (需 Provider 支持) | Keymaster 3+ | 混合加密 | |
| 摘要 Hash | SHA-256 / SHA-384 / SHA-512 | Keymaster 1+ | 消息认证码 HMAC 的基础 |
| SHA-1 (已弃用) | Keymaster 1+ | 兼容旧版本(不推荐) | |
| MAC | HmacSHA256 / HmacSHA384 | Keymaster 1+ | 蓝牙数据完整性校验 |
| AES-CMAC (部分设备) | Keymaster 3+ | 替代 HMAC |
版本兼容提醒:Keymaster 版本对应 Android API 级别:Keymaster 1(API 23+)、Keymaster 2(API 24+)、Keymaster 3(API 28+)、Keymaster 4(API 31+)。在
KeyGenParameterSpec.Builder 中通过 setKeySize() 和 setAlgorithmParameterSpec() 指定算法时,应使用 Security.getProviders() 检查运行时支持。
// 检查设备是否支持 AES-256 GCM 硬件密钥
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
try {
KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder("bt_aes_key",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setKeySize(256)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build();
KeyGenerator kg = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
kg.init(spec);
kg.generateKey();
Log.i("KeyStore", "AES-256 GCM hardware key created");
} catch (InvalidAlgorithmParameterException e) {
Log.w("KeyStore", "Hardware key not supported, try software fallback");
}
}
已知限制:部分低端设备 TEE 仅支持 AES-128,Keymaster 3 以下不支持 ECDH,或 StrongBox 密钥槽数有限(通常 4-16 个)。生产环境务必通过
KeyStore.getKeyCharacteristics() 验证实际能力,避免运行时崩溃。