我想使用 AES 加密和解密 SD 卡中的文件。为了做到这一点,我们总是需要一个种子(通常是用户作为密码插入的字符串):
public static byte[] generateKey(String password) throws Exception{
byte[] keyStart = password.getBytes("UTF-8");
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
sr.setSeed(keyStart);
kgen.init(128, sr);
SecretKey skey = kgen.generateKey();
return skey.getEncoded();
}
我想跳过此步骤(用户插入密码),只需要用户通过指纹传感器进行身份验证,然后开始加密过程!
我想知道是否有一种方法可以为接触指纹传感器的每个不同手指获取唯一密钥,该密钥可用作 SEED 来创建 SecretKey!?
我在 github 上阅读了一些关于 SO 和相关示例的问题,但我仍然找不到一种方法。
以清除问题:我已经完成了AES本身的实现,并且完全可以接受它,我只需要找到一种方法在身份验证后从指纹传感器获取唯一密钥。
更新 2019-10-14
TL;博士
不可以,您无法访问指纹。您只能从生物识别 API 获得"竖起大拇指"或"竖起大拇指"。这是有意为之。
但是,您可以利用 Android 密钥库进行硬件支持的加密操作,并要求用户重新进行身份验证才能释放密钥。这几乎可以满足您的需求。
长答案
从指纹生成类似密码的种子是不可能的。正如詹姆斯·波尔克(James K Polk)所评论的那样,指纹在扫描时会有所不同,并且它们永远不会直接清晰地存储在设备上。
注册指纹时,会临时存储其图像 在安全设备内存上,在其中对其进行处理以生成验证 数据和指纹模板(这些都无法访问 安卓操作系统)。然后丢弃原始图像。当手指 扫描后,将图像与生成的验证数据进行比较 之前,如果它匹配到一定程度的确定性,则用户是 被视为已通过身份验证。
生物识别操作在Android的可信执行环境(TEE)内进行。这是一个完全隔离的操作系统,可以在现代设备 (SE) 上单独协处理器上的 CPU 受保护部分上运行。
这是一个几乎不可触碰的环境,具有受限的接口和硬件屏障,以防止篡改芯片和强制提取生物识别验证数据和加密密钥。
溶液
回到你最初的问题,不,你不能得到任何唯一的手指识别。这本质上是不安全的,因为任何应用程序都可以读取机密!
您可以做的是利用Android的硬件支持的Keystore
,并要求设备级身份验证来释放硬件支持的加密密钥(setUserAuthenticationRequired(true)
)。这意味着生成一个随机密钥,该密钥安全地保存到密钥库中,需要手指滑动才能将密钥释放到用户空间。我怎么强调硬件支持这个词都不为过。
例如,您无法控制可以使用哪个手指,以及特定于供应商的实现是否允许使用设备解锁模式绕过生物识别。
安卓密钥库
密钥库的目的是保护加密密钥。只有在满足足够的要求(例如最近或立即的生物识别身份验证)后,拥有密钥的应用程序才能检索密钥。
可以保护密钥免受恶意提取,并且在现代设备上受硬件约束,这意味着它们永远不会离开安全硬件 (TEE/SE),因此永远不会暴露给您的 Android 应用程序。任何加密操作(如 AES 加密/解密)都在用户空间之外(在安全硬件上)安全地执行,注册新指纹/更改锁定模式将使密钥永久失效。在这种操作模式下,密钥库条目仅用作在安全硬件内执行加密操作的"接口",真正的机密永远不会暴露给您的应用程序。
总结
有一个指纹/生物识别API,它纯粹是为了方便起见,允许您通过要求用户进行身份验证来快速确认操作。它归结为TEE/SE的"是"/"否"答案,并且因手机制造商而异!
密钥库是用于加密密钥的硬件支持的保管库。运行 API 级别 28+ 的设备也可以访问Strongbox Keymaster(如果设备硬件支持),这会将加密操作限制为具有更安全存储的专用安全 CPU。
这些功能是特定于设备/供应商的!并且可能会受到损害/不安全!如果您不确定设备,请在启用指纹身份验证之前警告用户。唯一真正安全的加密方法是每次提示用户输入解密密钥(在这种情况下,头脑是硬件支持的存储)。将其存储在任何地方,即使是在实时内存中,也始终是一个经过计算的风险。
正确地进行密码学是极其困难的。我高度重视 建议您研究并尝试了解基础知识,以及什么 在尝试在尝试使用它之前,Android 必须提供额外的安全性 生产。