mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Simpler password strength estimation.
This commit is contained in:
@@ -6,9 +6,9 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
public interface PasswordStrengthEstimator {
|
||||
|
||||
float NONE = 0;
|
||||
float WEAK = 0.4f;
|
||||
float QUITE_WEAK = 0.6f;
|
||||
float QUITE_STRONG = 0.8f;
|
||||
float WEAK = 0.25f;
|
||||
float QUITE_WEAK = 0.5f;
|
||||
float QUITE_STRONG = 0.75f;
|
||||
float STRONG = 1;
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,31 +11,14 @@ import javax.annotation.concurrent.Immutable;
|
||||
@NotNullByDefault
|
||||
class PasswordStrengthEstimatorImpl implements PasswordStrengthEstimator {
|
||||
|
||||
private static final int LOWER = 26;
|
||||
private static final int UPPER = 26;
|
||||
private static final int DIGIT = 10;
|
||||
private static final int OTHER = 10;
|
||||
private static final double STRONG = Math.log(Math.pow(LOWER + UPPER +
|
||||
DIGIT + OTHER, 10));
|
||||
// The minimum number of unique characters in a strong password
|
||||
private static final int STRONG_UNIQUE_CHARS = 12;
|
||||
|
||||
@Override
|
||||
public float estimateStrength(String password) {
|
||||
HashSet<Character> unique = new HashSet<Character>();
|
||||
int length = password.length();
|
||||
for (int i = 0; i < length; i++) unique.add(password.charAt(i));
|
||||
boolean lower = false, upper = false, digit = false, other = false;
|
||||
for (char c : unique) {
|
||||
if (Character.isLowerCase(c)) lower = true;
|
||||
else if (Character.isUpperCase(c)) upper = true;
|
||||
else if (Character.isDigit(c)) digit = true;
|
||||
else other = true;
|
||||
}
|
||||
int alphabetSize = 0;
|
||||
if (lower) alphabetSize += LOWER;
|
||||
if (upper) alphabetSize += UPPER;
|
||||
if (digit) alphabetSize += DIGIT;
|
||||
if (other) alphabetSize += OTHER;
|
||||
double score = Math.log(Math.pow(alphabetSize, unique.size()));
|
||||
return Math.min(1, (float) (score / STRONG));
|
||||
return Math.min(1, (float) unique.size() / STRONG_UNIQUE_CHARS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||
import org.briarproject.bramble.test.BrambleTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.NONE;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@@ -12,7 +13,7 @@ public class PasswordStrengthEstimatorImplTest extends BrambleTestCase {
|
||||
@Test
|
||||
public void testWeakPasswords() {
|
||||
PasswordStrengthEstimator e = new PasswordStrengthEstimatorImpl();
|
||||
assertTrue(e.estimateStrength("") < QUITE_STRONG);
|
||||
assertTrue(e.estimateStrength("") == NONE);
|
||||
assertTrue(e.estimateStrength("password") < QUITE_STRONG);
|
||||
assertTrue(e.estimateStrength("letmein") < QUITE_STRONG);
|
||||
assertTrue(e.estimateStrength("123456") < QUITE_STRONG);
|
||||
|
||||
@@ -25,7 +25,7 @@ import javax.inject.Inject;
|
||||
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.WEAK;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
|
||||
|
||||
public class ChangePasswordActivity extends BaseActivity
|
||||
implements OnClickListener, OnEditorActionListener {
|
||||
@@ -109,13 +109,13 @@ public class ChangePasswordActivity extends BaseActivity
|
||||
strengthMeter.setStrength(strength);
|
||||
UiUtils.setError(newPasswordEntryWrapper,
|
||||
getString(R.string.password_too_weak),
|
||||
firstPassword.length() > 0 && strength < WEAK);
|
||||
firstPassword.length() > 0 && strength < QUITE_WEAK);
|
||||
UiUtils.setError(newPasswordConfirmationWrapper,
|
||||
getString(R.string.passwords_do_not_match),
|
||||
secondPassword.length() > 0 && !passwordsMatch);
|
||||
changePasswordButton.setEnabled(
|
||||
!currentPassword.getText().toString().isEmpty() &&
|
||||
passwordsMatch && strength >= WEAK);
|
||||
passwordsMatch && strength >= QUITE_WEAK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,7 +28,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.WEAK;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
|
||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||
|
||||
public class SetupActivity extends BaseActivity implements OnClickListener,
|
||||
@@ -115,13 +115,13 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
|
||||
nicknameLength > MAX_AUTHOR_NAME_LENGTH);
|
||||
UiUtils.setError(passwordEntryWrapper,
|
||||
getString(R.string.password_too_weak),
|
||||
firstPassword.length() > 0 && strength < WEAK);
|
||||
firstPassword.length() > 0 && strength < QUITE_WEAK);
|
||||
UiUtils.setError(passwordConfirmationWrapper,
|
||||
getString(R.string.passwords_do_not_match),
|
||||
secondPassword.length() > 0 && !passwordsMatch);
|
||||
createAccountButton.setEnabled(nicknameLength > 0
|
||||
&& nicknameLength <= MAX_AUTHOR_NAME_LENGTH
|
||||
&& passwordsMatch && strength >= WEAK);
|
||||
&& passwordsMatch && strength >= QUITE_WEAK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -193,7 +193,7 @@ public class ChangePasswordActivityTest {
|
||||
// Mock answers for UI testing only
|
||||
when(mockedController.estimatePasswordStrength("strong")).thenReturn(
|
||||
STRONG);
|
||||
when(mockedController.estimatePasswordStrength("qstring")).thenReturn(
|
||||
when(mockedController.estimatePasswordStrength("qstrong")).thenReturn(
|
||||
QUITE_STRONG);
|
||||
when(mockedController.estimatePasswordStrength("qweak")).thenReturn(
|
||||
QUITE_WEAK);
|
||||
@@ -205,9 +205,9 @@ public class ChangePasswordActivityTest {
|
||||
testStrengthMeter("strong", STRONG, StrengthMeter.GREEN);
|
||||
Mockito.verify(mockedController, Mockito.times(1))
|
||||
.estimatePasswordStrength(eq("strong"));
|
||||
testStrengthMeter("qstring", QUITE_STRONG, StrengthMeter.LIME);
|
||||
testStrengthMeter("qstrong", QUITE_STRONG, StrengthMeter.LIME);
|
||||
Mockito.verify(mockedController, Mockito.times(1))
|
||||
.estimatePasswordStrength(eq("qstring"));
|
||||
.estimatePasswordStrength(eq("qstrong"));
|
||||
testStrengthMeter("qweak", QUITE_WEAK, StrengthMeter.YELLOW);
|
||||
Mockito.verify(mockedController, Mockito.times(1))
|
||||
.estimatePasswordStrength(eq("qweak"));
|
||||
|
||||
@@ -196,7 +196,7 @@ public class SetupActivityTest {
|
||||
// Mock answers for UI testing only
|
||||
when(mockedController.estimatePasswordStrength("strong")).thenReturn(
|
||||
STRONG);
|
||||
when(mockedController.estimatePasswordStrength("qstring")).thenReturn(
|
||||
when(mockedController.estimatePasswordStrength("qstrong")).thenReturn(
|
||||
QUITE_STRONG);
|
||||
when(mockedController.estimatePasswordStrength("qweak")).thenReturn(
|
||||
QUITE_WEAK);
|
||||
@@ -208,9 +208,9 @@ public class SetupActivityTest {
|
||||
testStrengthMeter("strong", STRONG, StrengthMeter.GREEN);
|
||||
Mockito.verify(mockedController, Mockito.times(1))
|
||||
.estimatePasswordStrength(eq("strong"));
|
||||
testStrengthMeter("qstring", QUITE_STRONG, StrengthMeter.LIME);
|
||||
testStrengthMeter("qstrong", QUITE_STRONG, StrengthMeter.LIME);
|
||||
Mockito.verify(mockedController, Mockito.times(1))
|
||||
.estimatePasswordStrength(eq("qstring"));
|
||||
.estimatePasswordStrength(eq("qstrong"));
|
||||
testStrengthMeter("qweak", QUITE_WEAK, StrengthMeter.YELLOW);
|
||||
Mockito.verify(mockedController, Mockito.times(1))
|
||||
.estimatePasswordStrength(eq("qweak"));
|
||||
|
||||
Reference in New Issue
Block a user