Android中如何安全获取用户密钥并分享给其他用户?KeyStore方案咨询
解决Android密钥安全存储与授权导出问题
一、Android KeyStore的可行配置方案
Android KeyStore并非完全无法导出密钥,核心在于生成密钥时的参数配置。你可以在生成密钥时同时开启可导出性和用户认证要求,具体实现步骤如下:
- 生成用于加密存储项的对称密钥时,通过
KeyGenParameterSpec.Builder配置关键参数:KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder( "my_data_key", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT ) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setUserAuthenticationRequired(true) // 强制用户完成认证(指纹/密码/图案) .setUserAuthenticationValidityDurationSeconds(30) // 认证后30秒内可操作密钥 .setExtractable(true) // 开启密钥导出权限 .build(); KeyGenerator keyGenerator = KeyGenerator.getInstance( KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore" ); keyGenerator.init(spec); SecretKey dataKey = keyGenerator.generateKey(); - 用户完成认证(比如通过
BiometricPrompt验证指纹)后,即可通过KeyStore.getKey()获取密钥,转换为可导出的格式(如Base64编码),再用B、C的公钥加密后发送给对方。
注意:部分厂商定制的Android系统可能对KeyStore的可导出参数有额外限制,需在目标设备上测试验证。
二、替代方案:信封加密模式(更安全的实践)
如果不想依赖KeyStore的导出能力,推荐采用信封加密,从根源上避免导出用户A的密钥:
- 用户A生成一次性数据加密密钥(DEK,AES类型),用DEK加密目标存储项;
- 获取用户B、C的RSA公钥,分别用他们的公钥加密DEK,得到各自对应的加密DEK副本;
- 将加密后的存储项,加上对应B、C的加密DEK副本一同上传至服务器;
- 用户B、C下载后,用自己的RSA私钥解密对应的DEK副本,再用DEK解密存储项。
这种模式下,用户A的密钥全程无需导出,极大降低了密钥泄露的风险,是加密授权场景的最佳实践。
三、基于用户密码的密钥派生方案
如果上述两种方案不适用,可采用PBKDF2密钥派生方案:
- 用户A设置强密码,结合随机盐、高迭代次数,通过PBKDF2算法派生出主密钥;
- 用主密钥加密数据密钥(DEK),将加密后的DEK、盐、迭代次数存储在本地;
- 用户认证时(输入密码),重新派生主密钥,解密出DEK,再用B、C的公钥加密DEK后发送。
缺点:该方案依赖用户密码的强度,若密码被破解,密钥会面临泄露风险,需提醒用户设置强密码。
内容的提问来源于stack exchange,提问作者Mai3
相关产品推荐
相关产品推荐

