Skip to content

Commit 3c124de

Browse files
Merge pull request #1336 from alexbakker/limit-strength-analysis
Stop analyzing password strength if it becomes longer than 64 chars
2 parents 0643713 + 559e68e commit 3c124de

File tree

4 files changed

+64
-42
lines changed

4 files changed

+64
-42
lines changed

app/src/main/java/com/beemdevelopment/aegis/helpers/PasswordStrengthHelper.java

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,60 @@
11
package com.beemdevelopment.aegis.helpers;
22

33
import android.content.Context;
4+
import android.content.res.ColorStateList;
5+
import android.graphics.Color;
6+
import android.widget.EditText;
7+
import android.widget.ProgressBar;
8+
import android.widget.TextView;
49

510
import com.beemdevelopment.aegis.R;
11+
import com.google.android.material.textfield.TextInputLayout;
12+
import com.google.common.base.Strings;
13+
import com.nulabinc.zxcvbn.Strength;
14+
import com.nulabinc.zxcvbn.Zxcvbn;
615

716
public class PasswordStrengthHelper {
17+
// Limit the password length to prevent zxcvbn4j from exploding
18+
private static final int MAX_PASSWORD_LENGTH = 64;
19+
820
// Material design color palette
9-
private static String[] COLORS = {"#FF5252", "#FF5252", "#FFC107", "#8BC34A", "#4CAF50"};
21+
private final static String[] COLORS = {"#FF5252", "#FF5252", "#FFC107", "#8BC34A", "#4CAF50"};
22+
23+
private final Zxcvbn _zxcvbn = new Zxcvbn();
24+
private final EditText _textPassword;
25+
private final ProgressBar _barPasswordStrength;
26+
private final TextView _textPasswordStrength;
27+
private final TextInputLayout _textPasswordWrapper;
28+
29+
public PasswordStrengthHelper(
30+
EditText textPassword,
31+
ProgressBar barPasswordStrength,
32+
TextView textPasswordStrength,
33+
TextInputLayout textPasswordWrapper
34+
) {
35+
_textPassword = textPassword;
36+
_barPasswordStrength = barPasswordStrength;
37+
_textPasswordStrength = textPasswordStrength;
38+
_textPasswordWrapper = textPasswordWrapper;
39+
}
40+
41+
public void measure(Context context) {
42+
if (_textPassword.getText().length() > MAX_PASSWORD_LENGTH) {
43+
_barPasswordStrength.setProgress(0);
44+
_textPasswordStrength.setText(R.string.password_strength_unknown);
45+
} else {
46+
Strength strength = _zxcvbn.measure(_textPassword.getText());
47+
_barPasswordStrength.setProgress(strength.getScore());
48+
_barPasswordStrength.setProgressTintList(ColorStateList.valueOf(Color.parseColor(getColor(strength.getScore()))));
49+
_textPasswordStrength.setText((_textPassword.getText().length() != 0) ? getString(strength.getScore(), context) : "");
50+
String warning = strength.getFeedback().getWarning();
51+
_textPasswordWrapper.setError(warning);
52+
_textPasswordWrapper.setErrorEnabled(!Strings.isNullOrEmpty(warning));
53+
strength.wipe();
54+
}
55+
}
1056

11-
public static String getString(int score, Context context) {
57+
private static String getString(int score, Context context) {
1258
if (score < 0 || score > 4) {
1359
throw new IllegalArgumentException("Not a valid zxcvbn score");
1460
}
@@ -17,7 +63,7 @@ public static String getString(int score, Context context) {
1763
return strings[score];
1864
}
1965

20-
public static String getColor(int score) {
66+
private static String getColor(int score) {
2167
if (score < 0 || score > 4) {
2268
throw new IllegalArgumentException("Not a valid zxcvbn score");
2369
}

app/src/main/java/com/beemdevelopment/aegis/ui/dialogs/Dialogs.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import android.content.ClipboardManager;
66
import android.content.Context;
77
import android.content.DialogInterface;
8-
import android.content.res.ColorStateList;
9-
import android.graphics.Color;
108
import android.text.InputType;
119
import android.text.SpannableStringBuilder;
1210
import android.text.TextWatcher;
@@ -43,8 +41,6 @@
4341
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
4442
import com.google.android.material.textfield.TextInputEditText;
4543
import com.google.android.material.textfield.TextInputLayout;
46-
import com.nulabinc.zxcvbn.Strength;
47-
import com.nulabinc.zxcvbn.Zxcvbn;
4844

4945
import java.util.ArrayList;
5046
import java.util.List;
@@ -120,14 +116,15 @@ public static void showDiscardDialog(Context context, DialogInterface.OnClickLis
120116
}
121117

122118
public static void showSetPasswordDialog(ComponentActivity activity, PasswordSlotListener listener) {
123-
Zxcvbn zxcvbn = new Zxcvbn();
124119
View view = activity.getLayoutInflater().inflate(R.layout.dialog_password, null);
125120
EditText textPassword = view.findViewById(R.id.text_password);
126121
EditText textPasswordConfirm = view.findViewById(R.id.text_password_confirm);
127122
ProgressBar barPasswordStrength = view.findViewById(R.id.progressBar);
128123
TextView textPasswordStrength = view.findViewById(R.id.text_password_strength);
129124
TextInputLayout textPasswordWrapper = view.findViewById(R.id.text_password_wrapper);
130125
CheckBox switchToggleVisibility = view.findViewById(R.id.check_toggle_visibility);
126+
PasswordStrengthHelper passStrength = new PasswordStrengthHelper(
127+
textPassword, barPasswordStrength, textPasswordStrength, textPasswordWrapper);
131128

132129
switchToggleVisibility.setOnCheckedChangeListener((buttonView, isChecked) -> {
133130
if (isChecked) {
@@ -183,13 +180,7 @@ public static void showSetPasswordDialog(ComponentActivity activity, PasswordSlo
183180
TextWatcher watcher = new SimpleTextWatcher(text -> {
184181
boolean equal = EditTextHelper.areEditTextsEqual(textPassword, textPasswordConfirm);
185182
buttonOK.get().setEnabled(equal);
186-
187-
Strength strength = zxcvbn.measure(textPassword.getText());
188-
barPasswordStrength.setProgress(strength.getScore());
189-
barPasswordStrength.setProgressTintList(ColorStateList.valueOf(Color.parseColor(PasswordStrengthHelper.getColor(strength.getScore()))));
190-
textPasswordStrength.setText((textPassword.getText().length() != 0) ? PasswordStrengthHelper.getString(strength.getScore(), activity) : "");
191-
textPasswordWrapper.setError(strength.getFeedback().getWarning());
192-
strength.wipe();
183+
passStrength.measure(activity);
193184
});
194185
textPassword.addTextChangedListener(watcher);
195186
textPasswordConfirm.addTextChangedListener(watcher);

app/src/main/java/com/beemdevelopment/aegis/ui/slides/SecuritySetupSlide.java

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package com.beemdevelopment.aegis.ui.slides;
22

3-
import android.content.res.ColorStateList;
4-
import android.graphics.Color;
3+
import static com.beemdevelopment.aegis.ui.slides.SecurityPickerSlide.CRYPT_TYPE_BIOMETRIC;
4+
import static com.beemdevelopment.aegis.ui.slides.SecurityPickerSlide.CRYPT_TYPE_INVALID;
5+
import static com.beemdevelopment.aegis.ui.slides.SecurityPickerSlide.CRYPT_TYPE_NONE;
6+
import static com.beemdevelopment.aegis.ui.slides.SecurityPickerSlide.CRYPT_TYPE_PASS;
7+
58
import android.os.Bundle;
69
import android.text.Editable;
7-
import android.text.TextWatcher;
810
import android.text.method.PasswordTransformationMethod;
911
import android.view.LayoutInflater;
1012
import android.view.View;
@@ -23,6 +25,7 @@
2325
import com.beemdevelopment.aegis.helpers.BiometricsHelper;
2426
import com.beemdevelopment.aegis.helpers.EditTextHelper;
2527
import com.beemdevelopment.aegis.helpers.PasswordStrengthHelper;
28+
import com.beemdevelopment.aegis.helpers.SimpleTextWatcher;
2629
import com.beemdevelopment.aegis.ui.dialogs.Dialogs;
2730
import com.beemdevelopment.aegis.ui.intro.SlideFragment;
2831
import com.beemdevelopment.aegis.ui.tasks.KeyDerivationTask;
@@ -32,17 +35,10 @@
3235
import com.beemdevelopment.aegis.vault.slots.Slot;
3336
import com.beemdevelopment.aegis.vault.slots.SlotException;
3437
import com.google.android.material.textfield.TextInputLayout;
35-
import com.nulabinc.zxcvbn.Strength;
36-
import com.nulabinc.zxcvbn.Zxcvbn;
3738

3839
import javax.crypto.Cipher;
3940
import javax.crypto.SecretKey;
4041

41-
import static com.beemdevelopment.aegis.ui.slides.SecurityPickerSlide.CRYPT_TYPE_BIOMETRIC;
42-
import static com.beemdevelopment.aegis.ui.slides.SecurityPickerSlide.CRYPT_TYPE_INVALID;
43-
import static com.beemdevelopment.aegis.ui.slides.SecurityPickerSlide.CRYPT_TYPE_NONE;
44-
import static com.beemdevelopment.aegis.ui.slides.SecurityPickerSlide.CRYPT_TYPE_PASS;
45-
4642
public class SecuritySetupSlide extends SlideFragment {
4743
private EditText _textPassword;
4844
private EditText _textPasswordConfirm;
@@ -76,27 +72,15 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
7672
}
7773
});
7874

79-
_textPassword.addTextChangedListener(new TextWatcher() {
80-
private Zxcvbn _zxcvbn = new Zxcvbn();
81-
82-
@Override
83-
public void onTextChanged(CharSequence s, int start, int before, int count) {
84-
Strength strength = _zxcvbn.measure(_textPassword.getText());
85-
_barPasswordStrength.setProgress(strength.getScore());
86-
_barPasswordStrength.setProgressTintList(ColorStateList.valueOf(Color.parseColor(PasswordStrengthHelper.getColor(strength.getScore()))));
87-
_textPasswordStrength.setText((_textPassword.getText().length() != 0) ? PasswordStrengthHelper.getString(strength.getScore(), requireContext()) : "");
88-
_textPasswordWrapper.setError(strength.getFeedback().getWarning());
89-
strength.wipe();
90-
}
91-
92-
@Override
93-
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
94-
}
75+
_textPassword.addTextChangedListener(new SimpleTextWatcher(new SimpleTextWatcher.Listener() {
76+
private final PasswordStrengthHelper passStrength = new PasswordStrengthHelper(
77+
_textPassword, _barPasswordStrength, _textPasswordStrength, _textPasswordWrapper);
9578

9679
@Override
9780
public void afterTextChanged(Editable s) {
81+
passStrength.measure(requireContext());
9882
}
99-
});
83+
}));
10084

10185
return view;
10286
}

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@
447447
<string name="password_strength_fair">Fair</string>
448448
<string name="password_strength_good">Good</string>
449449
<string name="password_strength_strong">Strong</string>
450+
<string name="password_strength_unknown">Password too long for strength analysis</string>
450451
<string name="pref_pin_keyboard_title">Use PIN keyboard on lockscreen</string>
451452
<string name="pref_pin_keyboard_summary">Enable this if you want to enable the PIN keyboard on the lockscreen. This only works for numeric passwords</string>
452453

0 commit comments

Comments
 (0)