|
|
@@ -9,6 +9,7 @@ import android.support.v4.hardware.fingerprint.FingerprintManagerCompat;
|
|
|
import android.support.v4.os.CancellationSignal;
|
|
|
import android.util.Base64;
|
|
|
import android.util.Base64DataException;
|
|
|
+import android.widget.Toast;
|
|
|
|
|
|
import java.io.File;
|
|
|
import java.io.FileWriter;
|
|
|
@@ -59,6 +60,7 @@ class FingerprintPicker extends PasswordPicker {
|
|
|
private IvAndPayload fEncrypted;
|
|
|
private Queue<String> fPassword;
|
|
|
private Queue<String> fPasswordIterator;
|
|
|
+ private AlertPrompt fDisplayingPrompt;
|
|
|
|
|
|
private static final class IvAndPayload {
|
|
|
static final char SEPARATOR = '-';
|
|
|
@@ -181,6 +183,10 @@ class FingerprintPicker extends PasswordPicker {
|
|
|
private void DoWriteFile(FingerprintManagerCompat.CryptoObject cryptoObject, String content) {
|
|
|
try {
|
|
|
Cipher cipher = cryptoObject.getCipher();
|
|
|
+ if (cipher == null) {
|
|
|
+ log.severe("Cannot write content: cipher is null");
|
|
|
+ return;
|
|
|
+ }
|
|
|
byte[] encrypted = cipher.doFinal(content.getBytes());
|
|
|
Writer writer = new FileWriter(fFile);
|
|
|
writer.write((new IvAndPayload(cipher, encrypted)).toString());
|
|
|
@@ -194,10 +200,11 @@ class FingerprintPicker extends PasswordPicker {
|
|
|
private void DisplayPrompt(IvAndPayload ivForDecoding, OnResponseListener<FingerprintManagerCompat.CryptoObject> resp) {
|
|
|
final CancellationSignal signal = new CancellationSignal();
|
|
|
final FingerprintView fingerprintView = new FingerprintView(fContext);
|
|
|
- final AlertPrompt prompt = fAlertFactory.Generate(fContext)
|
|
|
+ fDisplayingPrompt = fAlertFactory.Generate(fContext)
|
|
|
.setView(fingerprintView)
|
|
|
.setTitle(R.string.pushfinger)
|
|
|
.setNegativeButton(R.string.cancel, (dialogInterface, view) -> {
|
|
|
+ fDisplayingPrompt = null;
|
|
|
signal.cancel();
|
|
|
resp.onError(fContext.getString(R.string.cancelled), null);
|
|
|
})
|
|
|
@@ -209,7 +216,9 @@ class FingerprintPicker extends PasswordPicker {
|
|
|
GetFingerprintManager().authenticate(cryptoObject, 0, signal, new FingerprintManagerCompat.AuthenticationCallback() {
|
|
|
@Override
|
|
|
public void onAuthenticationError(int errMsgId, CharSequence errString) {
|
|
|
- resp.onError(errString.toString(), null);
|
|
|
+ ClosePrompt();
|
|
|
+ if (errMsgId != 5) // cancelled
|
|
|
+ resp.onError(errString.toString(), null);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -220,24 +229,31 @@ class FingerprintPicker extends PasswordPicker {
|
|
|
|
|
|
@Override
|
|
|
public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
|
|
|
- prompt.close();
|
|
|
+ ClosePrompt();
|
|
|
resp.onResponse(cryptoObject);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void onAuthenticationFailed() {
|
|
|
- ((FingerprintView)(prompt.getView())).onAuthFailed();
|
|
|
+ ((FingerprintView)(fDisplayingPrompt.getView())).onAuthFailed();
|
|
|
}
|
|
|
}, null);
|
|
|
}
|
|
|
|
|
|
+ private void ClosePrompt() {
|
|
|
+ if (fDisplayingPrompt != null) {
|
|
|
+ fDisplayingPrompt.close();
|
|
|
+ fDisplayingPrompt = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private void ReadAllPasswords(final FileInterfaceFactory.OnPasswordEnteredListener onResp) {
|
|
|
try {
|
|
|
String raw = FileUtils.ReadAllFile(fFile);
|
|
|
fEncrypted = new IvAndPayload(raw);
|
|
|
} catch (IOException e) {
|
|
|
// Fallback password
|
|
|
- SuperGetPassword(onResp);
|
|
|
+ SuperGetPassword(true, onResp);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -245,7 +261,14 @@ class FingerprintPicker extends PasswordPicker {
|
|
|
@Override
|
|
|
public void onResponse(FingerprintManagerCompat.CryptoObject cryptoObject) {
|
|
|
try {
|
|
|
- byte[] decoded = cryptoObject.getCipher().doFinal(fEncrypted.fPayload);
|
|
|
+ Cipher cipher = cryptoObject.getCipher();
|
|
|
+ if (cipher == null) {
|
|
|
+ log.severe("Cannot read content: cipher is null");
|
|
|
+ Toast.makeText(fContext, R.string.fingerprint_init_error, Toast.LENGTH_LONG).show();
|
|
|
+ SuperGetPassword(false, onResp);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ byte[] decoded = cipher.doFinal(fEncrypted.fPayload);
|
|
|
String[] passwords = (new String(decoded, "UTF-8")).split("\n");
|
|
|
fPassword = new ArrayDeque<>();
|
|
|
fPasswordIterator = new ArrayDeque<>();
|
|
|
@@ -255,7 +278,7 @@ class FingerprintPicker extends PasswordPicker {
|
|
|
fPassword.add(i);
|
|
|
fPasswordIterator.addAll(fPassword);
|
|
|
if (fPasswordIterator.isEmpty())
|
|
|
- SuperGetPassword(onResp);
|
|
|
+ SuperGetPassword(true, onResp);
|
|
|
else
|
|
|
onResp.onResponse(fPasswordIterator.remove());
|
|
|
}
|
|
|
@@ -270,13 +293,14 @@ class FingerprintPicker extends PasswordPicker {
|
|
|
// Fallback password
|
|
|
fPassword = new ArrayDeque<>();
|
|
|
fPasswordIterator = new ArrayDeque<>();
|
|
|
- SuperGetPassword(onResp);
|
|
|
+ SuperGetPassword(false, onResp);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- private void SuperGetPassword(FileInterfaceFactory.OnPasswordEnteredListener onResp) {
|
|
|
- FingerprintPicker.super.GetPassword(new FileInterfaceFactory.OnPasswordEnteredListener() {
|
|
|
+ private void SuperGetPassword(boolean savePassword, FileInterfaceFactory.OnPasswordEnteredListener onResp) {
|
|
|
+ ClosePrompt();
|
|
|
+ FingerprintPicker.super.GetPassword(savePassword ? new FileInterfaceFactory.OnPasswordEnteredListener() {
|
|
|
@Override
|
|
|
public boolean onResponse(String result) {
|
|
|
// TODO checkbox save password ?
|
|
|
@@ -290,7 +314,7 @@ class FingerprintPicker extends PasswordPicker {
|
|
|
public void onError(String msg, Throwable e) {
|
|
|
onResp.onError(msg, e);
|
|
|
}
|
|
|
- });
|
|
|
+ } : onResp);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -298,7 +322,7 @@ class FingerprintPicker extends PasswordPicker {
|
|
|
if (fPassword == null)
|
|
|
ReadAllPasswords(onResp);
|
|
|
else if (fPasswordIterator.isEmpty())
|
|
|
- SuperGetPassword(onResp);
|
|
|
+ SuperGetPassword(true, onResp);
|
|
|
else
|
|
|
onResp.onResponse(fPasswordIterator.remove());
|
|
|
}
|