Skip to content

Commit

Permalink
Merge pull request #245 from alanpoulain/fix/l33t-levenshtein
Browse files Browse the repository at this point in the history
fix(l33t): make sure all full subs use levenshtein
  • Loading branch information
MrWook authored Jan 17, 2024
2 parents 2c5882d + 846794e commit 7bdf886
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,14 @@ class MatchL33t {
zxcvbnOptions.trieNodeRoot,
)
let hasFullMatch = false
let isFullSubstitution = true
subbedPasswords.forEach((subbedPassword) => {
if (hasFullMatch) {
return
}
const matchedDictionary = this.defaultMatch({
password: subbedPassword.password,
useLevenshtein: isFullSubstitution,
useLevenshtein: subbedPassword.isFullSubstitution,
})
// only the first entry has a full substitution
isFullSubstitution = false
matchedDictionary.forEach((match: DictionaryMatch) => {
if (!hasFullMatch) {
hasFullMatch = match.i === 0 && match.j === password.length - 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type IndexedPasswordChanges = PasswordChanges & { i: number }
export interface PasswordWithSubs {
password: string
changes: IndexedPasswordChanges[]
isFullSubstitution: boolean
}

interface HelperOptions {
Expand Down Expand Up @@ -75,7 +76,7 @@ class CleanPasswords {

if (index === this.substr.length) {
if (onlyFullSub === isFullSub) {
this.finalPasswords.push({ password: this.buffer.join(''), changes })
this.finalPasswords.push({ password: this.buffer.join(''), changes, isFullSubstitution: onlyFullSub })
}
return
}
Expand All @@ -87,38 +88,39 @@ class CleanPasswords {
// iterate backward to get wider substitutions first
for (let i = index + nodes.length - 1; i >= index; i -= 1) {
const cur = nodes[i - index]
const sub = cur.parents.join('')
if (cur.isTerminal()) {
// Skip if this would be a 4th or more consecutive substitution of the same letter
// this should work in all language as there shouldn't be the same letter more than four times in a row
// So we can ignore the rest to save calculation time
if (
lastSubLetter === cur.parents.join('') &&
lastSubLetter === sub &&
consecutiveSubCount >= 3
) {
// eslint-disable-next-line no-continue
continue
}
hasSubs = true
const subs = cur.subs!
const letters = cur.subs!
// eslint-disable-next-line no-restricted-syntax
for (const sub of subs) {
this.buffer.push(sub)
for (const letter of letters) {
this.buffer.push(letter)
const newSubs = changes.concat({
i: subIndex,
letter: sub,
substitution: cur.parents.join(''),
letter,
substitution: sub,
})

// recursively build the rest of the string
this.helper({
onlyFullSub,
isFullSub,
index: i + 1,
subIndex: subIndex + sub.length,
index: index + sub.length,
subIndex: subIndex + letter.length,
changes: newSubs,
lastSubLetter: cur.parents.join(''),
lastSubLetter: sub,
consecutiveSubCount:
lastSubLetter === cur.parents.join('')
lastSubLetter === sub
? consecutiveSubCount + 1
: 1,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "4",
},
],
"isFullSubstitution": true,
"password": "Pau$mard",
},
{
Expand All @@ -45,6 +46,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "nn",
},
],
"isFullSubstitution": false,
"password": "Pau$m4rd",
},
{
Expand All @@ -65,6 +67,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "4",
},
],
"isFullSubstitution": false,
"password": "Pau$nnard",
},
{
Expand All @@ -80,6 +83,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "|_|",
},
],
"isFullSubstitution": false,
"password": "Pau$nn4rd",
},
{
Expand All @@ -100,6 +104,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "4",
},
],
"isFullSubstitution": false,
"password": "Pa|_|$mard",
},
{
Expand All @@ -115,6 +120,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "nn",
},
],
"isFullSubstitution": false,
"password": "Pa|_|$m4rd",
},
{
Expand All @@ -130,6 +136,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "4",
},
],
"isFullSubstitution": false,
"password": "Pa|_|$nnard",
},
{
Expand All @@ -140,6 +147,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "4",
},
],
"isFullSubstitution": false,
"password": "Pa|_|$nn4rd",
},
{
Expand All @@ -160,6 +168,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "4",
},
],
"isFullSubstitution": false,
"password": "P4u$mard",
},
{
Expand All @@ -175,6 +184,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "nn",
},
],
"isFullSubstitution": false,
"password": "P4u$m4rd",
},
{
Expand All @@ -190,6 +200,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "4",
},
],
"isFullSubstitution": false,
"password": "P4u$nnard",
},
{
Expand All @@ -200,6 +211,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "|_|",
},
],
"isFullSubstitution": false,
"password": "P4u$nn4rd",
},
{
Expand All @@ -215,6 +227,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "4",
},
],
"isFullSubstitution": false,
"password": "P4|_|$mard",
},
{
Expand All @@ -225,6 +238,7 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "nn",
},
],
"isFullSubstitution": false,
"password": "P4|_|$m4rd",
},
{
Expand All @@ -235,10 +249,12 @@ exports[`getCleanPasswords should get correct clean passwords 1`] = `
"substitution": "4",
},
],
"isFullSubstitution": false,
"password": "P4|_|$nnard",
},
{
"changes": [],
"isFullSubstitution": false,
"password": "P4|_|$nn4rd",
},
]
Expand All @@ -254,6 +270,7 @@ exports[`getCleanPasswords should limit the substitutions correctly 1`] = `
"substitution": "vv",
},
],
"isFullSubstitution": true,
"password": "w",
},
{
Expand All @@ -269,6 +286,7 @@ exports[`getCleanPasswords should limit the substitutions correctly 1`] = `
"substitution": "v",
},
],
"isFullSubstitution": true,
"password": "ff",
},
{
Expand All @@ -284,6 +302,7 @@ exports[`getCleanPasswords should limit the substitutions correctly 1`] = `
"substitution": "v",
},
],
"isFullSubstitution": true,
"password": "fu",
},
]
Expand All @@ -304,6 +323,7 @@ exports[`getCleanPasswords should substitute to multiple symbols correctly 1`] =
"substitution": "",
},
],
"isFullSubstitution": true,
"password": "pacific",
},
{
Expand All @@ -314,6 +334,7 @@ exports[`getCleanPasswords should substitute to multiple symbols correctly 1`] =
"substitution": "@",
},
],
"isFullSubstitution": false,
"password": "pacific",
},
{
Expand All @@ -324,10 +345,12 @@ exports[`getCleanPasswords should substitute to multiple symbols correctly 1`] =
"substitution": "",
},
],
"isFullSubstitution": false,
"password": "p@cific",
},
{
"changes": [],
"isFullSubstitution": false,
"password": "p@cific",
},
]
Expand All @@ -343,6 +366,7 @@ exports[`getCleanPasswords should substitute to multiple variants correctly 1`]
"substitution": "vv",
},
],
"isFullSubstitution": true,
"password": "w",
},
{
Expand All @@ -358,6 +382,7 @@ exports[`getCleanPasswords should substitute to multiple variants correctly 1`]
"substitution": "v",
},
],
"isFullSubstitution": true,
"password": "ff",
},
{
Expand All @@ -373,6 +398,7 @@ exports[`getCleanPasswords should substitute to multiple variants correctly 1`]
"substitution": "v",
},
],
"isFullSubstitution": true,
"password": "fu",
},
{
Expand All @@ -388,6 +414,7 @@ exports[`getCleanPasswords should substitute to multiple variants correctly 1`]
"substitution": "v",
},
],
"isFullSubstitution": true,
"password": "uf",
},
{
Expand All @@ -403,6 +430,7 @@ exports[`getCleanPasswords should substitute to multiple variants correctly 1`]
"substitution": "v",
},
],
"isFullSubstitution": true,
"password": "uu",
},
{
Expand All @@ -413,6 +441,7 @@ exports[`getCleanPasswords should substitute to multiple variants correctly 1`]
"substitution": "v",
},
],
"isFullSubstitution": false,
"password": "fv",
},
{
Expand All @@ -423,6 +452,7 @@ exports[`getCleanPasswords should substitute to multiple variants correctly 1`]
"substitution": "v",
},
],
"isFullSubstitution": false,
"password": "uv",
},
{
Expand All @@ -433,6 +463,7 @@ exports[`getCleanPasswords should substitute to multiple variants correctly 1`]
"substitution": "v",
},
],
"isFullSubstitution": false,
"password": "vf",
},
{
Expand All @@ -443,10 +474,12 @@ exports[`getCleanPasswords should substitute to multiple variants correctly 1`]
"substitution": "v",
},
],
"isFullSubstitution": false,
"password": "vu",
},
{
"changes": [],
"isFullSubstitution": false,
"password": "vv",
},
]
Expand Down

0 comments on commit 7bdf886

Please sign in to comment.