|
|
@@ -1,8 +1,21 @@
|
|
|
package com.iscs.bozzys.utils
|
|
|
|
|
|
+import android.app.Activity
|
|
|
import android.content.Context
|
|
|
+import android.os.Build
|
|
|
+import android.os.CancellationSignal
|
|
|
+import android.security.keystore.KeyGenParameterSpec
|
|
|
+import android.security.keystore.KeyProperties
|
|
|
import android.util.Log
|
|
|
import androidx.biometric.BiometricManager
|
|
|
+import androidx.biometric.BiometricPrompt
|
|
|
+import androidx.fragment.app.FragmentActivity
|
|
|
+import com.iscs.bozzys.utils.Storage.saveTokenIv
|
|
|
+import java.security.KeyStore
|
|
|
+import javax.crypto.Cipher
|
|
|
+import javax.crypto.KeyGenerator
|
|
|
+import javax.crypto.SecretKey
|
|
|
+import javax.crypto.spec.IvParameterSpec
|
|
|
|
|
|
/**
|
|
|
* 用于系统相关操作的功能
|
|
|
@@ -16,7 +29,6 @@ object SystemUtil {
|
|
|
fun Context.isBiometricCanUse(): Boolean {
|
|
|
val bm = BiometricManager.from(this)
|
|
|
val canAuth = bm.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)
|
|
|
- Log.d("xiaoming", "指纹功能是否可用:$canAuth")
|
|
|
return when (canAuth) {
|
|
|
// 可以使用指纹
|
|
|
BiometricManager.BIOMETRIC_SUCCESS -> true
|
|
|
@@ -31,4 +43,93 @@ object SystemUtil {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-}
|
|
|
+ /**
|
|
|
+ * 显示指纹验证
|
|
|
+ *
|
|
|
+ * @param act
|
|
|
+ */
|
|
|
+ fun showFingerAuth(act: Activity) {
|
|
|
+ if (act is FragmentActivity) {
|
|
|
+ val bp = BiometricPrompt(act, act.mainExecutor, object : BiometricPrompt.AuthenticationCallback() {
|
|
|
+
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ BiometricKeyStore.createKeyIfNeeded()
|
|
|
+ val cipher = BiometricKeyStore.encryptCipher()
|
|
|
+ val bp = android.hardware.biometrics.BiometricPrompt.Builder(act)
|
|
|
+ .setTitle("请验证")
|
|
|
+ .setNegativeButton("取消", act.mainExecutor) { _, _ ->
|
|
|
+ // onError("用户取消")
|
|
|
+ }
|
|
|
+ .build()
|
|
|
+ bp.authenticate(
|
|
|
+ android.hardware.biometrics.BiometricPrompt.CryptoObject(cipher),
|
|
|
+ CancellationSignal(),
|
|
|
+ act.mainExecutor,
|
|
|
+ object : android.hardware.biometrics.BiometricPrompt.AuthenticationCallback() {
|
|
|
+
|
|
|
+ override fun onAuthenticationSucceeded(result: android.hardware.biometrics.BiometricPrompt.AuthenticationResult) {
|
|
|
+ val cipher = result.cryptoObject?.cipher
|
|
|
+ cipher?.doFinal(Storage.readToken().toByteArray())?.let {
|
|
|
+ (it + cipher.iv).saveTokenIv()
|
|
|
+ }
|
|
|
+ // val = BiometricKeyStore.decryptCipher(Storage.readTokenIv())
|
|
|
+ // Log.d("xiaoming", "验证成功 ${String(Storage.readTokenIv())}")
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
|
|
+ Log.d("xiaoming", "验证失败")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 指纹签名校验操作
|
|
|
+ */
|
|
|
+object BiometricKeyStore {
|
|
|
+
|
|
|
+ private const val KEY_ALIAS = "biometric_key"
|
|
|
+ private const val ANDROID_KEYSTORE = "AndroidKeyStore"
|
|
|
+
|
|
|
+ fun createKeyIfNeeded() {
|
|
|
+ val ks = KeyStore.getInstance(ANDROID_KEYSTORE).apply { load(null) }
|
|
|
+ if (ks.containsAlias(KEY_ALIAS)) return
|
|
|
+
|
|
|
+ val generator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEYSTORE)
|
|
|
+
|
|
|
+ val spec = KeyGenParameterSpec.Builder(KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
|
|
|
+ .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
|
|
|
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
|
|
|
+ .setUserAuthenticationRequired(true)
|
|
|
+ .apply {
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
|
+ setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG)
|
|
|
+ } else {
|
|
|
+ setUserAuthenticationValidityDurationSeconds(-1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .build()
|
|
|
+
|
|
|
+ generator.init(spec)
|
|
|
+ generator.generateKey()
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun getKey(): SecretKey {
|
|
|
+ val ks = KeyStore.getInstance(ANDROID_KEYSTORE).apply { load(null) }
|
|
|
+ return ks.getKey(KEY_ALIAS, null) as SecretKey
|
|
|
+ }
|
|
|
+
|
|
|
+ fun encryptCipher(): Cipher =
|
|
|
+ Cipher.getInstance("AES/CBC/PKCS7Padding").apply {
|
|
|
+ init(Cipher.ENCRYPT_MODE, getKey())
|
|
|
+ }
|
|
|
+
|
|
|
+ fun decryptCipher(iv: ByteArray): Cipher =
|
|
|
+ Cipher.getInstance("AES/CBC/PKCS7Padding").apply {
|
|
|
+ init(Cipher.DECRYPT_MODE, getKey(), IvParameterSpec(iv))
|
|
|
+ }
|
|
|
+}
|