Skip to content

Instantly share code, notes, and snippets.

@jochasinga
Created October 3, 2019 17:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jochasinga/d1a1d5a3dfd4ef9bf7eb3ed5c7e04dca to your computer and use it in GitHub Desktop.
Save jochasinga/d1a1d5a3dfd4ef9bf7eb3ed5c7e04dca to your computer and use it in GitHub Desktop.
Example of HeadSpin's HSFingerprintManager usage
/*-
* #%L
* Demo Fingerprint Authentication Activity
* %%
* Copyright (C) 2019 Headspin Inc.
* %%
* #L%
*/
package com.nextunicorn.app;
import android.annotation.TargetApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.content.Context;
import android.app.KeyguardManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.*;
import android.support.v4.app.ActivityCompat;
import android.widget.Toast;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.security.keystore.KeyProperties;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import javax.crypto.KeyGenerator;
import android.security.keystore.KeyGenParameterSpec;
import java.security.cert.CertificateException;
import java.security.InvalidAlgorithmParameterException;
import java.io.IOException;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.support.annotation.RequiresApi;
import android.util.Log;
import java.security.InvalidKeyException;
import java.security.KeyStoreException;
import java.security.UnrecoverableKeyException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
// Import from HeadSpin biometrics library
import io.headspin.instruments.fingerprint.HSFingerprintManager;
import io.headspin.instruments.fingerprint.HSFingerprintAuthCallback;
@TargetApi(28)
@RequiresApi(23)
class DemoFingerprintActivity extends AppCompatActivity {
private static String TAG = "DemoFingerprintActivity";
private static String KEY_NAME = "hot_key";
private HSFingerprintManager hsFingerprintManager;
private KeyguardManager keyguardManager;
private KeyStore keyStore;
private KeyGenerator keyGenerator;
private Cipher cipher;
private CryptoObject cryptoObject;
private CancellationSignal cancellationSignal;
/**
* Inherit [HSFingerprintAuthCallback] to get default toast messages or
* or [android.hardware.fingerprint.FingerprintManager.AuthenticationCallback]
* to implement your own callbacks.
*/
private HSFingerprintCallback authCallback = new HSFingerprintAuthCallback() {
@Override
void onAuthenticationSucceeded(AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
}, 2000);
}
};
@Override
void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "creating DemoFingerprintActivity")
super.onCreate(savedInstanceState);
hsfingerprintManager = new HSFingerprintManager(this);
setContentView(R.layout.activity_fingerprint);
if (managersReady()) {
generateKey();
if (initCipher()) {
cryptoObject = new CryptoObject(cipher);
cancellationSignal = new CancellationSignal();
if (hsFingerprintManager.ready()) {
/*
* authenticate() sends authCallback to the underlying HSfingerprintService
* so it can be called by Headspin biometrics API.
*/
hsFingerprintManager.authenticate(cryptoObject, cancellationSignal,
0, authCallback, null);
}
}
}
}
@Override
void onStop() {
super.onStop();
// IMPORTANT: call close() to stop the HSFingerprintService.
hsFingerprintManager.close();
}
/*
* This is a sample and thus using CBC Block mode should be good enough.
* However, please take care to implement a more secure key for your app.
*/
private boolean initCipher() {
try {
cipher = Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7);
} catch (NoSuchAlgorithmException e) {
throw RuntimeException("Failed to get Cipher", e);
} catch (NoSuchPaddingException e) {
throw RuntimeException("Failed to get Cipher", e);
}
try {
if (keyStore != null) {
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME, null);
cipher.init(Cipher.ENCRYPT_MODE, key);
return true;
}
} catch (KeyPermanentlyInvalidatedException e) {
return false;
} catch (KeyStoreException e) {
throw RuntimeException("Failed to init Cipher", e);
} catch (CertificateException e) {
throw RuntimeException("Failed to init Cipher", e);
} catch (UnrecoverableKeyException e) {
throw RuntimeException("Failed to init Cipher", e);
} catch (IOException e) {
throw RuntimeException("Failed to init Cipher", e);
} catch (NoSuchAlgorithmException e) {
throw RuntimeException("Failed to init Cipher", e)
} catch (InvalidKeyException e) {
throw RuntimeException("Failed to init Cipher", e)
}
}
private void generateKey() {
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
} catch (Exception e) {
e.printStackTrace();
}
try {
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES,
"AndroidKeyStore");
} catch (NoSuchAlgorithmException e) {
throw RuntimeException("Failed to get KeyGenerator instance", e);
} catch (NoSuchProviderException e) {
throw RuntimeException("Failed to get KeyGenerator instance", e);
}
try {
if (keyStore != null) {
keyStore.load(null);
keyGenerator.init(KeyGenParameterSpec.Builder(
KEY_NAME,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT
).setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();
}
} catch (NoSuchAlgorithmException e ) {
throw RuntimeException(e);
} catch (InvalidAlgorithmParameterException e) {
throw RuntimeException(e);
} catch (CertificateException e) {
throw RuntimeException(e);
} catch (IOException e) {
throw RuntimeException(e);
}
}
private Boolean managersReady() {
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
/*
* HSFingerprintManager fashions a ready() method that takes care of
* inquiring the wrapped FingerprintManager's readiness.
*/
if ((keyguardManager == null) || (!hsfingerprintManager.ready())) {
return false;
}
if (keyguardManager.isKeyguardSecure == false) {
Toast.makeText(this,
"Lock screen security is not enabled in Settings",
Toast.LENGTH_LONG).show();
return false;
}
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.USE_FINGERPRINT) !=
PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,
"Fingerprint authentication permission not enabled",
Toast.LENGTH_LONG).show();
return false;
}
if (hsfingerprintManager?.hasEnrolledFingerprints() == false) {
Toast.makeText(this,
"Register at least one fingerprint in Settings",
Toast.LENGTH_LONG).show();
return false;
}
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment