Android - 如何从指纹认证中获取唯一密钥?
Android - how to get Unique key from Finger-Print Authentication?
我想使用 AES 加密和解密 SD 卡中的文件。为了做到这一点,我们总是需要一个 seed (通常是用户插入的字符串作为密码):
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;DR
不,您不能访问指纹。您只能通过生物识别 API 获得 "thumbs up" 或 "thumbs down"。这是故意设计的。
但是,您可以利用 Android 密钥库进行硬件支持的加密操作,并要求用户重新验证以释放密钥。这几乎可以满足您的需求。
长答案
从指纹生成类似密码的种子不可能。正如 James K Polk 评论的那样,指纹在扫描时会有所不同,并且它们 从未清晰地直接存储在设备上 。
When a fingerprint is being enrolled, its image is temporarily stored
on secure device memory, where it is processed to generate validation
data and a fingerprint template (these are all inaccessible to the
Android OS). The raw image is then discarded. When a finger is
scanned, the image is compared to the validation data generated
before, and if it matches to a certain degree of certainty, a user is
deemed as authenticated.
生物识别操作在 Android 的 可信执行环境 (TEE) 中进行。这是一个完全隔离的 OS 运行 或者在 CPU 的受保护部分,在现代设备 (SE) 的单独协处理器上。
这是一个几乎不可触及的环境,具有受限的接口和硬件屏障,以防止篡改芯片和强制提取生物识别验证数据和加密密钥。
解决方案
回到你原来的问题,不,你不能得到任何唯一的指纹识别。这本质上是不安全的,因为任何应用程序都可以读取秘密!
您可以做的是利用Android的硬件支持Keystore
并需要设备级身份验证来发布硬件支持的加密密钥(setUserAuthenticationRequired(true)
)。这意味着生成一个安全保存到密钥库的随机秘密,需要手指滑动才能将密钥释放到用户空间。 硬件支持这个词怎么强调都不为过。
例如,您无法控制可以使用哪个手指以及特定于供应商的实现是否允许使用设备解锁模式绕过生物识别。
Android 密钥库
Keystore 的目的是保护加密密钥。只有在满足足够的要求(例如最近或即时的生物识别身份验证)后,拥有密钥的应用程序才能检索密钥。
密钥可以防止恶意提取,在现代设备上,hardware bound,这意味着它们永远不会离开安全硬件 (TEE/SE),因此永远不会暴露给您的 Android 应用。任何加密操作,例如 AES encryption/decryption,都在用户空间之外(在安全硬件上)安全地执行,并且注册新的 fingerprints/changing 锁定模式将使密钥永久无效。在这种操作模式下,Keystore 条目仅用作 "interface" 在安全硬件内部进行加密操作,真正的秘密永远不会暴露给您的应用程序。
总结
有一个 Fingerprint/Biometric API,它纯粹是为了方便,允许您通过要求用户进行身份验证来快速确认操作。它归结为来自 TEE/SE 的 "yes"/"no" 答案,并且因 phone 制造商而异!
Keystore 是一个由硬件支持的加密密钥保管库。设备 运行 API-level 28+ 也可以访问 Strongbox Keymaster,如果设备硬件支持它,这将加密操作限制为专用安全 CPU 更安全的存储。
这些功能是 device/vendor 特有的!并且可能是 compromised/insecure!如果您对设备不确定,请在启用指纹身份验证之前警告用户。
仅 真正安全的加密方法是提示用户 每次 解密密钥(在这种情况下,头脑是硬件支持的存储) .将它存储在任何地方,即使是在实时内存中,也始终是一个经过计算的风险。
Doing cryptography right is extremely difficult. I highly
advise that you research and try to understand the basics, and what
additional security Android has to offer, before attempting to use this in
production.
我想使用 AES 加密和解密 SD 卡中的文件。为了做到这一点,我们总是需要一个 seed (通常是用户插入的字符串作为密码):
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;DR
不,您不能访问指纹。您只能通过生物识别 API 获得 "thumbs up" 或 "thumbs down"。这是故意设计的。
但是,您可以利用 Android 密钥库进行硬件支持的加密操作,并要求用户重新验证以释放密钥。这几乎可以满足您的需求。
长答案
从指纹生成类似密码的种子不可能。正如 James K Polk 评论的那样,指纹在扫描时会有所不同,并且它们 从未清晰地直接存储在设备上 。
When a fingerprint is being enrolled, its image is temporarily stored on secure device memory, where it is processed to generate validation data and a fingerprint template (these are all inaccessible to the Android OS). The raw image is then discarded. When a finger is scanned, the image is compared to the validation data generated before, and if it matches to a certain degree of certainty, a user is deemed as authenticated.
生物识别操作在 Android 的 可信执行环境 (TEE) 中进行。这是一个完全隔离的 OS 运行 或者在 CPU 的受保护部分,在现代设备 (SE) 的单独协处理器上。
这是一个几乎不可触及的环境,具有受限的接口和硬件屏障,以防止篡改芯片和强制提取生物识别验证数据和加密密钥。
解决方案
回到你原来的问题,不,你不能得到任何唯一的指纹识别。这本质上是不安全的,因为任何应用程序都可以读取秘密!
您可以做的是利用Android的硬件支持Keystore
并需要设备级身份验证来发布硬件支持的加密密钥(setUserAuthenticationRequired(true)
)。这意味着生成一个安全保存到密钥库的随机秘密,需要手指滑动才能将密钥释放到用户空间。 硬件支持这个词怎么强调都不为过。
例如,您无法控制可以使用哪个手指以及特定于供应商的实现是否允许使用设备解锁模式绕过生物识别。
Android 密钥库
Keystore 的目的是保护加密密钥。只有在满足足够的要求(例如最近或即时的生物识别身份验证)后,拥有密钥的应用程序才能检索密钥。
密钥可以防止恶意提取,在现代设备上,hardware bound,这意味着它们永远不会离开安全硬件 (TEE/SE),因此永远不会暴露给您的 Android 应用。任何加密操作,例如 AES encryption/decryption,都在用户空间之外(在安全硬件上)安全地执行,并且注册新的 fingerprints/changing 锁定模式将使密钥永久无效。在这种操作模式下,Keystore 条目仅用作 "interface" 在安全硬件内部进行加密操作,真正的秘密永远不会暴露给您的应用程序。
总结
有一个 Fingerprint/Biometric API,它纯粹是为了方便,允许您通过要求用户进行身份验证来快速确认操作。它归结为来自 TEE/SE 的 "yes"/"no" 答案,并且因 phone 制造商而异!
Keystore 是一个由硬件支持的加密密钥保管库。设备 运行 API-level 28+ 也可以访问 Strongbox Keymaster,如果设备硬件支持它,这将加密操作限制为专用安全 CPU 更安全的存储。
这些功能是 device/vendor 特有的!并且可能是 compromised/insecure!如果您对设备不确定,请在启用指纹身份验证之前警告用户。 仅 真正安全的加密方法是提示用户 每次 解密密钥(在这种情况下,头脑是硬件支持的存储) .将它存储在任何地方,即使是在实时内存中,也始终是一个经过计算的风险。
Doing cryptography right is extremely difficult. I highly advise that you research and try to understand the basics, and what additional security Android has to offer, before attempting to use this in production.