'Key user not authenticated',了解 Android 密钥库

'Key user not authenticated', Understanding the Android KeyStore

我正在尝试将秘密安全地存储在 Android 应用程序中。为此,我想使用 Android KeyStore 中的密钥对它们进行加密,类似于您在 iOS 上使用 KeyChain 所做的操作。我跟着this Guide只需要考虑Android 6.0+

据我了解,KeyStore 是由 Android 提供的安全存储。但是,我真的不明白是谁解锁了对密钥库的访问。我目前所做的是,我使用以下方法创建了一个密钥:

private SecretKey generateKey(String keyAlias) {
    try {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);

        keyGenerator.init(new KeyGenParameterSpec.Builder(keyAlias, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setUserAuthenticationRequired(true)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                .build());
        return keyGenerator.generateKey();
    } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
        // handling...
    }
}

现在使用此密钥在使用 android.security.KeyStoreException: Key user not authenticated 加密期间失败。我看到设置 setUserAuthenticationRequired(true) 需要身份验证,但是,我看不到如何提供此身份验证。我假设只要用户解锁了他的 phone,KeyStore 就可以访问。我了解到需要指纹传感器来验证 KeyStore 的用户身份,但是,许多 Android 设备还没有指纹传感器。

如果您将 "AndroidKeyStore" 指定为提供程序,则在设备支持的情况下将使用安全的硬件支持的密钥库。这意味着在实践中应该不可能 * 提取私钥 material,即使对于您自己的应用程序也是如此。

其他应用也应该不可能/很难使用您创建的密钥。但我并不真正了解这是如何执行的。

您可以使用 KeyInfogetOriginisInsideSecureHardware 方法检查您创建的密钥是否由 / 生成并存储在安全硬件中。

*显然,这取决于设备的安全硬件模块是否得到了很好的实施并且没有可利用的错误。过去发现了一些实际的漏洞利用,尽管它们需要对设备 IIRC 进行物理访问。关键是没有什么是 100% 安全的。


Now using this key fails during encryption with an android.security.KeyStoreException: Key user not authenticated.

默认情况下,setUserAuthenticationRequired(true)表示每次使用密钥都需要授权,唯一的授权方式就是指纹认证。

您可以使用 setUserAuthenticationValidityDurationSeconds to specify that you want the key to be usable for a certain amount of time after the last authorization. In this case, the key becomes usable as soon as the user provides any of their screen unlock credentials,不管它们是什么。