gpt4 book ai didi

android - 添加新指纹时不会抛出 KeyPermanentlyInvalidatedException

转载 作者:行者123 更新时间:2023-11-29 18:27:51 26 4
gpt4 key购买 nike

我有 CipherUtils 类,它负责创建取自 the google dialog sample 的密码


import android.annotation.TargetApi
import android.app.Application
import android.app.KeyguardManager
import android.content.SharedPreferences
import android.hardware.fingerprint.FingerprintManager
import android.os.Build
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyPermanentlyInvalidatedException
import android.security.keystore.KeyProperties
import androidx.core.content.ContextCompat.getSystemService
import androidx.core.content.edit
import java.io.IOException
import java.security.*
import java.security.cert.CertificateException
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.NoSuchPaddingException
import javax.crypto.SecretKey
import javax.inject.Inject


class CipherUtils @Inject constructor(
val application: Application,
val sharedPreferences: SharedPreferences
) {
internal val DEFAULT_KEY_NAME = "ubit_key"
private val KEY = "fingerInvalid"

private var mKeyStore: KeyStore? = null
private var mKeyGenerator: KeyGenerator? = null
private var defaultCipher: Cipher

init {

try {
mKeyStore = KeyStore.getInstance("AndroidKeyStore")
} catch (e: KeyStoreException) {
throw RuntimeException("Failed to get an instance of KeyStore", e)
}

try {
mKeyGenerator = KeyGenerator
.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
} catch (e: NoSuchAlgorithmException) {
throw RuntimeException("Failed to get an instance of KeyGenerator", e)
} catch (e: NoSuchProviderException) {
throw RuntimeException("Failed to get an instance of KeyGenerator", e)
}

try {
defaultCipher = Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7
)
} catch (e: NoSuchAlgorithmException) {
throw RuntimeException("Failed to get an instance of Cipher", e)
} catch (e: NoSuchPaddingException) {
throw RuntimeException("Failed to get an instance of Cipher", e)
}

init()
}

@TargetApi(Build.VERSION_CODES.M)
private fun init() {
val keyguardManager = getSystemService(application,KeyguardManager::class.java)
val fingerprintManager = getSystemService(application,FingerprintManager::class.java)

if (!keyguardManager!!.isKeyguardSecure()) {
// Show a message that the user hasn't set up a fingerprint or lock screen.
return
}

// Now the protection level of USE_FINGERPRINT permission is normal instead of dangerous.
// See http://developer.android.com/reference/android/Manifest.permission.html#USE_FINGERPRINT
// The line below prevents the false positive inspection from Android Studio
// noinspection ResourceType
if (!fingerprintManager!!.hasEnrolledFingerprints()) {
// This happens when no fingerprints are registered.

return
}
createKey(DEFAULT_KEY_NAME, true)
}

/**
* Creates a symmetric key in the Android Key Store which can only be used after the user has
* authenticated with fingerprint.
*
* @param keyName the name of the key to be created
* @param invalidatedByBiometricEnrollment if `false` is passed, the created key will not
* be invalidated even if a new fingerprint is enrolled.
* The default value is `true`, so passing
* `true` doesn't change the behavior
* (the key will be invalidated if a new fingerprint is
* enrolled.). Note that this parameter is only valid if
* the app works on Android N developer preview.
*/
@TargetApi(Build.VERSION_CODES.M)
fun createKey(keyName: String, invalidatedByBiometricEnrollment: Boolean) {
// The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint
// for your flow. Use of keys is necessary if you need to know if the set of
// enrolled fingerprints has changed.
try {
mKeyStore?.load(null)
// Set the alias of the entry in Android KeyStore where the key will appear
// and the constrains (purposes) in the constructor of the Builder

val builder = KeyGenParameterSpec.Builder(
keyName,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
// Require the user to authenticate with a fingerprint to authorize every use
// of the key
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)

// This is a workaround to avoid crashes on devices whose API level is < 24
// because KeyGenParameterSpec.Builder#setInvalidatedByBiometricEnrollment is only
// visible on API level +24.
// Ideally there should be a compat library for KeyGenParameterSpec.Builder but
// which isn't available yet.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
builder.setInvalidatedByBiometricEnrollment(invalidatedByBiometricEnrollment)
}
mKeyGenerator?.init(builder.build())
mKeyGenerator?.generateKey()
} catch (e: NoSuchAlgorithmException) {
throw RuntimeException(e)
} catch (e: InvalidAlgorithmParameterException) {
throw RuntimeException(e)
} catch (e: CertificateException) {
throw RuntimeException(e)
} catch (e: IOException) {
throw RuntimeException(e)
}

}

/**
* Initialize the [Cipher] instance with the created key in the
* [.createKey] method.
*
* @param keyName the key name to init the cipher
* @return `true` if initialization is successful, `false` if the lock screen has
* been disabled or reset after the key was generated, or if a fingerprint got enrolled after
* the key was generated.
*/
@TargetApi(Build.VERSION_CODES.M)
private fun initCipher(cipher: Cipher, keyName: String): Boolean {
try {
mKeyStore?.load(null)
val key = mKeyStore?.getKey(keyName, null) as SecretKey
cipher.init(Cipher.ENCRYPT_MODE, key)
return true
} catch (e: KeyPermanentlyInvalidatedException) {
return false
} catch (e: KeyStoreException) {
throw RuntimeException("Failed to init Cipher", e)
} catch (e: CertificateException) {
throw RuntimeException("Failed to init Cipher", e)
} catch (e: UnrecoverableKeyException) {
throw RuntimeException("Failed to init Cipher", e)
} catch (e: IOException) {
throw RuntimeException("Failed to init Cipher", e)
} catch (e: NoSuchAlgorithmException) {
throw RuntimeException("Failed to init Cipher", e)
} catch (e: InvalidKeyException) {
throw RuntimeException("Failed to init Cipher", e)
}

}

}

注册新指纹时,运行 initCipher,我希望得到 KeyPermanentlyInvalidatedException 但它返回 true。我缺少什么以及如何解决此问题以了解何时添加了新指纹?

最佳答案

我搜索了很多,找到了答案 in a comment in issues

This sample creates a new key in onCreate, so if you launch the sample app after you add a new fingerprint, KeyPermanentlyInvalidatedException is not thrown because at the time the key is created, a set of fingerprints include the new created one.

If you want to test that KeyPermanentlyInvalidatedException, please try to add a new fingerprint while keeping the app open.

但我希望此功能在应用程序关闭时起作用。所以在创建新 key 之前添加了几行代码,我检查之前是否有 key ,如果存在则不创建。

/**
* returns current saved key
*/
private fun getCurrentKey(keyName: String): Key? {
keyStore?.load(null)
return keyStore?.getKey(keyName, null)
}

并将其替换为代码的创建 key 部分

/**
* Only if the key is not created, Create a new key
*/
private fun createKeyIfNotExists() {
if (getCurrentKey(DEFAULT_KEY_NAME) == null) {
createKey(DEFAULT_KEY_NAME, true)
}
}

关于android - 添加新指纹时不会抛出 KeyPermanentlyInvalidatedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57944220/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com