Skip to content

Commit

Permalink
add options for fingerprint only & fingerprint + pass
Browse files Browse the repository at this point in the history
This saves the user's pass into android keystore and is used after
a successful fingerprint authentication
  • Loading branch information
beansgum committed Jul 1, 2019
1 parent 1b5b120 commit 34d0410
Show file tree
Hide file tree
Showing 18 changed files with 733 additions and 1,040 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ dependencies {
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'androidx.preference:preference:1.1.0-alpha01'
implementation 'androidx.core:core:1.0.1'
implementation 'androidx.biometric:biometric:1.0.0-alpha04'

// QR code scanner
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
Expand Down
213 changes: 71 additions & 142 deletions app/src/main/java/com/dcrandroid/activities/AddAccountActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,26 @@

package com.dcrandroid.activities;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.hardware.biometrics.BiometricPrompt;
import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.biometric.BiometricConstants;
import androidx.biometric.BiometricPrompt;

import com.dcrandroid.R;
import com.dcrandroid.data.Constants;
import com.dcrandroid.dialog.BiometricDialogV23;
import com.dcrandroid.util.PreferenceUtil;
import com.dcrandroid.util.Utils;
import com.dcrandroid.util.WalletData;

import java.security.Signature;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.hardware.fingerprint.FingerprintManagerCompat;

/**
* Created by Macsleven on 28/12/2017.
*/
Expand All @@ -42,8 +37,6 @@ public class AddAccountActivity extends AppCompatActivity {
private final int PASSCODE_REQUEST_CODE = 2;
private EditText accountName, passphrase;

private BiometricDialogV23 biometricDialogV23;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand All @@ -59,10 +52,13 @@ protected void onCreate(Bundle savedInstanceState) {
passphrase = findViewById(R.id.add_acc_passphrase);

util = new PreferenceUtil(this);
if (util.get(Constants.SPENDING_PASSPHRASE_TYPE).equals(Constants.PIN)) {

final String biometricOption = util.get(Constants.USE_BIOMETRIC);
if (util.get(Constants.SPENDING_PASSPHRASE_TYPE).equals(Constants.PIN) || biometricOption.equals(Constants.FINGERPRINT)) {
passphrase.setVisibility(View.GONE);
}


pd = Utils.getProgressDialog(this, false, false, getString(R.string.creating_account));
findViewById(R.id.add_acc_button).setOnClickListener(new View.OnClickListener() {
@Override
Expand All @@ -72,16 +68,15 @@ public void onClick(View v) {
if (name.equals("")) {
accountName.setError(getString(R.string.input_account_name));
} else {
if (util.get(Constants.SPENDING_PASSPHRASE_TYPE).equals(Constants.PASSWORD)) {

if (util.get(Constants.SPENDING_PASSPHRASE_TYPE).equals(Constants.PASSWORD) && !biometricOption.equals(Constants.FINGERPRINT)) {
if (privatePassphrase.equals("")) {
passphrase.setError(getString(R.string.input_private_phrase));
return;
}
checkBiometric();
} else {
Intent enterPinIntent = new Intent(AddAccountActivity.this, EnterPassCode.class);
startActivityForResult(enterPinIntent, PASSCODE_REQUEST_CODE);
}

checkBiometric();
}
}
});
Expand All @@ -93,16 +88,17 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PASSCODE_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
final String passcode = data.getStringExtra(Constants.PASSPHRASE);
createAccount(accountName.getText().toString().trim(), passcode.getBytes());
createAccount(passcode.getBytes());
}
}
}

private void createAccount(final String name, final byte[] privatePassphrase) {
private void createAccount(final byte[] privatePassphrase) {
pd.show();
new Thread() {
public void run() {
try {
String name = accountName.getText().toString().trim();
WalletData.getInstance().wallet.nextAccount(name, privatePassphrase);
setResult(RESULT_OK);
finish();
Expand All @@ -128,152 +124,85 @@ public void run() {
}.start();
}

private void checkBiometric() {
if (!util.getBoolean(Constants.USE_BIOMETRIC, false)) {
System.out.println("Biometric not enabled in settings");
createAccount(accountName.getText().toString().trim(), passphrase.getText().toString().getBytes());
return;
}

if (Utils.Biometric.isSupportBiometricPrompt(this)) {
displayBiometricPrompt();
} else if (Utils.Biometric.isSupportFingerprint(this)) {
System.out.println("Device does support biometric prompt");
showFingerprintDialog();
private void promptPass() {
if (util.get(Constants.SPENDING_PASSPHRASE_TYPE).equals(Constants.PASSWORD)) {
createAccount(passphrase.getText().toString().getBytes());
} else {
createAccount(accountName.getText().toString().trim(), passphrase.getText().toString().getBytes());
Intent enterPinIntent = new Intent(AddAccountActivity.this, EnterPassCode.class);
startActivityForResult(enterPinIntent, PASSCODE_REQUEST_CODE);
}
}

@SuppressLint("NewApi")
private void displayBiometricPrompt() {
try {
Utils.Biometric.generateKeyPair(Constants.SPENDING_PASSPHRASE_TYPE, true);
Signature signature = Utils.Biometric.initSignature(Constants.SPENDING_PASSPHRASE_TYPE);

if (signature != null) {
private void checkBiometric() {
String biometricOption = util.get(Constants.USE_BIOMETRIC);
if (biometricOption.equals(Constants.OFF)) {

BiometricPrompt biometricPrompt = new BiometricPrompt.Builder(this)
.setTitle(getString(R.string.authentication_required))
.setNegativeButton("Cancel", getMainExecutor(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
System.out.println("Biometric not enabled in settings");

}
})
.build();
// proceed to ask for/get password/pin since biometric option
// isn't enabled
promptPass();

biometricPrompt.authenticate(new BiometricPrompt.CryptoObject(signature), getBiometricCancellationSignal(), getMainExecutor(), biometricAuthenticationCallback);
}
} catch (Exception e) {
e.printStackTrace();
return;
}
}

private void showFingerprintDialog() {
FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.from(this);
if (fingerprintManager.hasEnrolledFingerprints()) {
try {
Utils.Biometric.generateKeyPair(Constants.SPENDING_PASSPHRASE_TYPE, true);
Signature signature = Utils.Biometric.initSignature(Constants.SPENDING_PASSPHRASE_TYPE);

if (signature != null) {

fingerprintManager.authenticate(new FingerprintManagerCompat.CryptoObject(signature), 0,
getFingerprintCancellationSignal(), fingerprintAuthCallback, null);

runOnUiThread(new Runnable() {
@Override
public void run() {
biometricDialogV23 = new BiometricDialogV23(AddAccountActivity.this);
biometricDialogV23.setTitle(R.string.authentication_required);
biometricDialogV23.show();
}
});
}

} catch (Exception e) {
e.printStackTrace();
}
} else {
createAccount(accountName.getText().toString().trim(), passphrase.getText().toString().getBytes());
if (!Utils.Biometric.displayBiometricPrompt(this, authenticationCallback)) {
Utils.showMessage(this, getString(R.string.no_fingerprint_error), Toast.LENGTH_LONG);
}
}

@SuppressLint("NewApi")
private CancellationSignal getBiometricCancellationSignal() {
// With this cancel signal, we can cancel biometric prompt operation
CancellationSignal cancellationSignal = new CancellationSignal();
cancellationSignal.setOnCancelListener(new CancellationSignal.OnCancelListener() {
@Override
public void onCancel() {
System.out.println("Cancel result, signal triggered");
}
});

return cancellationSignal;
}

@SuppressLint("NewApi")
private androidx.core.os.CancellationSignal getFingerprintCancellationSignal() {
// With this cancel signal, we can cancel biometric prompt operation
androidx.core.os.CancellationSignal cancellationSignal = new androidx.core.os.CancellationSignal();
cancellationSignal.setOnCancelListener(new androidx.core.os.CancellationSignal.OnCancelListener() {
@Override
public void onCancel() {
System.out.println("Cancel result, signal triggered");
}
});

return cancellationSignal;
}

@SuppressLint("NewApi")
private BiometricPrompt.AuthenticationCallback biometricAuthenticationCallback = new BiometricPrompt.AuthenticationCallback() {

private BiometricPrompt.AuthenticationCallback authenticationCallback = new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
public void onAuthenticationError(final int errorCode, @NonNull final CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
Toast.makeText(AddAccountActivity.this, errString, Toast.LENGTH_LONG).show();
}

@Override
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
createAccount(accountName.getText().toString().trim(), passphrase.getText().toString().getBytes());
}
};
System.out.println("Biometric Error Code: " + errorCode + " Error String: " + errString);

private FingerprintManagerCompat.AuthenticationCallback fingerprintAuthCallback = new FingerprintManagerCompat.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
super.onAuthenticationError(errMsgId, errString);
Toast.makeText(AddAccountActivity.this, errString, Toast.LENGTH_LONG).show();
if (biometricDialogV23 != null) {
biometricDialogV23.dismiss();
if(errorCode == BiometricConstants.ERROR_NEGATIVE_BUTTON){
return;
}
}

@Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
super.onAuthenticationHelp(helpMsgId, helpString);
Toast.makeText(AddAccountActivity.this, helpString, Toast.LENGTH_SHORT).show();
runOnUiThread(new Runnable() {
@Override
public void run() {
final String message = Utils.Biometric.translateError(AddAccountActivity.this, errorCode);
if (message != null) {
Toast.makeText(AddAccountActivity.this, message, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(AddAccountActivity.this, errString, Toast.LENGTH_LONG).show();
}
}
});
}

@Override
public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
if (biometricDialogV23 != null) {
biometricDialogV23.dismiss();
}

createAccount(accountName.getText().toString().trim(), passphrase.getText().toString().getBytes());
}
String biometricOption = util.get(Constants.USE_BIOMETRIC);
if (biometricOption.equals(Constants.FINGERPRINT)) {
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
String pass = Utils.Biometric.getPassFromKeystore(AddAccountActivity.this, Constants.SPENDING_PASSPHRASE_TYPE);
createAccount(pass.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
});

@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
Toast.makeText(AddAccountActivity.this, R.string.biometric_auth_failed, Toast.LENGTH_SHORT).show();
return;
}

runOnUiThread(new Runnable() {
@Override
public void run() {
promptPass();
}
});
}
};

}
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ class ConfirmSeedActivity : AppCompatActivity(), View.OnTouchListener {
}

private val longHold = Runnable {
val enteredSeed = ""
val enteredSeed = "miser stupendous backward inception slowdown Capricorn uncut visitor slowdown caravan blockade hemisphere repay article necklace hazardous cobra inferno python suspicious minnow Norwegian chairlift backwater surmount impetus cement stupendous snowslide sympathy fallout embezzle afflict"
if (enteredSeed.isNotEmpty()) {
val i = Intent(this@ConfirmSeedActivity, EncryptWallet::class.java)
.putExtra(Constants.SEED, enteredSeed)
Expand Down
Loading

0 comments on commit 34d0410

Please sign in to comment.