Created
July 7, 2016 08:51
-
-
Save wyyqyl/b2e8ccf9f796f8d0e107e16eabf46e18 to your computer and use it in GitHub Desktop.
use fingerprint to encrypt and decrypt message
This file contains hidden or 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
package com.stephen.demo; | |
import android.Manifest; | |
import android.annotation.TargetApi; | |
import android.app.KeyguardManager; | |
import android.content.Context; | |
import android.content.pm.PackageManager; | |
import android.hardware.fingerprint.FingerprintManager; | |
import android.os.Build; | |
import android.os.CancellationSignal; | |
import android.security.keystore.KeyGenParameterSpec; | |
import android.security.keystore.KeyProperties; | |
import android.util.Base64; | |
import android.util.Log; | |
import android.widget.Toast; | |
import java.security.KeyStore; | |
import javax.crypto.Cipher; | |
import javax.crypto.KeyGenerator; | |
import javax.crypto.SecretKey; | |
import javax.crypto.spec.IvParameterSpec; | |
/** | |
* Created by Stephen on 7/7/16. | |
*/ | |
@TargetApi(Build.VERSION_CODES.M) | |
public class FingerprintHelper extends FingerprintManager.AuthenticationCallback { | |
private static final String TAG = "TAG"; | |
private static final String KEY_NAME = "example_key"; | |
private boolean op; | |
private String message; | |
private String IV; | |
private Context mContext; | |
private FingerprintManager mFingerprintManager; | |
private KeyStore mKeyStore; | |
private Cipher mCipher; | |
private CancellationSignal mCancellationSignal; | |
private FingerprintManager.AuthenticationCallback mCallback = new FingerprintManager.AuthenticationCallback() { | |
@Override | |
public void onAuthenticationError(int errMsgId, CharSequence errString) { | |
Toast.makeText(mContext, "Authentication error: " + errString, Toast.LENGTH_SHORT).show(); | |
} | |
@Override | |
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { | |
Toast.makeText(mContext, "Authentication help: " + helpString, Toast.LENGTH_SHORT).show(); | |
} | |
@Override | |
public void onAuthenticationFailed() { | |
Toast.makeText(mContext, "Authentication failed.", Toast.LENGTH_SHORT).show(); | |
} | |
@Override | |
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { | |
Toast.makeText(mContext, "Authentication succeeded.", Toast.LENGTH_SHORT).show(); | |
try { | |
if (op) { | |
byte[] encrypted = mCipher.doFinal("Hello World".getBytes()); | |
message = Base64.encodeToString(encrypted, Base64.URL_SAFE); | |
} else { | |
byte[] data = mCipher.doFinal(Base64.decode(message, Base64.URL_SAFE)); | |
Log.d(TAG, "data: " + new String(data, "UTF-8")); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
}; | |
public boolean init(Context context) { | |
mContext = context; | |
KeyguardManager keyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); | |
if (!keyguardManager.isKeyguardSecure()) { | |
Toast.makeText(mContext, "Lock screen security not enabled in Settings", Toast.LENGTH_SHORT).show(); | |
return false; | |
} | |
if (mContext.checkSelfPermission(Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) { | |
Toast.makeText(mContext, "Fingerprint authentication permission not enabled", Toast.LENGTH_SHORT).show(); | |
return false; | |
} | |
mFingerprintManager = (FingerprintManager) mContext.getSystemService(Context.FINGERPRINT_SERVICE); | |
if (!mFingerprintManager.isHardwareDetected()) { | |
Toast.makeText(mContext, "Fingerprint sensor not detected", Toast.LENGTH_SHORT).show(); | |
return false; | |
} | |
if (!mFingerprintManager.hasEnrolledFingerprints()) { | |
// This happens when no fingerprints are registered. | |
Toast.makeText(mContext, "Register at least one fingerprint in Settings", Toast.LENGTH_SHORT).show(); | |
return false; | |
} | |
try { | |
mKeyStore = KeyStore.getInstance("AndroidKeyStore"); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
return false; | |
} | |
try { | |
mCipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" | |
+ KeyProperties.BLOCK_MODE_CBC + "/" | |
+ KeyProperties.ENCRYPTION_PADDING_PKCS7); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
return false; | |
} | |
generateKey(); | |
return true; | |
} | |
private void generateKey() { | |
KeyGenerator keyGenerator; | |
try { | |
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
return; | |
} | |
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(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
private boolean initCipher() { | |
try { | |
mKeyStore.load(null); | |
SecretKey key = (SecretKey) mKeyStore.getKey(KEY_NAME, null); | |
if (op) { | |
mCipher.init(Cipher.ENCRYPT_MODE, key); | |
IV = Base64.encodeToString(mCipher.getIV(), Base64.URL_SAFE); | |
} else { | |
mCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(Base64.decode(IV, Base64.URL_SAFE))); | |
} | |
return true; | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return false; | |
} | |
public void startAuth(boolean op) { | |
this.op = op; | |
if (initCipher()) { | |
mCancellationSignal = new CancellationSignal(); | |
if (mContext.checkSelfPermission(Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) { | |
Toast.makeText(mContext, "Fingerprint authentication permission not enabled", Toast.LENGTH_SHORT).show(); | |
return; | |
} | |
FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(mCipher); | |
mFingerprintManager.authenticate(cryptoObject, mCancellationSignal, 0, mCallback, null); | |
} | |
} | |
public void stopAuth() { | |
if (mCancellationSignal != null) { | |
mCancellationSignal.cancel(); | |
mCancellationSignal = null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment