diff --git a/app/src/main/java/app/notesr/activity/security/AuthHandler.java b/app/src/main/java/app/notesr/activity/security/AuthHandler.java index 97da88fe..aed4db36 100644 --- a/app/src/main/java/app/notesr/activity/security/AuthHandler.java +++ b/app/src/main/java/app/notesr/activity/security/AuthHandler.java @@ -40,14 +40,14 @@ @RequiredArgsConstructor public final class AuthHandler { private static final int MAX_ATTEMPTS = 3; - private static final int ON_WRONG_PASSWORD_DELAY_MS = 1500; + private static final int DELAY_AFTER_AUTH_FAILED = 1500; private final AuthActivity activity; private final AppSecurityService appSecurityService; private final SecretsRotationService secretsRotationService; private final SecureStringBuilder passwordBuilder; - private int attempts = MAX_ATTEMPTS; + private int authAttempts = MAX_ATTEMPTS; private char[] createdPassword; public void authenticate() { @@ -181,9 +181,9 @@ private void onAuthenticationSuccessful() { } private void onAuthenticationFailed() { - attempts--; + authAttempts--; - if (attempts == 0) { + if (authAttempts == 0) { try { appSecurityService.blockApp(); } catch (AppSecurityException e) { @@ -193,16 +193,17 @@ private void onAuthenticationFailed() { showToastMessage(R.string.blocked); activity.startActivity(new Intent(activity.getApplicationContext(), KeyRecoveryActivity.class)); + activity.finish(); } else { try { - Thread.sleep(ON_WRONG_PASSWORD_DELAY_MS); + Thread.sleep(DELAY_AFTER_AUTH_FAILED); } catch (InterruptedException e) { throw new RuntimeException(e); } showToastMessage(String.format( activity.getString(R.string.wrong_code_you_have_n_attempts), - attempts)); + authAttempts)); } resetPassword(); diff --git a/app/src/main/java/app/notesr/activity/security/KeyRecoveryActivity.java b/app/src/main/java/app/notesr/activity/security/KeyRecoveryActivity.java index 85d349fc..3818ddd0 100644 --- a/app/src/main/java/app/notesr/activity/security/KeyRecoveryActivity.java +++ b/app/src/main/java/app/notesr/activity/security/KeyRecoveryActivity.java @@ -12,7 +12,6 @@ import static app.notesr.core.util.CharUtils.charsToBytes; import static app.notesr.core.util.KeyUtils.getKeyBytesFromKeyHex; -import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.text.Editable; @@ -30,17 +29,16 @@ import app.notesr.service.security.AppSecurityException; import app.notesr.service.security.AppSecurityService; -import java.io.IOException; import java.nio.charset.CharacterCodingException; import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Objects; public final class KeyRecoveryActivity extends ActivityBase { - private static final String TAG = KeyRecoveryActivity.class.toString(); + private static final String TAG = KeyRecoveryActivity.class.getSimpleName(); private AppSecurityService appSecurityService; + private EditText hexKeyField; @Override protected void onCreate(Bundle savedInstanceState) { @@ -53,13 +51,13 @@ protected void onCreate(Bundle savedInstanceState) { ActionBar actionBar = getSupportActionBar(); Objects.requireNonNull(actionBar).setTitle(getString(R.string.key_recovery)); - EditText hexKeyField = findViewById(R.id.importRecoveryKeyField); + hexKeyField = findViewById(R.id.importRecoveryKeyField); Button applyButton = findViewById(R.id.applyRecoveryKeyButton); disableBackButton(this); hexKeyField.setImeOptions(IME_FLAG_NO_PERSONALIZED_LEARNING); - applyButton.setOnClickListener(applyButtonOnClick(hexKeyField)); + applyButton.setOnClickListener(getApplyButtonOnClickListener()); } @Override @@ -67,7 +65,17 @@ protected boolean requiresSession() { return false; } - private View.OnClickListener applyButtonOnClick(EditText hexKeyField) { + @Override + public void finish() { + if (hexKeyField != null) { + hexKeyField.getText().replace(0, hexKeyField.getText().length(), ""); + hexKeyField.setText(""); + } + + super.finish(); + } + + private View.OnClickListener getApplyButtonOnClickListener() { return view -> { Editable hexKeyEditable = hexKeyField.getText(); int hexKeyLength = hexKeyEditable.length(); @@ -77,56 +85,49 @@ private View.OnClickListener applyButtonOnClick(EditText hexKeyField) { hexKeyEditable.getChars(0, hexKeyLength, hexKey, 0); try { - apply(hexKeyField, hexKey); + if (isMatch(hexKey)) { + proceedKeyMatch(hexKey); + } else { + proceedKeyMismatch(); + } } catch (IllegalArgumentException e) { Log.e(TAG, "Invalid key", e); showToastMessage(this, getString(R.string.invalid_key), Toast.LENGTH_SHORT); - } catch (CharacterCodingException e) { - throw new RuntimeException(e); - } catch (IOException | NoSuchAlgorithmException e) { + } catch (AppSecurityException | CharacterCodingException e) { Log.e(TAG, e.toString()); throw new RuntimeException(e); + } finally { + Arrays.fill(hexKey, '\0'); } } }; } - private void apply(EditText hexKeyField, char[] hexKey) - throws IOException, NoSuchAlgorithmException { - - char[] hexKeyCopy = Arrays.copyOf(hexKey, hexKey.length); - byte[] keyBytes = getKeyBytesFromKeyHex(hexKeyCopy); + private boolean isMatch(char[] hexKey) { + byte[] keyBytes = getKeyBytesFromKeyHex(Arrays.copyOf(hexKey, hexKey.length)); + boolean isMatch = appSecurityService.isKeyMatchingWithStored(keyBytes); - Context context = getApplicationContext(); - - try { - if (appSecurityService.isKeyMatchingWithStored(keyBytes)) { - byte[] hexKeyBytes = charsToBytes(hexKey, StandardCharsets.UTF_8); - SecretCache.put(AuthActivity.CACHE_KEY_HEX_KEY, hexKeyBytes); + Arrays.fill(keyBytes, (byte) 0); + return isMatch; + } - // The hex key has already been wiped by charsToBytes - wipeSecretData(keyBytes, hexKeyField); + private void proceedKeyMatch(char[] hexKey) throws CharacterCodingException { + byte[] hexKeyBytes = charsToBytes(Arrays.copyOf(hexKey, hexKey.length), + StandardCharsets.UTF_8); + SecretCache.put(AuthActivity.CACHE_KEY_HEX_KEY, hexKeyBytes); - var targetMode = AuthActivity.Mode.KEY_RECOVERY; - var authActivityIntent = new Intent(context, AuthActivity.class) - .putExtra(AuthActivity.EXTRA_MODE, targetMode.toString()); + var targetMode = AuthActivity.Mode.KEY_RECOVERY; + var authActivityIntent = new Intent(getApplicationContext(), AuthActivity.class) + .putExtra(AuthActivity.EXTRA_MODE, targetMode.toString()); - startActivity(authActivityIntent); - finish(); - } else { - showToastMessage(this, - getString(R.string.wrong_key), - Toast.LENGTH_SHORT); - } - } catch (AppSecurityException e) { - throw new RuntimeException(e); - } + startActivity(authActivityIntent); + finish(); } - private void wipeSecretData(byte[] keyBytes, EditText keyField) { - Arrays.fill(keyBytes, (byte) 0); - keyField.getText().replace(0, keyField.getText().length(), ""); - keyField.setText(""); + private void proceedKeyMismatch() { + showToastMessage(this, + getString(R.string.wrong_key), + Toast.LENGTH_SHORT); } }