Skip to content

Instantly share code, notes, and snippets.

@isaidamier
Created February 19, 2020 18:05
Show Gist options
  • Save isaidamier/b88d10b36e5be3489cea837e9372711c to your computer and use it in GitHub Desktop.
Save isaidamier/b88d10b36e5be3489cea837e9372711c to your computer and use it in GitHub Desktop.
class MainActivity : AppCompatActivity() {
private lateinit var textInputView: AppCompatEditText
private lateinit var textOutputView: AppCompatTextView
private lateinit var biometricPrompt: BiometricPrompt
private lateinit var promptInfo: BiometricPrompt.PromptInfo
private var readyToEncrypt: Boolean = false
private lateinit var cryptographyManager: CryptographyManager
private lateinit var secretKeyName: String
private lateinit var ciphertext:ByteArray
private lateinit var initializationVector: ByteArray
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
cryptographyManager = CryptographyManager()
// e.g. secretKeyName = "biometric_sample_encryption_key"
secretKeyName = getString(R.string.secret_key_name)
biometricPrompt = createBiometricPrompt()
promptInfo = createPromptInfo()
textInputView = findViewById(R.id.input_view)
textOutputView = findViewById(R.id.output_view)
findViewById<Button>(R.id.encrypt_button).setOnClickListener { authenticateToEncrypt() }
findViewById<Button>(R.id.decrypt_button).setOnClickListener { authenticateToDecrypt() }
}
private fun createBiometricPrompt(): BiometricPrompt {
val executor = ContextCompat.getMainExecutor(this)
val callback = object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)
Log.d(TAG, "$errorCode :: $errString")
}
override fun onAuthenticationFailed() {
super.onAuthenticationFailed()
Log.d(TAG, "Authentication failed for an unknown reason")
}
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
Log.d(TAG, "Authentication was successful")
processData(result.cryptoObject)
}
}
//The API requires the client/Activity context for displaying the prompt view
val biometricPrompt = BiometricPrompt(this, executor, callback)
return biometricPrompt
}
private fun createPromptInfo(): BiometricPrompt.PromptInfo {
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle(getString(R.string.prompt_info_title)) // e.g. "Sign in"
.setSubtitle(getString(R.string.prompt_info_subtitle)) // e.g. "Biometric for My App"
.setDescription(getString(R.string.prompt_info_description)) // e.g. "Confirm biometric to continue"
.setConfirmationRequired(false)
.setNegativeButtonText(getString(R.string.prompt_info_use_app_password)) // e.g. "Use Account Password"
// .setDeviceCredentialAllowed(true) // Allow PIN/pattern/password authentication.
// Also note that setDeviceCredentialAllowed and setNegativeButtonText are
// incompatible so that if you uncomment one you must comment out the other
.build()
return promptInfo
}
private fun authenticateToEncrypt() {
readyToEncrypt = true
if (BiometricManager.from(applicationContext).canAuthenticate() == BiometricManager
.BIOMETRIC_SUCCESS) {
val cipher = cryptographyManager.getInitializedCipherForEncryption(secretKeyName)
biometricPrompt.authenticate(promptInfo, BiometricPrompt.CryptoObject(cipher))
}
}
private fun authenticateToDecrypt() {
readyToEncrypt = false
if (BiometricManager.from(applicationContext).canAuthenticate() == BiometricManager
.BIOMETRIC_SUCCESS) {
val cipher = cryptographyManager.getInitializedCipherForDecryption(secretKeyName,initializationVector)
biometricPrompt.authenticate(promptInfo, BiometricPrompt.CryptoObject(cipher))
}
}
private fun processData(cryptoObject: BiometricPrompt.CryptoObject?) {
val data = if (readyToEncrypt) {
val text = textInputView.text.toString()
val encryptedData = cryptographyManager.encryptData(text, cryptoObject?.cipher!!)
ciphertext = encryptedData.ciphertext
initializationVector = encryptedData.initializationVector
String(ciphertext, Charset.forName("UTF-8"))
} else {
cryptographyManager.decryptData(ciphertext, cryptoObject?.cipher!!)
}
textOutputView.text = data
}
companion object {
private const val TAG = "MainActivity"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment