I'm using the ANDROID BIOMETRIC LIBRARY for authentication and encryption. Right now it uses the fingerprint but I want it to use the default lock screen password/pin when fingerprint isn't enabled.
object BiometricPromptUtils { private const val TAG = "BiometricPromptUtils" fun createBiometricPrompt( activity: AppCompatActivity, processCancel: () -> Unit, processSuccess: (BiometricPrompt.CryptoObject?) -> Unit ): BiometricPrompt { val executor = ContextCompat.getMainExecutor(activity) val callback = object : BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationError(errCode: Int, errString: CharSequence) { super.onAuthenticationError(errCode, errString) Log.d(TAG, "errCode is $errCode and errString is: $errString") if ( (errCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON) or (errCode == BiometricPrompt.ERROR_USER_CANCELED) ) { processCancel() } } override fun onAuthenticationFailed() { super.onAuthenticationFailed() Log.d(TAG, "Biometric authentication failed for unknown reason.") } override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { super.onAuthenticationSucceeded(result) Log.d(TAG, "Authentication was successful") processSuccess(result.cryptoObject) } } return BiometricPrompt(activity, executor, callback) } fun createPromptInfo(activity: AppCompatActivity): BiometricPrompt.PromptInfo { return BiometricPrompt.PromptInfo.Builder().apply { setTitle(activity.getString(R.string.prompt_info_title)) setConfirmationRequired(false) setNegativeButtonText(activity.getString(R.string.prompt_info_cancel_text)) }.build() } } interface CryptographyManager { fun getInitializedCipherForEncryption(keyName: String): Cipher fun getInitializedCipherForDecryption(keyName: String, initializationVector: ByteArray): Cipher fun encryptData(plaintext: String, cipher: Cipher): EncryptedData fun decryptData(ciphertext: ByteArray, cipher: Cipher): String fun saveEncryptedDataToSharedPrefs( encryptedData: EncryptedData, context: Context, filename: String, mode: Int, prefKey: String ) fun getEncryptedDataFromSharedPrefs( context: Context, filename: String, mode: Int, prefKey: String ): EncryptedData? fun isDataExistInSharedPrefs(context: Context, filename: String, mode: Int, prefKey: String): Boolean } fun CryptographyManager(): CryptographyManager = CryptographyManagerImpl() data class EncryptedData(val ciphertext: ByteArray, val initializationVector: ByteArray) private class CryptographyManagerImpl : CryptographyManager { private val KEY_SIZE: Int = 256 val ANDROID_KEYSTORE = "AndroidKeyStore" private val ENCRYPTION_BLOCK_MODE = KeyProperties.BLOCK_MODE_GCM private val ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_NONE private val ENCRYPTION_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES override fun getInitializedCipherForEncryption(keyName: String): Cipher { val cipher = getCipher() val secretKey = getOrCreateSecretKey(keyName) cipher.init(Cipher.ENCRYPT_MODE, secretKey) return cipher } override fun getInitializedCipherForDecryption(keyName: String, initializationVector: ByteArray): Cipher { val cipher = getCipher() val secretKey = getOrCreateSecretKey(keyName) cipher.init(Cipher.DECRYPT_MODE, secretKey, GCMParameterSpec(128, initializationVector)) return cipher } override fun encryptData(plaintext: String, cipher: Cipher): EncryptedData { val ciphertext = cipher.doFinal(plaintext.toByteArray(Charset.forName("UTF-8"))) return EncryptedData(ciphertext,cipher.iv) } override fun decryptData(ciphertext: ByteArray, cipher: Cipher): String { val plaintext = cipher.doFinal(ciphertext) return String(plaintext, Charset.forName("UTF-8")) } override fun saveEncryptedDataToSharedPrefs( encryptedData: EncryptedData, context: Context, filename: String, mode: Int, prefKey: String ) { val json = Gson().toJson(encryptedData) context.getSharedPreferences(filename, mode).edit().putString(prefKey, json).apply() } override fun getEncryptedDataFromSharedPrefs( context: Context, filename: String, mode: Int, prefKey: String ): EncryptedData? { val json = context.getSharedPreferences(filename, mode).getString(prefKey, null) return Gson().fromJson(json, EncryptedData::class.java) } override fun isDataExistInSharedPrefs( context: Context, filename: String, mode: Int, prefKey: String ): Boolean { val pref = context.getSharedPreferences(filename, mode).getString(prefKey, null) return pref != null } private fun getCipher(): Cipher { val transformation = "$ENCRYPTION_ALGORITHM/$ENCRYPTION_BLOCK_MODE/$ENCRYPTION_PADDING" return Cipher.getInstance(transformation) } private fun getOrCreateSecretKey(keyName: String): SecretKey { // 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) setEncryptionPaddings(ENCRYPTION_PADDING) setKeySize(KEY_SIZE) setUserAuthenticationRequired(true) } val keyGenParams = paramsBuilder.build() val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEYSTORE) keyGenerator.init(keyGenParams) return keyGenerator.generateKey() } }
https://stackoverflow.com/questions/67358706/how-to-use-lock-screen-password-instead-of-fingerprint May 03, 2021 at 12:27AM
没有评论:
发表评论