Created
September 12, 2016 10:47
-
-
Save kevalpatel2106/0a2b3d385cb4b48c557587d81ee2435d to your computer and use it in GitHub Desktop.
Finger Print Authentication in Android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by Keval on 11-Sep-16. | |
* | |
* @author {@link 'https://github.com/kevalpatel2106'} | |
*/ | |
public interface FingerPrintAuthCallback { | |
void onAuthSuccess(); | |
void onAuthFailed(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.annotation.TargetApi; | |
import android.content.Context; | |
import android.hardware.fingerprint.FingerprintManager; | |
import android.os.Build; | |
import android.os.CancellationSignal; | |
import android.security.keystore.KeyGenParameterSpec; | |
import android.security.keystore.KeyPermanentlyInvalidatedException; | |
import android.security.keystore.KeyProperties; | |
import android.support.annotation.Nullable; | |
import android.support.v4.hardware.fingerprint.FingerprintManagerCompat; | |
import android.util.Log; | |
import com.severnx.ailauncher.interfaces.FingerPrintAuthCallback; | |
import java.io.IOException; | |
import java.security.InvalidAlgorithmParameterException; | |
import java.security.InvalidKeyException; | |
import java.security.KeyStore; | |
import java.security.KeyStoreException; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.NoSuchProviderException; | |
import java.security.UnrecoverableKeyException; | |
import java.security.cert.CertificateException; | |
import javax.crypto.Cipher; | |
import javax.crypto.KeyGenerator; | |
import javax.crypto.NoSuchPaddingException; | |
import javax.crypto.SecretKey; | |
/** | |
* Created by Keval on 11-Sep-16. | |
* | |
* @author {@link 'https://github.com/kevalpatel2106'} | |
*/ | |
@TargetApi(Build.VERSION_CODES.M) | |
public class FingerPrintAuthHelper extends FingerprintManager.AuthenticationCallback { | |
private static final String KEY_NAME = "example_key"; | |
private KeyStore mKeyStore; | |
private Cipher mCipher; | |
private Context mContext; | |
private FingerPrintAuthCallback mCallback; | |
public FingerPrintAuthHelper(Context context, FingerPrintAuthCallback callback) { | |
mCallback = callback; | |
mContext = context; | |
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) | |
throw new RuntimeException("Finger authentication requires API 23 or above."); | |
} | |
@SuppressWarnings({"RedundantIfStatement"}) | |
public static boolean isFingerPrintSupported(Context context) { | |
// Check if we're running on Android 6.0 (M) or higher | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | |
//Fingerprint API only available on from Android 6.0 (M) | |
FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.from(context); | |
if (!fingerprintManager.isHardwareDetected()) { | |
// Device doesn't support fingerprint authentication | |
return false; | |
} else if (!fingerprintManager.hasEnrolledFingerprints()) { | |
// User hasn't enrolled any fingerprints to authenticate with | |
return false; | |
} else { | |
// Everything is ready for fingerprint authentication | |
return true; | |
} | |
} | |
//Below API 23 fingerprint were not supported. | |
return false; | |
} | |
@TargetApi(23) | |
private boolean generateKey() { | |
mKeyStore = null; | |
KeyGenerator keyGenerator; | |
try { | |
mKeyStore = KeyStore.getInstance("AndroidKeyStore"); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
try { | |
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); | |
} catch (NoSuchAlgorithmException | | |
NoSuchProviderException e) { | |
throw new RuntimeException( | |
"Failed to get KeyGenerator instance", e); | |
} | |
if (mKeyStore == null || keyGenerator == null) return false; | |
try { | |
mKeyStore.load(null); | |
keyGenerator.init(new | |
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(); | |
return true; | |
} catch (NoSuchAlgorithmException | |
| InvalidAlgorithmParameterException | |
| CertificateException | |
| IOException e) { | |
return false; | |
} | |
} | |
@TargetApi(23) | |
private boolean cipherInit() { | |
boolean isKeyGenerated = generateKey(); | |
if (!isKeyGenerated) return false; | |
try { | |
mCipher = Cipher.getInstance( | |
KeyProperties.KEY_ALGORITHM_AES + "/" | |
+ KeyProperties.BLOCK_MODE_CBC + "/" | |
+ KeyProperties.ENCRYPTION_PADDING_PKCS7); | |
} catch (NoSuchAlgorithmException | | |
NoSuchPaddingException e) { | |
return false; | |
} | |
try { | |
mKeyStore.load(null); | |
SecretKey key = (SecretKey) mKeyStore.getKey(KEY_NAME, null); | |
mCipher.init(Cipher.ENCRYPT_MODE, key); | |
return true; | |
} catch (KeyPermanentlyInvalidatedException e) { | |
return false; | |
} catch (KeyStoreException | CertificateException | |
| UnrecoverableKeyException | IOException | |
| NoSuchAlgorithmException | InvalidKeyException e) { | |
return false; | |
} | |
} | |
@TargetApi(23) | |
@Nullable | |
private FingerprintManager.CryptoObject getCryptoObject() { | |
return cipherInit() ? new FingerprintManager.CryptoObject(mCipher) : null; | |
} | |
@TargetApi(Build.VERSION_CODES.M) | |
public void startAuth() { | |
FingerprintManager fingerprintManager = (FingerprintManager) mContext.getSystemService(Context.FINGERPRINT_SERVICE); | |
FingerprintManager.CryptoObject cryptoObject = getCryptoObject(); | |
if (cryptoObject == null) { | |
mCallback.onAuthFailed(); | |
} else { | |
//noinspection MissingPermission | |
fingerprintManager.authenticate(cryptoObject, new CancellationSignal(), 0, this, null); | |
} | |
} | |
@Override | |
public void onAuthenticationError(int errMsgId, | |
CharSequence errString) { | |
mCallback.onAuthFailed(); | |
} | |
@Override | |
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { | |
Log.d("FingerPrint", "auth help"); | |
} | |
@Override | |
public void onAuthenticationFailed() { | |
mCallback.onAuthFailed(); | |
} | |
@Override | |
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { | |
mCallback.onAuthSuccess(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by Keval on 11-Sep-16. | |
* | |
* @author {@link 'https://github.com/kevalpatel2106'} | |
*/ | |
public class MainActivity extends AppCompatActivity implements FingerPrintAuthCallback { | |
private boolean allowFingerPrintAuth; | |
//... | |
//... | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
//... | |
//... | |
//Check if the device supports finger print hardware | |
allowFingerPrintAuth = FingerPrintAuthHelper.isFingerPrintSupported(this); | |
if(allowFingerPrintAuth){ | |
//... | |
//Start authenticating | |
new FingerPrintAuthHelper(this, this).startAuth(); | |
} else{ | |
//Device dosen'r have support | |
//... | |
} | |
} | |
@Override | |
public void onAuthSuccess() { | |
//Authentication succesful. | |
} | |
@Override | |
public void onAuthFailed() { | |
//Authentication failed. | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment