Android Keystore 系统如何保护密钥不被导出?

解读

面试官问“如何保护密钥不被导出”,并不是想听你背诵 Keystore 的类名,而是考察:

  1. 是否真正理解“密钥一旦可以被导出,就等于泄露”这一安全底线;
  2. 是否清楚 Keystore 从硬件到系统再到应用的完整信任链;
  3. 能否结合国内项目经验,把 TEE、SELinux、密钥属性、生物识别等机制串成闭环,并给出可落地的编码/测试方案。

知识点

  1. 安全边界

    • TEE(可信执行环境):国内主流 SoC(麒麟、高通、MTK)均通过中国泰尔实验室可信认证,TEE OS 与 REE 物理隔离,密钥明文只在 TEE 内出现。
    • SELinux + 密钥守护进程:Android 10 以后强制启用 keystore2 SELinux policy,守护进程(keystore2 / keymint)以 system_keystore 域运行,拒绝任何 uid≠system 的 ptrace 与 open。
  2. 密钥生命周期

    • 生成:GenerateKey 时指定 PURPOSE_ENCRYPT|PURPOSE_DECRYPT,排除 PURPOSE_EXPORT;若标记为 hardware-backed,则 TEE 返回 KeyBlob,REE 侧仅存加密句柄。
    • 使用:通过 IKeyMintDevice::begin() 把请求送入 TEE,运算结果由 TEE 加密后返回到用户态,明文永不离开安全世界。
    • 销毁:Keymaster 2.0+ 支持 key attestation extension,国内厂商(华为、OPPO、vivo)在出厂证书链里加入 SM2 国密根证书,可远程验证密钥是否已被吊销。
  3. 国内合规要求

    • 国密算法:金融类 App(银行、支付)需通过人行《移动金融客户端规范》,要求 RSA/ECC 密钥长度≥256 位,SM4 密钥必须存储在 TEE,且提供 SM2 签名证书链。
    • 数据出境:若业务需把密文同步到海外服务器,必须走国家网信办安全评估;Keystore 本身禁止任何“密钥出境”行为,否则无法通过应用商店安全扫描。
  4. 编码与测试

    • 强制硬件:setIsStrongBoxRequired(true) 在 Pixel 与国内部分旗舰机可调用独立安全芯片;若设备不支持,则回退 TEE,但拒绝纯软件实现。
    • 用户认证绑定:setUserAuthenticationRequired(true) + setUserAuthenticationValidityDurationSeconds(0) 配合 BiometricPrompt,实现“每次使用即指纹/人脸”,防止锁屏被绕过。
    • 单元测试:使用 androidx.security.crypto 的 MasterKeys 方案,配合 Robolectric 4.9+ 的 ShadowKeyStore 模拟硬件失败路径,确保在 TEE 不可用时应用主动降级或熔断。

答案

Android Keystore 通过“硬件隔离 + 系统强制访问控制 + 密钥属性白名单”三级机制,保证密钥不可导出:

  1. 硬件层:密钥在 TEE 或独立安全芯片内生成,私钥明文永不离开安全世界;REE 侧仅拿到句柄。
  2. 系统层:keystore2 守护进程以 SELinux system_keystore 域运行,拒绝非系统组件的 ptrace、open、ioctl;KeyBlob 用 TEE 存储密钥加密,拆包即自毁。
  3. 应用层:生成密钥时显式排除 PURPOSE_EXPORT,并绑定用户生物特征与锁屏状态;每次运算都通过 Binder 调用到 TEE,返回结果而非密钥。
  4. 合规层:国内金融 App 需通过泰尔实验室可信认证与国密检测,密钥链含 SM2 根证书,确保即使云端也无法获取私钥。

因此,只要密钥标记为 hardware-backed 且 PURPOSE 不包含 EXPORT,无论 Root、调试器还是恶意应用,都无法把密钥从 Keystore 中完整读出。

拓展思考

  1. 如果项目需要支持低端机(无 TEE),如何平衡安全与体验?
    • 采用“服务端派生 + 客户端会话密钥”混合方案:主密钥放服务端,Keystore 仅保存一次性会话密钥,有效期≤24 h;同时启用 Google Play App Signing 或国内应用商店签名保护,降低密钥泄露后的影响面。
  2. 国内折叠屏/双系统设备(工作资料 vs 个人资料)对 Keystore 的影响?
    • Android 13 开始,工作资料与个人资料分别挂载不同 TEE 存储域,KeyBlob 绑定 Profile ID;跨资料访问会触发 INVALID_KEY_USER 错误,需在代码里捕获并提示用户切换资料。
  3. 未来趋势:Android 14 引入“Ultra-wideband Keystore”与“隐私沙盒”后,密钥将支持跨设备安全共享,但国内需适配国密且通过工信部备案;面试时可主动提及自己已关注 AOSP 14 的 KeyMint 3.0 接口变化,体现技术前瞻性。