4. Android Keystore系统概述

Android Keystore 并不是一个简单的“密钥文件仓库”,而是一套从应用 API 到系统服务、再到硬件安全模块的完整密钥管理链路。理解它的历史演进、架构分层以及 Keymaster/KeyMint 的角色,是后续进行密钥生成、加解密、签名验签和身份认证开发的基础。很多开发者只记住 KeyStore.getInstance("AndroidKeyStore") 这一行代码,却忽略了密钥真正存放在哪里、由谁保护、如何被硬件绑定,导致在设备迁移、指纹变更、系统升级时出现难以排查的问题。

一、历史演进:从文件密钥库到硬件密钥库

Android 的密钥管理经历了明显的三个阶段。早期 Android 2.x 到 4.x 时代,开发者通常使用 BKS 或 PKCS#12 文件型密钥库,密钥以软件形式保存在应用私有目录中。这类方案的问题很直接:只要设备被 root,攻击者就能复制密钥文件,密钥与设备之间没有强绑定关系。

Android 4.3(API 18)引入了 Android Keystore Provider,密钥开始由系统服务统一管理,应用只能通过句柄引用密钥,无法直接导出私钥。这是“密钥不离开安全边界”理念的起点。Android 6.0(API 23)进一步引入 Keymaster 2,支持 AES 对称密钥、指纹绑定和密钥认证。Android 7.0 引入 Keymaster 3,使用 HIDL 接口,并支持 ECDSA、RSA 的硬件密钥。Android 8.0 引入 Keymaster 4,支持 StrongBox 独立安全芯片。Android 12 开始,Google 推出 KeyMint 替代 Keymaster,使用 AIDL 接口,成为新设备的主流实现。

演进主线可以概括为:软件文件密钥库 → 系统托管密钥库 → 硬件支持密钥库 → 独立安全芯片密钥库。每一步都在缩小密钥暴露面,增强设备绑定与用户认证绑定能力。

二、架构组成:四层协作模型

Android Keystore 的架构可以划分为四个层次。最上层是应用层,开发者通过 KeyStore、KeyGenerator、KeyPairGenerator、Cipher、Signature 等标准 JCA/JCE API 访问密钥。第二层是框架层,由 keystore2 系统服务负责密钥生命周期管理、访问控制和权限校验。第三层是 HAL 层,即 Keymaster 或 KeyMint,负责把上层请求转换为具体安全环境可执行的密码学操作。最底层是安全环境,可能是 TEE(可信执行环境)、StrongBox 独立芯片,或在无硬件支持时退化为软件实现。

这种分层带来的关键特性是:应用拿到的不是密钥本身,而是密钥的别名和操作句柄。真正的私钥或对称密钥始终留在 TEE 或 StrongBox 中,加解密和签名操作在安全环境内部完成,应用只能获得结果。这就是 Android Keystore 与普通文件密钥库最本质的区别。

Android Keystore 四层架构与密钥流向 应用层 KeyStore / KeyGenerator / Cipher / Signature / KeyPairGenerator 只持有别名与句柄 Binder IPC 框架层:keystore2 系统服务 密钥生命周期管理 · 访问控制 · 权限校验 · 密钥认证 · 用户认证绑定 HAL 调用 HAL 层:Keymaster / KeyMint Keymaster 2/3/4(HIDL) · KeyMint(AIDL,Android 12+) 安全环境调用 安全环境 TEE 可信执行环境 · StrongBox 独立安全芯片 · 软件回退实现 私钥/对称密钥 永不离开此边界

三、Keymaster 与 KeyMint 的作用

Keymaster 和 KeyMint 是 Android Keystore 与安全硬件之间的“翻译官”和“执行器”。它们定义了一组标准接口,把上层“生成一个 RSA 2048 密钥”“用别名 myKey 做 SHA256withRSA 签名”这样的请求,转换为 TEE 或 StrongBox 能理解的命令。同时,它们还负责密钥的导入、导出(仅限公钥)、删除、认证、随机数生成和密钥证明。

Keymaster 早期使用 C++ 接口,Android 8 之后使用 HIDL。Android 12 引入的 KeyMint 改用 AIDL,接口更清晰,并强化了对 StrongBox、密钥认证和远程证明的支持。对于开发者而言,Keymaster 与 KeyMint 的差异通常被系统服务屏蔽,但在排查设备兼容性、密钥认证失败或 StrongBox 不可用时,必须知道当前设备到底走的是哪条 HAL 路径。

对比项 Keymaster KeyMint
引入版本 Android 6.0 起逐步完善 Android 12 起成为主流
接口方式 HIDL(Android 8+) AIDL
典型版本 Keymaster 2 / 3 / 4 KeyMint 1 / 2 / 3
StrongBox 支持 Keymaster 4 开始支持 原生强化支持
开发者感知 通常透明 通常透明,但影响设备能力

四、典型场景:密钥生成与签名调用链

下面以生成一个硬件支持的 EC 密钥并签名一段数据为例,展示从应用到安全环境的调用链。注意代码中并没有出现私钥,私钥始终由 KeyMint/Keymaster 在安全环境中持有。

KeyPairGenerator kpg = KeyPairGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");

kpg.initialize(new KeyGenParameterSpec.Builder(
        "mySignKey",
        KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
        .setDigests(KeyProperties.DIGEST_SHA256)
        .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
        .setUserAuthenticationRequired(true)
        .build());

KeyPair kp = kpg.generateKeyPair();

Signature sig = Signature.getInstance("SHA256withECDSA");
sig.initSign(kp.getPrivate());
sig.update("hello keystore".getBytes());
byte[] signature = sig.sign();

调用链为:应用调用 generateKeyPair() → keystore2 校验参数与权限 → KeyMint/Keymaster 在 TEE 或 StrongBox 中生成密钥 → 返回公钥和密钥别名。签名时,应用把数据交给 Signature,系统把数据送入安全环境,由安全环境用私钥完成签名,再把签名结果返回应用。

判断密钥是否真正受硬件保护,可以查看 KeyInfo 中的 isInsideSecureHardware(),或使用密钥认证(Key Attestation)解析证书扩展中的安全级别。不要仅凭“用了 AndroidKeyStore”就认为密钥一定在硬件中。

五、常见误区与复盘

  • 误区一:AndroidKeyStore 等于硬件密钥库。实际上它可能回退到软件实现,是否硬件保护取决于设备能力和密钥生成参数。
  • 误区二:密钥可以随意导出。私钥和对称密钥不可导出,只能导出公钥;试图导出私钥会抛出异常。
  • 误区三:忽略用户认证绑定。设置 setUserAuthenticationRequired(true) 后,密钥使用会受锁屏和生物识别状态影响,设备重置或指纹变更可能导致密钥失效。
  • 误区四:不处理 StrongBox 不可用。调用 setIsStrongBoxBacked(true) 时,若设备不支持会抛出 StrongBoxUnavailableException,应做好降级。
在设备迁移、系统升级或恢复出厂设置后,Android Keystore 中的密钥可能不可用。涉及长期数据加密时,应设计密钥轮换与数据恢复策略,避免把唯一密钥永久绑定在单一设备状态上。