Untuk melindungi data yang sensitif kita membutuhkan sebuah pengamanan yang hanya di akses oleh orang itu sendiri. Beberapa tahun terakhir perangkat android menyediakan autentifikasi biometrik menggunakan sidik jari, sehingga jika ingin membuka aplikasi, selain menggunakan username-password ataupun menggunakan nomor telepon kita bisa sebagai pengembang aplikasi bisa menambahkan fitur autentifikasi dengan sidik jari. Sehingga data pengguna lebih aman karena hanya dia sendiri yang bisa mengakses aplikasi tersebut. Anda juga bisa menggunakan jasa pembuatan aplikasi mobile yang ditawarkan oleh CAN Creative
Penerapan autentifiaksi sidik jari ini sendiri dimulai di android versi 6.0 dengan nama Marshmallows. Untuk versi android dibawah tersebut tidak mendapat dukungan sidik jari ini. Kita dapat mengimplementasikan sensor ini di perangkat yang tersedia sensor sidik jarinya.
Android Tutorial CAN Creative
Langsung saja kita implementasikan penggunaan sensor ini.
Pertama kita buat dulu projek dengan minimal APInya 6.0 Marshmallows dan pastinya menggunakan bahasa kotlin ya.
Setelah selesai membuat projeknya, kita buka AndroidManifest.xml dan tambahkan ijin untuk menggunakan sensor fingerprint tersebut.
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
Selanjutnya kita buat sebuah class kotlin dengan nama FingerprintHelper. Class ini berfungsi untuk penggunaan fingerprint sehingga kita tau respon ketika kita sedang melakukan autentifikasi sidik jari, apakah gagal, berhasil atau membutuhkan bantuan.
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.hardware.fingerprint.FingerprintManager
import android.os.CancellationSignal
import android.widget.Toast
import androidx.core.app.ActivityCompat
class FingerprintHelper(private val appContext: Context) : FingerprintManager.AuthenticationCallback() {
lateinit var cancellationSignal: CancellationSignal
fun startAuth(manager: FingerprintManager,
cryptoObject: FingerprintManager.CryptoObject) {
cancellationSignal = CancellationSignal()
if (ActivityCompat.checkSelfPermission(appContext,
Manifest.permission.USE_FINGERPRINT) !=
PackageManager.PERMISSION_GRANTED) {
return
}
manager.authenticate(cryptoObject, cancellationSignal, 0, this, null)
}
override fun onAuthenticationError(errMsgId: Int,
errString: CharSequence) {
Toast.makeText(appContext, "Autentifikasi bermasalah \n" + errString,
Toast.LENGTH_LONG).show()
}
override fun onAuthenticationHelp(helpMsgId: Int,
helpString: CharSequence) {
Toast.makeText(appContext,
"Autentifikasi membutuhkan bantuan \n" + helpString,
Toast.LENGTH_LONG).show()
}
override fun onAuthenticationFailed() {
Toast.makeText(appContext,
"Autentifikasi gagal.",
Toast.LENGTH_LONG).show()
}
override fun onAuthenticationSucceeded(
result: FingerprintManager.AuthenticationResult) {
Toast.makeText(appContext,
"Autentifikasi berhasil.",
Toast.LENGTH_LONG).show()
}
}
Selanjutnya kita buka activity_main.xml kita untuk membuat tampilan sederhana dan tambahkan kode seperti di bawah ini :
<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">
<TextView
android:id="@+id/tv_fingerprint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tekan Fingerprint"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Selanjutnya kita buka MainActivity.class kita, disini kita akan menerapkan fungsi dari autentifikasi sidik jari itu sendiri, kita akan menambahkan beberapa method dengan fungsi masing masing. Pertama kita inisialisasi dulu beberapa kelas library yang di butuhkan seperti FingerprintManager, KeyguardManager, KeyStore, KeyGenerator, Chiper dan ChiperObject dari FingerprintManager.
class MainActivity : AppCompatActivity() {
private lateinit var fingerprintManager: FingerprintManager
private lateinit var keyguardManager: KeyguardManager
private lateinit var keyStore: KeyStore
private lateinit var keyGenerator: KeyGenerator
private val KEY_NAME = "key_saya"
private lateinit var cipher: Cipher
private lateinit var cryptoObject: FingerprintManager.CryptoObject
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Selanjutnya kita buat sebuat method dengan nama checkLockScreen() method ini berfungsi untuk memeriksa apakah perangkat mengaktifkan kunci layarnya sehingga kita bisa menggunakan sensor ini dengan sidik jari yang sama.
private fun checkLockScreen(): Boolean {
keyguardManager = getSystemService(Context.KEYGUARD_SERVICE)
as KeyguardManager
fingerprintManager = getSystemService(Context.FINGERPRINT_SERVICE)
as FingerprintManager
if (keyguardManager.isKeyguardSecure == false) {
Toast.makeText(this,
"Kunci layar tiak di aktifkan",
Toast.LENGTH_LONG).show()
return false
}
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.USE_FINGERPRINT) !=
PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,
"Ijin untuk sidik jari tidak diaktifkan",
Toast.LENGTH_LONG).show()
return false
}
if (fingerprintManager.hasEnrolledFingerprints() == false) {
Toast.makeText(this,
"Tidak ada sidik jari terdaftar, silahkan daftar sidik jari anda",
Toast.LENGTH_LONG).show()
return false
}
return true
}
Selanjutnya kita buat method dengan nama generateKey(). di method ini kita harus membuat kunci enkripsi kemudian di simpan di Sistem Android Keystore. Disini kita harus mendapatkan akses dan kunci enkripsi di method ini. Bisa code di bawah ini.
private fun generateKey() {
try {
keyStore = KeyStore.getInstance("AndroidKeyStore")
} catch (e: Exception) {
e.printStackTrace()
}
try {
keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES,
"AndroidKeyStore")
} catch (e: NoSuchAlgorithmException) {
throw RuntimeException(
"Gagal untuk mendapatkan KeyGenerator", e)
} catch (e: NoSuchProviderException) {
throw RuntimeException("Gagal untuk mendapatkan KeyGenerator", e)
}
try {
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: NoSuchAlgorithmException) {
throw RuntimeException(e)
} catch (e: InvalidAlgorithmParameterException) {
throw RuntimeException(e)
} catch (e: CertificateException) {
throw RuntimeException(e)
} catch (e: IOException) {
throw RuntimeException(e)
}
}
Setelah kita membuat kunci di generateKey(), langkah selanjutnya kita menginisialiasi chiper yang menggunakan instance CriptoObject. CroptoObject inilah yang akan kita gunakan selama proses autentifikasi menggunakan sidik jari. Sebagai contohnya, bisa lihat kode dibawah ini.
private fun initCipher(): Boolean {
try {
cipher = Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7)
} catch (e: NoSuchAlgorithmException) {
throw RuntimeException("Failed to get Cipher", e)
} catch (e: NoSuchPaddingException) {
throw RuntimeException("Failed to get Cipher", e)
}
try {
keyStore.load(null)
val key = keyStore.getKey(KEY_NAME, 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)
}
}
Sampai juga kita dilangkah terakhir. Oke setelah kita membuat 3 method diatas saatnya kita mengimplementasikannya. Kita tambahkan beberapa kode di dalam method onCreate() seperti dibawah ini.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (checkLockScreen()) {
generateKey()
if (initCipher()) {
cipher.let {
cryptoObject = FingerprintManager.CryptoObject(it)
}
val helper = FingerprintHelper(this)
if (fingerprintManager != null && cryptoObject != null) {
helper.startAuth(fingerprintManager, cryptoObject)
}
}
}
}
Kode lengkap untuk MainActivity.class bisa dilihat kode dibawah ini.
import android.Manifest
import android.app.KeyguardManager
import android.content.Context
import android.content.pm.PackageManager
import android.hardware.fingerprint.FingerprintManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyPermanentlyInvalidatedException
import android.security.keystore.KeyProperties
import android.widget.Toast
import androidx.core.app.ActivityCompat
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
class MainActivity : AppCompatActivity() {
private lateinit var fingerprintManager: FingerprintManager
private lateinit var keyguardManager: KeyguardManager
private lateinit var keyStore: KeyStore
private lateinit var keyGenerator: KeyGenerator
private val KEY_NAME = "key_saya"
private lateinit var cipher: Cipher
private lateinit var cryptoObject: FingerprintManager.CryptoObject
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (checkLockScreen()) {
generateKey()
if (initCipher()) {
cipher.let {
cryptoObject = FingerprintManager.CryptoObject(it)
}
val helper = FingerprintHelper(this)
if (fingerprintManager != null && cryptoObject != null) {
helper.startAuth(fingerprintManager, cryptoObject)
}
}
}
}
private fun checkLockScreen(): Boolean {
keyguardManager = getSystemService(Context.KEYGUARD_SERVICE)
as KeyguardManager
fingerprintManager = getSystemService(Context.FINGERPRINT_SERVICE)
as FingerprintManager
if (keyguardManager.isKeyguardSecure == false) {
Toast.makeText(this,
"Kunci layar tiak di aktifkan",
Toast.LENGTH_LONG).show()
return false
}
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.USE_FINGERPRINT) !=
PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,
"Ijin untuk sidik jari tidak diaktifkan",
Toast.LENGTH_LONG).show()
return false
}
if (fingerprintManager.hasEnrolledFingerprints() == false) {
Toast.makeText(this,
"Tidak ada sidik jari terdaftar, silahkan daftar sidik jari anda",
Toast.LENGTH_LONG).show()
return false
}
return true
}
private fun generateKey() {
try {
keyStore = KeyStore.getInstance("AndroidKeyStore")
} catch (e: Exception) {
e.printStackTrace()
}
try {
keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES,
"AndroidKeyStore")
} catch (e: NoSuchAlgorithmException) {
throw RuntimeException(
"Gagal untuk mendapatkan KeyGenerator", e)
} catch (e: NoSuchProviderException) {
throw RuntimeException("Gagal untuk mendapatkan KeyGenerator", e)
}
try {
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: NoSuchAlgorithmException) {
throw RuntimeException(e)
} catch (e: InvalidAlgorithmParameterException) {
throw RuntimeException(e)
} catch (e: CertificateException) {
throw RuntimeException(e)
} catch (e: IOException) {
throw RuntimeException(e)
}
}
private fun initCipher(): Boolean {
try {
cipher = Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7)
} catch (e: NoSuchAlgorithmException) {
throw RuntimeException("Failed to get Cipher", e)
} catch (e: NoSuchPaddingException) {
throw RuntimeException("Failed to get Cipher", e)
}
try {
keyStore.load(null)
val key = keyStore.getKey(KEY_NAME, 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)
}
}
}
Hasilnya akan seperti dibawah ini.
Selamat mencoba, semoga sefruit tutorial ini berguna untuk sahabat CAN Creative yang berminat menekuni bidang IT khususnya menjadi developer. Anda juga dapat mengetahui promo menarik seputar penawaran website, aplikasi, digital marketing ataupun SEO melalui website kami can.co.id Jasa Pembuatan Aplikasi Mobile. Kami juga aktif di media sosial instagram @cancreative, Line @cancreative. Source Code bisa dilihat di Github : https://github.com/ramcona/myfingerprint
Referensi : https://blog.mindorks.com/authentication-using-fingerprint-in-android-tutorial
Referensi : https://developer.android.com/about/versions/marshmallow/android-6.0?hl=id
Referensi : https://www.google.com/url?client=internal-element-cse&cx=000521750095050289010:zpcpi1ea4s8&q=https://developer.android.com/training/sign-in/biometric-auth%3Fhl%3Did&sa=U&ved=2ahUKEwieu6D-6LvxAhVOyzgGHdO-A2MQFjACegQIBxAC&usg=AOvVaw38uHhpWYbxqFGDZl49lVlz