微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将BiometricPrompt与CryptoObject结合使用以同时获得解密和加密的KeyStore访问权限?

如何解决如何将BiometricPrompt与CryptoObject结合使用以同时获得解密和加密的KeyStore访问权限?

问题描述:当使用BiometricPrompt身份验证访问Android KeyStore时,每次必须对KeyStore执行读或写操作时都会出现BiometricPrompt。我正在寻找一种只进行一次身份验证的解决方案,然后按照我希望的方式操纵密钥库中的数据,就像在iOS KeyChain上所做的那样。

我已经为Android实现了生物特征认证,以便可以通过在KeyStore params构建器上调用setUserAuthenticationrequired(true)将应用API AuthRefreshToken存储在由生物特征认证保护的应用程序KeyStore中(请参见下文)。我遵循了Google(https://github.com/android/security-samples/tree/main/BiometricLoginKotlin)和其他开发人员的示例,并使解决方案成功运行。我现在试图解决上述问题的第二个工作日没有成功,现在考虑使用不带CryptoObject的BiometricPrompt,这将是一个很大的失望。我怀疑有一段时间可以进行一次身份验证的方法,可能是通过设置paramsBuilder.setUserAuthenticationValidityDurationSeconds(30)来完成的,但是我无法达到预期的结果。

要使用KeyStore并读取API AuthRefreshToken,请使用以下代码

biometricPrompt = BiometricPromptUtils.createBiometricPrompt(this,::decryptServerTokenFromStorage)
val promptInfo = BiometricPromptUtils.createPromptInfo(this)
biometricPrompt.authenticate(promptInfo,BiometricPrompt.CryptoObject(cipher))

fun decryptServerTokenFromStorage(authResult: BiometricPrompt.AuthenticationResult) {
    ciphertextwrapper?.let { textwrapper ->
        authResult.cryptoObject?.cipher?.let {
            val authRefreshToken = cryptographyManager.decryptData(textwrapper.ciphertext,it)
            // Use authRefreshToken to get authToken from the API
            // The API returns new authRefreshToken which has to be saved back to the KeyStore
        }
    }
}

一切正常,我得到了解密的数据。但是,在使用AuthRefreshToken对应用程序API进行每次身份验证之后,令牌会更改,我必须立即将其保存回KeyStore。发生这种情况时,我使用下面的代码,再次显示BiometricPrompt。这将导致UI流程两次显示BiometricPrompt:

biometricPrompt = BiometricPromptUtils.createBiometricPrompt(this,::encryptServerTokenToStorage)
val promptInfo = BiometricPromptUtils.createPromptInfo(this)
biometricPrompt.authenticate(promptInfo,BiometricPrompt.CryptoObject(cipher))

fun encryptServerTokenToStorage(authResult: BiometricPrompt.AuthenticationResult) {
    authResult.cryptoObject?.cipher?.apply {
            SampleAppUser.refreshAuthToken?.let { refreshAuthToken ->
                Log.d(TAG,"The token from server is $refreshAuthToken")
                val encryptedServerTokenWrapper = cryptographyManager.encryptData(refreshAuthToken,this)
                // Now save encrypted authRefreshToken together with initializationVector in the app prefs for future authentications
            )
        }
    }
}

如何立即通过BiometricPrompt进行身份验证,以便我可以在1分钟或更长时间的间隔内对KeyStore进行完全读/写访问,而无需多次调用BiometricPrompt?

我尝试了不同的方法,并尝试为不同的目的重新创建密码或重新初始化密码,但是在所有这些尝试中,我都收到Javax.Crypto.IllegalBlockSizeException 消息“密钥用户未通过身份验证”

密钥库初始化如下:

    // If Secretkey was prevIoUsly created for that keyName,then grab and return it.
    val keyStore = KeyStore.getInstance(ANDROID_KEYSTORE)
    keyStore.load(null) // Keystore must be loaded before it can be accessed
    keyStore.getKey(keyName,null)?.let { return it as SecretKey }

    // if you reach here,then a new SecretKey must be generated for that keyName
    val paramsBuilder = KeyGenParameterSpec.Builder(
        keyName,KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
    )
    paramsBuilder.apply {
        setBlockModes(ENCRYPTION_BLOCK_MODE) // KeyProperties.BLOCK_MODE_GCM
        setEncryptionPaddings(ENCRYPTION_PADDING) // KeyProperties.ENCRYPTION_PADDING_NONE
        setKeySize(KEY_SIZE) // 256
        setUserAuthenticationrequired(true) // This is required for BiometricPrompt to work properly
    }

    val keyGenParams = paramsBuilder.build()
    val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES,"AndroidKeyStore")
    keyGenerator.init(keyGenParams)
    return keyGenerator.generateKey()
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。