Solve bug #25 - Read the fingerprint

This commit is contained in:
J-Jamet
2018-02-26 20:53:22 +01:00
parent bb4e067394
commit 6faee3cef9
3 changed files with 88 additions and 95 deletions

View File

@@ -320,4 +320,8 @@ public class FingerPrintHelper {
void handleDecryptedResult(String value); void handleDecryptedResult(String value);
} }
public enum Mode {
NOT_CONFIGURED_MODE, ENCRYPT_MODE, DECRYPT_MODE
}
} }

View File

@@ -45,20 +45,20 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.keepassdroid.database.Database; import com.keepassdroid.activities.GroupActivity;
import com.keepassdroid.activities.LockingActivity; import com.keepassdroid.activities.LockingActivity;
import com.keepassdroid.tasks.ProgressTask;
import com.keepassdroid.app.App; import com.keepassdroid.app.App;
import com.keepassdroid.compat.BackupManagerCompat; import com.keepassdroid.compat.BackupManagerCompat;
import com.keepassdroid.compat.ClipDataCompat; import com.keepassdroid.compat.ClipDataCompat;
import com.keepassdroid.compat.EditorCompat; import com.keepassdroid.compat.EditorCompat;
import com.keepassdroid.database.Database;
import com.keepassdroid.database.edit.LoadDB; import com.keepassdroid.database.edit.LoadDB;
import com.keepassdroid.database.edit.OnFinish; import com.keepassdroid.database.edit.OnFinish;
import com.keepassdroid.dialog.PasswordEncodingDialogHelper; import com.keepassdroid.dialog.PasswordEncodingDialogHelper;
import com.keepassdroid.fingerprint.FingerPrintAnimatedVector; import com.keepassdroid.fingerprint.FingerPrintAnimatedVector;
import com.keepassdroid.fingerprint.FingerPrintHelper; import com.keepassdroid.fingerprint.FingerPrintHelper;
import com.keepassdroid.activities.GroupActivity;
import com.keepassdroid.settings.PrefsUtil; import com.keepassdroid.settings.PrefsUtil;
import com.keepassdroid.tasks.ProgressTask;
import com.keepassdroid.utils.EmptyUtils; import com.keepassdroid.utils.EmptyUtils;
import com.keepassdroid.utils.MenuUtil; import com.keepassdroid.utils.MenuUtil;
import com.keepassdroid.utils.UriUtil; import com.keepassdroid.utils.UriUtil;
@@ -70,7 +70,9 @@ import com.kunzisoft.keepass.R;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import javax.crypto.Cipher; import static com.keepassdroid.fingerprint.FingerPrintHelper.Mode.DECRYPT_MODE;
import static com.keepassdroid.fingerprint.FingerPrintHelper.Mode.ENCRYPT_MODE;
import static com.keepassdroid.fingerprint.FingerPrintHelper.Mode.NOT_CONFIGURED_MODE;
public class PasswordActivity extends LockingActivity public class PasswordActivity extends LockingActivity
implements FingerPrintHelper.FingerPrintCallback, UriIntentInitTaskCallback { implements FingerPrintHelper.FingerPrintCallback, UriIntentInitTaskCallback {
@@ -80,7 +82,6 @@ public class PasswordActivity extends LockingActivity
private static final String KEY_LAUNCH_IMMEDIATELY = "launchImmediately"; private static final String KEY_LAUNCH_IMMEDIATELY = "launchImmediately";
private Uri mDbUri = null; private Uri mDbUri = null;
private Uri mKeyUri = null;
SharedPreferences prefs; SharedPreferences prefs;
SharedPreferences prefsNoBackup; SharedPreferences prefsNoBackup;
@@ -88,12 +89,11 @@ public class PasswordActivity extends LockingActivity
private boolean fingerprintMustBeConfigured = true; private boolean fingerprintMustBeConfigured = true;
private boolean mRememberKeyfile; private boolean mRememberKeyfile;
private int mode; private FingerPrintHelper.Mode mode;
private static final String PREF_KEY_VALUE_PREFIX = "valueFor_"; // key is a combination of db file name and this prefix private static final String PREF_KEY_VALUE_PREFIX = "valueFor_"; // key is a combination of db file name and this prefix
private static final String PREF_KEY_IV_PREFIX = "ivFor_"; // key is a combination of db file name and this prefix private static final String PREF_KEY_IV_PREFIX = "ivFor_"; // key is a combination of db file name and this prefix
private View fingerprintContainerView; private View fingerprintContainerView;
private View fingerprintImageView;
private FingerPrintAnimatedVector fingerPrintAnimatedVector; private FingerPrintAnimatedVector fingerPrintAnimatedVector;
private TextView fingerprintTextView; private TextView fingerprintTextView;
private TextView filenameView; private TextView filenameView;
@@ -104,6 +104,9 @@ public class PasswordActivity extends LockingActivity
private CompoundButton checkboxKeyfileView; private CompoundButton checkboxKeyfileView;
private CompoundButton checkboxDefaultDatabaseView; private CompoundButton checkboxDefaultDatabaseView;
private DefaultCheckChange defaultCheckChange;
private ValidateButtonViewClickListener validateButtonViewClickListener;
private KeyFileHelper keyFileHelper; private KeyFileHelper keyFileHelper;
public static void Launch( public static void Launch(
@@ -194,7 +197,6 @@ public class PasswordActivity extends LockingActivity
confirmButtonView = (Button) findViewById(R.id.pass_ok); confirmButtonView = (Button) findViewById(R.id.pass_ok);
fingerprintContainerView = findViewById(R.id.fingerprint_container); fingerprintContainerView = findViewById(R.id.fingerprint_container);
fingerprintImageView = findViewById(R.id.fingerprint_image);
fingerprintTextView = (TextView) findViewById(R.id.fingerprint_label); fingerprintTextView = (TextView) findViewById(R.id.fingerprint_label);
filenameView = (TextView) findViewById(R.id.filename); filenameView = (TextView) findViewById(R.id.filename);
passwordView = (EditText) findViewById(R.id.password); passwordView = (EditText) findViewById(R.id.password);
@@ -232,75 +234,16 @@ public class PasswordActivity extends LockingActivity
} }
}); });
new UriIntentInitTask(this, mRememberKeyfile) defaultCheckChange = new DefaultCheckChange();
.execute(getIntent()); validateButtonViewClickListener = new ValidateButtonViewClickListener();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
initForFingerprint();
fingerPrintAnimatedVector = new FingerPrintAnimatedVector(this, fingerPrintAnimatedVector = new FingerPrintAnimatedVector(this,
(ImageView) fingerprintImageView); (ImageView) findViewById(R.id.fingerprint_image));
} }
} }
@Override
public void onPostInitTask(Uri dbUri, Uri keyFileUri, Integer errorStringId) {
mDbUri = dbUri;
mKeyUri = keyFileUri;
Intent intent = getIntent();
String password = intent.getStringExtra(KEY_PASSWORD);
boolean launch_immediately = intent.getBooleanExtra(KEY_LAUNCH_IMMEDIATELY, false);
if (errorStringId != null) {
Toast.makeText(PasswordActivity.this, errorStringId, Toast.LENGTH_LONG).show();
finish();
return;
}
populateView();
confirmButtonView.setOnClickListener(new OkClickHandler());
if (password != null) {
passwordView.setText(password);
}
checkboxDefaultDatabaseView.setOnCheckedChangeListener(new DefaultCheckChange());
retrieveSettings();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkFingerprintAvailability();
}
if (launch_immediately) {
verifyCheckboxesAndLoadDatabase(password, mKeyUri);
}
}
private void retrieveSettings() {
String defaultFilename = prefs.getString(KEY_DEFAULT_FILENAME, "");
if (mDbUri!=null
&& !EmptyUtils.isNullOrEmpty(mDbUri.getPath())
&& UriUtil.equalsDefaultfile(mDbUri, defaultFilename)) {
checkboxDefaultDatabaseView.setChecked(true);
}
}
private void populateView() {
String db = (mDbUri == null) ? "" : mDbUri.toString();
if (!db.isEmpty()) {
if (PrefsUtil.isFullFilePathEnable(this))
filenameView.setText(db);
else
filenameView.setText(new File(mDbUri.getPath()).getName()); // TODO Encapsulate
}
String key = (mKeyUri == null) ? "" : mKeyUri.toString();
if (!key.isEmpty() && mRememberKeyfile) { // Bug KeepassDX #18
keyFileView.setText(key);
}
}
@Override @Override
protected void onResume() { protected void onResume() {
@@ -316,14 +259,67 @@ public class PasswordActivity extends LockingActivity
// For check shutdown // For check shutdown
super.onResume(); super.onResume();
new UriIntentInitTask(this, mRememberKeyfile)
.execute(getIntent());
}
@Override
public void onPostInitTask(Uri dbUri, Uri keyFileUri, Integer errorStringId) {
mDbUri = dbUri;
if (errorStringId != null) {
Toast.makeText(PasswordActivity.this, errorStringId, Toast.LENGTH_LONG).show();
finish();
return;
}
// Define title
String dbUriString = (mDbUri == null) ? "" : mDbUri.toString();
if (!dbUriString.isEmpty()) {
if (PrefsUtil.isFullFilePathEnable(this))
filenameView.setText(dbUriString);
else
filenameView.setText(new File(mDbUri.getPath()).getName()); // TODO Encapsulate
}
// Define Key File text
String keyUriString = (keyFileUri == null) ? "" : keyFileUri.toString();
if (!keyUriString.isEmpty() && mRememberKeyfile) { // Bug KeepassDX #18
keyFileView.setText(keyUriString);
}
// Define listeners for default database checkbox and validate button
checkboxDefaultDatabaseView.setOnCheckedChangeListener(defaultCheckChange);
confirmButtonView.setOnClickListener(validateButtonViewClickListener);
// Retrieve settings for default database
String defaultFilename = prefs.getString(KEY_DEFAULT_FILENAME, "");
if (mDbUri!=null
&& !EmptyUtils.isNullOrEmpty(mDbUri.getPath())
&& UriUtil.equalsDefaultfile(mDbUri, defaultFilename)) {
checkboxDefaultDatabaseView.setChecked(true);
}
// checks if fingerprint is available, will also start listening for fingerprints when available // checks if fingerprint is available, will also start listening for fingerprints when available
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
initForFingerprint();
checkFingerprintAvailability(); checkFingerprintAvailability();
if (fingerPrintAnimatedVector != null) { if (fingerPrintAnimatedVector != null) {
fingerPrintAnimatedVector.startScan(); fingerPrintAnimatedVector.startScan();
} }
} }
// If Activity is launch with a password and want to open directly
Intent intent = getIntent();
String password = intent.getStringExtra(KEY_PASSWORD);
boolean launch_immediately = intent.getBooleanExtra(KEY_LAUNCH_IMMEDIATELY, false);
if (password != null) {
passwordView.setText(password);
}
if (launch_immediately) {
verifyCheckboxesAndLoadDatabase(password, keyFileUri);
}
} }
private void setEmptyViews() { private void setEmptyViews() {
@@ -339,8 +335,6 @@ public class PasswordActivity extends LockingActivity
// fingerprint related code here // fingerprint related code here
@RequiresApi(api = Build.VERSION_CODES.M) @RequiresApi(api = Build.VERSION_CODES.M)
private void initForFingerprint() { private void initForFingerprint() {
mode = -1;
fingerPrintHelper = new FingerPrintHelper(this, this); fingerPrintHelper = new FingerPrintHelper(this, this);
// when text entered we can enable the logon/purchase button and if required update encryption/decryption mode // when text entered we can enable the logon/purchase button and if required update encryption/decryption mode
@@ -365,7 +359,10 @@ public class PasswordActivity extends LockingActivity
final boolean validInput = s.length() > 0; final boolean validInput = s.length() > 0;
// encrypt or decrypt mode based on how much input or not // encrypt or decrypt mode based on how much input or not
setFingerPrintTextView(validInput ? R.string.store_with_fingerprint : R.string.scanning_fingerprint); setFingerPrintTextView(validInput ? R.string.store_with_fingerprint : R.string.scanning_fingerprint);
mode = validInput ? toggleMode(Cipher.ENCRYPT_MODE) : toggleMode(Cipher.DECRYPT_MODE); if (validInput)
toggleMode(ENCRYPT_MODE);
else
toggleMode(DECRYPT_MODE);
} }
} }
}); });
@@ -398,13 +395,13 @@ public class PasswordActivity extends LockingActivity
@Override @Override
public void onAuthenticationSucceeded(final FingerprintManagerCompat.AuthenticationResult result) { public void onAuthenticationSucceeded(final FingerprintManagerCompat.AuthenticationResult result) {
if (mode == Cipher.ENCRYPT_MODE) { if (mode.equals(ENCRYPT_MODE)) {
// newly store the entered password in encrypted way // newly store the entered password in encrypted way
final String password = passwordView.getText().toString(); final String password = passwordView.getText().toString();
fingerPrintHelper.encryptData(password); fingerPrintHelper.encryptData(password);
} else if (mode == Cipher.DECRYPT_MODE) { } else if (mode.equals(DECRYPT_MODE)) {
// retrieve the encrypted value from preferences // retrieve the encrypted value from preferences
final String encryptedValue = prefsNoBackup.getString(getPreferenceKeyValue(), null); final String encryptedValue = prefsNoBackup.getString(getPreferenceKeyValue(), null);
@@ -432,21 +429,20 @@ public class PasswordActivity extends LockingActivity
} }
@RequiresApi(api = Build.VERSION_CODES.M) @RequiresApi(api = Build.VERSION_CODES.M)
private synchronized int toggleMode(final int newMode) { private synchronized void toggleMode(final FingerPrintHelper.Mode newMode) {
if(newMode != mode) { if(newMode != mode) {
mode = newMode; mode = newMode;
switch (mode) { switch (mode) {
case Cipher.ENCRYPT_MODE: case ENCRYPT_MODE:
fingerPrintHelper.initEncryptData(); fingerPrintHelper.initEncryptData();
break; break;
case Cipher.DECRYPT_MODE: case DECRYPT_MODE:
final String ivSpecValue = prefsNoBackup.getString(getPreferenceKeyIvSpec(), null); final String ivSpecValue = prefsNoBackup.getString(getPreferenceKeyIvSpec(), null);
if (ivSpecValue != null) if (ivSpecValue != null)
fingerPrintHelper.initDecryptData(ivSpecValue); fingerPrintHelper.initDecryptData(ivSpecValue);
break; break;
} }
} }
return newMode;
} }
@Override @Override
@@ -493,6 +489,7 @@ public class PasswordActivity extends LockingActivity
@RequiresApi(api = Build.VERSION_CODES.M) @RequiresApi(api = Build.VERSION_CODES.M)
private synchronized void checkFingerprintAvailability() { private synchronized void checkFingerprintAvailability() {
toggleMode(NOT_CONFIGURED_MODE);
// fingerprint not supported (by API level or hardware) so keep option hidden // fingerprint not supported (by API level or hardware) so keep option hidden
// or manually disable // or manually disable
@@ -526,13 +523,13 @@ public class PasswordActivity extends LockingActivity
if (!prefsNoBackup.contains(getPreferenceKeyValue())) { if (!prefsNoBackup.contains(getPreferenceKeyValue())) {
setFingerPrintTextView(R.string.no_password_stored); setFingerPrintTextView(R.string.no_password_stored);
// listen for encryption // listen for encryption
toggleMode(Cipher.ENCRYPT_MODE); toggleMode(ENCRYPT_MODE);
} }
// all is set here so we can confirm to user and start listening for fingerprints // all is set here so we can confirm to user and start listening for fingerprints
else { else {
setFingerPrintTextView(R.string.scanning_fingerprint); setFingerPrintTextView(R.string.scanning_fingerprint);
// listen for decryption // listen for decryption
toggleMode(Cipher.DECRYPT_MODE); toggleMode(DECRYPT_MODE);
} }
} }
} }
@@ -547,7 +544,7 @@ public class PasswordActivity extends LockingActivity
.putString(getPreferenceKeyIvSpec(), ivSpec) .putString(getPreferenceKeyIvSpec(), ivSpec)
.apply(); .apply();
// and remove visual input to reset UI // and remove visual input to reset UI
confirmButtonView.performClick(); confirmButtonView.performClick(); // TODO remove click
setFingerPrintTextView(R.string.encrypted_value_stored); setFingerPrintTextView(R.string.encrypted_value_stored);
} }
@@ -597,18 +594,14 @@ public class PasswordActivity extends LockingActivity
} }
private class DefaultCheckChange implements CompoundButton.OnCheckedChangeListener { private class DefaultCheckChange implements CompoundButton.OnCheckedChangeListener {
@Override @Override
public void onCheckedChanged( public void onCheckedChanged(
CompoundButton buttonView, CompoundButton buttonView,
boolean isChecked) { boolean isChecked) {
String newDefaultFileName; String newDefaultFileName = "";
if (isChecked) { if (isChecked) {
newDefaultFileName = mDbUri.toString(); newDefaultFileName = mDbUri.toString();
} else {
newDefaultFileName = "";
} }
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
@@ -617,13 +610,10 @@ public class PasswordActivity extends LockingActivity
BackupManagerCompat backupManager = new BackupManagerCompat(PasswordActivity.this); BackupManagerCompat backupManager = new BackupManagerCompat(PasswordActivity.this);
backupManager.dataChanged(); backupManager.dataChanged();
} }
} }
private class OkClickHandler implements View.OnClickListener { private class ValidateButtonViewClickListener implements View.OnClickListener {
public void onClick(View view) { public void onClick(View view) {
String pass = passwordView.getText().toString(); String pass = passwordView.getText().toString();
String key = keyFileView.getText().toString(); String key = keyFileView.getText().toString();

View File

@@ -25,6 +25,5 @@
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_toStartOf="@+id/fingerprint_image" android:layout_toStartOf="@+id/fingerprint_image"
style="@style/KeepassDXStyle.TextAppearance.DefaultTextOnPrimary" style="@style/KeepassDXStyle.TextAppearance.DefaultTextOnPrimary"
android:gravity="center_vertical|end" android:gravity="center_vertical|end" />
android:text="@string/entry_and_or" />
</RelativeLayout> </RelativeLayout>