三、Keystore 系统架构与能力边界

Android Keystore 是系统级密钥管理基础设施,通过分层架构将密钥生命周期与硬件安全模块(HSM)绑定。理解其架构层次、不可导出性机制及与软件 Keystore 的界限,是安全蓝牙数据加密的前提。

Android KeyStore 系统架构图 App (应用) KeyStore API KeyStore Provider KeyStore HAL TEE SE 密钥材料(不可导出) 关键路径 1. App 调用 KeyStore API 2. Provider 解析操作类型 3. HAL 分发到硬件安全模块 4. TEE/SE 执行运算并返回 不可导出性保障 密钥材料仅在 TEE/SE 内存 应用/系统进程均无法读取 导出操作返回 null

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 保证:

  1. 密钥材料一旦生成,应用层永远无法获取明文密钥字节。
  2. getEncoded() 或 getPublicKey() 仅返回公钥或元数据,私钥/密钥字节直接返回 null。
  3. 硬件支持的密钥在 TEE/SE 内生成并保留,系统重启后仍持久化,但导出请求会由 HAL 层拦截。
  4. 软件 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() 验证实际能力,避免运行时崩溃。