Biometric Security in Android Applications
Introduction
In recent years, the Android team’s focus has been mostly on improving security and privacy. Pattern/pin lock has been around for years in Android, and as an enhancement, fingerprint authentication was introduced a couple of years ago. Now it’s time to make enhancements to fingerprint authentication, and that’s known as biometric authentication.
Biometric authentication is more secure and easier to use, which comes in handy in many situations, such as authorization for payments, secure and simple login, authentication while accessing sensitive data, and more.
Check Availability
Before enabling this type of authentication for the user, it’s a good practice to check whether the device is compatible with biometric authentication.
Integration
We need to add the following line under the AndroidManifest.xml file. Have a look
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
Working
Firstly when you create the project a Main Activity is created. Now create another activity and name them as Welcome Activity(or name as per your choice).
Now create a class file with name FingerPrintHelper Class. In this class we have to implement four methods :
Authentication SUCCESS
: The device can work with biometric authentication.Authentication Error
: No biometric features are available on this device.Authentication Help
: Biometric features is unable to detect your fingerprint.Authentication Failed
: The user hasn’t associated any biometric credentials in the device yet.
Let’s have a look :
import android.content.Context
import android.hardware.fingerprint.FingerprintManager
import android.os.CancellationSignal
import androidx.core.app.ActivityCompat
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.widget.Toast
/**
@author bhavyasharma
**/
class FingerPrintHelper(private val context: Context) : FingerprintManager.AuthenticationCallback(){
lateinit var cancellationSignal : CancellationSignal
fun startAuth(manager: FingerprintManager, cryptoObject: FingerprintManager.CryptoObject){
cancellationSignal = CancellationSignal()
if(ActivityCompat.checkSelfPermission(context,Manifest.permission.USE_FINGERPRINT)!= PackageManager.PERMISSION_GRANTED) {
return
}
manager.authenticate(cryptoObject,cancellationSignal,0,this,null)
}
override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
super.onAuthenticationError(errorCode, errString)
Toast.makeText(context,"Authentication Error",Toast.LENGTH_SHORT).show()
}
override fun onAuthenticationSucceeded(result: FingerprintManager.AuthenticationResult?) {
super.onAuthenticationSucceeded(result)
Toast.makeText(context,"Authentication Success",Toast.LENGTH_SHORT).show()
context.startActivity(Intent(context,WelcomeActivity::class.java))
}
override fun onAuthenticationHelp(helpCode: Int, helpString: CharSequence?) {
super.onAuthenticationHelp(helpCode, helpString)
Toast.makeText(context,"Finger cannot be detected.Try Again!",Toast.LENGTH_SHORT).show()
}
override fun onAuthenticationFailed() {
super.onAuthenticationFailed()
Toast.makeText(context,"Authentication Failed",Toast.LENGTH_SHORT).show()
}
}
Now in Main Activity :
import android.Manifest
import android.app.KeyguardManager
import android.content.Context
import android.content.pm.PackageManager
import android.hardware.fingerprint.FingerprintManager
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import android.widget.Toast
import androidx.core.app.ActivityCompat
import java.lang.Exception
import java.security.KeyStore
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
/**
@author bhavyasharma
**/
class MainActivity : AppCompatActivity() {
lateinit var fm : FingerprintManager
lateinit var km : KeyguardManager
lateinit var keyStore : KeyStore
lateinit var keyGenerator : KeyGenerator
var KEY_NAME = "my_key"
lateinit var cipher : Cipher
lateinit var cryptoObject : FingerprintManager.CryptoObject
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
km = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
fm = getSystemService(Context.FINGERPRINT_SERVICE) as FingerprintManager
if(!km.isKeyguardSecure){
Toast.makeText(this,"Lock screen security not enabled in settings.",Toast.LENGTH_SHORT).show()
return
}
if(!fm.hasEnrolledFingerprints()){
Toast.makeText(this,"Register atleast one fingerprint in settings.",Toast.LENGTH_SHORT).show()
return
}
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT)!=PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.USE_FINGERPRINT),111)
}
else
validateFingerPrint()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if(requestCode==111 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
validateFingerPrint()
}
}
private fun validateFingerPrint() {
// Generating Key...
try {
keyStore = KeyStore.getInstance("AndroidKeyStore")
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES,"AndroidKeyStore")
keyStore.load(null)
keyGenerator.init(KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build())
keyGenerator.generateKey()
}catch (e: Exception){ }
// Initialization of Cryptography
if(initCipher()){
cipher.let {
cryptoObject = FingerprintManager.CryptoObject(it)
}
}
var helper = FingerPrintHelper(this)
if(fm!= null && cryptoObject!=null){
helper.startAuth(fm,cryptoObject)
}
}
private fun initCipher() : Boolean {
try {
cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES+"/"+KeyProperties.BLOCK_MODE_CBC+"/"+KeyProperties.ENCRYPTION_PADDING_PKCS7)
}catch(e:Exception){}
try {
keyStore.load(null)
val key = keyStore.getKey(KEY_NAME,null) as SecretKey
cipher.init(Cipher.ENCRYPT_MODE,key)
return true
}catch (e:Exception){return false}
}
}
Now take a look at .xml files also :
First create an icon in your drawable file. Icon is available in your “vector asset” ie. fingerprint icon. After that :
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="150dp"
android:layout_height="150dp"
android:src="@drawable/ic_fingerprint"
android:layout_marginTop="100dp"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="68dp"
android:text="Touch the sensor"
android:textSize="40sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/imageView" />
</androidx.constraintlayout.widget.ConstraintLayout>
Now in activity_welcome.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context=".WelcomeActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:textSize="25sp"
android:textStyle="bold"
android:text="Authentication is Successfully Running"/>
</LinearLayout>
Now you can run your project in your device and application is working . To get code of it visit to my github profile :
https://github.com/bhavya104/Biometric-Security
Thank you for reading.