我希望使用Android硬件支持的KeyStore,但是我担心安全性和可用性。
从我读过here的内容来看,除非用户省略了setEncryptionRequired(),否则当用户更改设备锁定时,KeyStore会被擦除。出于可用性考虑,似乎需要这样做,否则一旦修改了设备锁,所有由硬件支持的键都会被擦除。

但是,我也读过here,它说硬件支持的 key 实际上并没有存储在TEE中,而是作为 key 文件存储在/data/misc/keystore/user_0/中,并通过存储在设备中的设备特定 key 进行加密。球座。由于设备锁的更改会擦除KeyStore,因此似乎设备特定的 key 是从设备锁派生的。

出于安全原因,对 key 文件进行加密是有意义的,否则任何root用户都将能够读取 key 文件并提取私钥,因为它们大概处于清除状态。

所以我有点陷入困境。出于可用性考虑,我应该省略setEncryptionRequired(),但是出于安全考虑,我应该设置setEncryptionRequired()。

最后,是否可以使用setKeyEntry()将私钥导入到硬件支持的KeyStore中?我能够做到这一点而没有错误,但是我不确定它是否由硬件支持。

我的理解正确吗?

最佳答案

setEncryptionRequired()在Android 6.0(Marshmallow)中已弃用,但从未真正完成。 Android KeyStore的安全性取决于TEE,而不取决于密码。

您链接到的博客文章已经过时,至少在运行Android 6.0或更高版本的设备上已经过时。在这些设备上,您不应使用setEncryptionRequired(),并且在卸载应用程序(或完成出厂重置或您的应用程序删除它们)之前,不会删除您的 key 。您的 key 将被永远不会离开TEE的 secret key 安全地包裹起来。实际上,您的 key 永远不会以明文形式离开TEE。使用 key 时,数据与加密 key 一起传递到TEE中。 TEE解开 key ,然后处理并返回加密/签名/任何数据。

是的,您可以使用setKeyEntry()导入私钥。如果要确保您的 key 是硬件支持的,请使用KeyInfo.isInsideSecureHardware()。例如(这来自the documentation):

PrivateKey key = ...; // Android KeyStore key

KeyFactory factory = KeyFactory.getInstance(key.getAlgorithm(), "AndroidKeyStore");
KeyInfo keyInfo;
boolean isHardwareBacked = false;
try {
    keyInfo = factory.getKeySpec(key, KeyInfo.class);
    isHardwareBacked = keyInfo.isInsideSecureHardware();
} catch (InvalidKeySpecException e) {
    // Not an Android KeyStore key.
}

09-17 13:19