Skip to content

Commit

Permalink
fix: fix the discrepancy in password guesses between zxcvbn and zxcvb…
Browse files Browse the repository at this point in the history
…n4j (#105)
  • Loading branch information
vvatanabe committed Aug 21, 2023
1 parent a213a44 commit 44dda11
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 11 deletions.
3 changes: 2 additions & 1 deletion src/main/java/com/nulabinc/zxcvbn/Guess.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.nulabinc.zxcvbn;

import com.nulabinc.zxcvbn.matchers.Match;
import java.util.Calendar;

public interface Guess {

public static final int BRUTEFORCE_CARDINALITY = 10;
public static final int MIN_SUBMATCH_GUESSES_SINGLE_CHAR = 10;
public static final int MIN_SUBMATCH_GUESSES_MULTI_CHAR = 50;
public static final int MIN_YEAR_SPACE = 20;
public static final int REFERENCE_YEAR = 2000;
public static final int REFERENCE_YEAR = Calendar.getInstance().get(Calendar.YEAR);

public double exec(Match match);
}
20 changes: 10 additions & 10 deletions src/main/java/com/nulabinc/zxcvbn/matchers/DateMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,13 @@ private Dmy mapIntsToDmy(int[] ints) {
if (over31 >= 2 || over12 == 3 || under1 >= 2) {
return null;
}
Map<Integer, int[]> possibleYearSplits = new HashMap<>();
possibleYearSplits.put(ints[2], Arrays.copyOfRange(ints, 0, 1 + 1));
possibleYearSplits.put(ints[0], Arrays.copyOfRange(ints, 1, 2 + 1));
for (Map.Entry<Integer, int[]> possibleYearSplitRef : possibleYearSplits.entrySet()) {
int y = possibleYearSplitRef.getKey();
int[] rest = possibleYearSplitRef.getValue();
int[][] possibleYearSplits = {
{ints[2], ints[0], ints[1]},
{ints[0], ints[1], ints[2]}
};
for (int[] split : possibleYearSplits) {
int y = split[0];
int[] rest = new int[] {split[1], split[2]};
if (DATE_MIN_YEAR <= y && y <= DATE_MAX_YEAR) {
Dm dm = mapIntsToDm(rest);
if (dm != null) {
Expand All @@ -274,12 +275,11 @@ private Dmy mapIntsToDmy(int[] ints) {
}
}
}
for (Map.Entry<Integer, int[]> possibleYearSplitRef : possibleYearSplits.entrySet()) {
int y = possibleYearSplitRef.getKey();
int[] rest = possibleYearSplitRef.getValue();
for (int[] split : possibleYearSplits) {
int[] rest = new int[] {split[1], split[2]};
Dm dm = mapIntsToDm(rest);
if (dm != null) {
y = twoToFourDigitYear(y);
int y = twoToFourDigitYear(split[0]);
return new Dmy(dm.day, dm.month, y);
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/com/nulabinc/zxcvbn/JavaPortTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ public static Iterable<Object[]> data() {
{"password@123"},
{"lkjhgfdsa"},
{"hGFd"},
{"2352523452bd dhf"},
{"23525"},
// the following password fails in version 4.4.1
// https://github.com/dropbox/zxcvbn/issues/174
//
Expand Down
7 changes: 7 additions & 0 deletions src/test/java/com/nulabinc/zxcvbn/MatchingTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,13 @@ public static Collection<Object[]> data() {
new ExpectedMatch("111504").separator("").year(2004).month(11).day(15)
});

data.add(
new Object[] {
"23525",
"matches as 23/5/2025, not 25/5/2023",
new ExpectedMatch("23525").separator("").year(2025).month(5).day(23)
});

return data;
}
}
Expand Down
48 changes: 48 additions & 0 deletions src/test/java/com/nulabinc/zxcvbn/ScoringTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -398,4 +398,52 @@ public void testL33tVariants() throws Exception {
0.0);
}
}

@RunWith(Parameterized.class)
public static class DateGuessTest {

private final String token;
private final int i;
private final int j;
private final String separator;
private final int year;
private final int month;
private final int day;
private final double expectedGuesses;

public DateGuessTest(
String token,
int i,
int j,
String separator,
int year,
int month,
int day,
double expectedGuesses) {
this.token = token;
this.i = i;
this.j = j;
this.separator = separator;
this.year = year;
this.month = month;
this.day = day;
this.expectedGuesses = expectedGuesses;
}

@Test
public void testDateGuess() throws Exception {
Context context = StandardContext.build();
Match match = MatchFactory.createDateMatch(i, j, token, separator, year, month, day);
String msg = String.format("the date pattern '%s' has guesses of %s", token, expectedGuesses);
assertEquals(msg, expectedGuesses, new DateGuess(context).exec(match), 0.0);
}

@Parameterized.Parameters(name = "{0}")
public static Collection<Object[]> data() {
return Arrays.asList(
new Object[][] {
{"23525", 0, 4, "", 2025, 5, 23, 7300.0},
});
}
}
}

0 comments on commit 44dda11

Please sign in to comment.