Dev Build / cleanup (push) Canceled after 0s
Dev Build / typecheck (push) Canceled after 0s
Dev Build / build (linux-arm64, ubuntu-24.04-arm, linux-arm64) (push) Canceled after 0s
Dev Build / build (linux-x64, ubuntu-latest, linux-x64) (push) Canceled after 0s
Dev Build / build (win-x64, windows-latest, win32-x64) (push) Canceled after 0s
Dev Build / dispatch-dev-docker (push) Skipped
55 lines
1.8 KiB
Plaintext
55 lines
1.8 KiB
Plaintext
import utils from '../../../../scoring/utils'
|
|
import {
|
|
START_UPPER,
|
|
END_UPPER,
|
|
ALL_UPPER_INVERTED,
|
|
ALL_LOWER_INVERTED,
|
|
ONE_LOWER,
|
|
ONE_UPPER,
|
|
ALPHA_INVERTED,
|
|
} from '../../../../data/const'
|
|
|
|
const getVariations = (cleanedWord: string) => {
|
|
const wordArray = cleanedWord.split('')
|
|
const upperCaseCount = wordArray.filter((char) =>
|
|
char.match(ONE_UPPER),
|
|
).length
|
|
const lowerCaseCount = wordArray.filter((char) =>
|
|
char.match(ONE_LOWER),
|
|
).length
|
|
|
|
let variations = 0
|
|
const variationLength = Math.min(upperCaseCount, lowerCaseCount)
|
|
for (let i = 1; i <= variationLength; i += 1) {
|
|
variations += utils.nCk(upperCaseCount + lowerCaseCount, i)
|
|
}
|
|
return variations
|
|
}
|
|
|
|
export default (word: string) => {
|
|
// clean words of non alpha characters to remove the reward effekt to capitalize the first letter https://github.com/dropbox/zxcvbn/issues/232
|
|
const cleanedWord = word.replace(ALPHA_INVERTED, '')
|
|
if (
|
|
cleanedWord.match(ALL_LOWER_INVERTED) ||
|
|
cleanedWord.toLowerCase() === cleanedWord
|
|
) {
|
|
return 1
|
|
}
|
|
// a capitalized word is the most common capitalization scheme,
|
|
// so it only doubles the search space (uncapitalized + capitalized).
|
|
// all caps and end-capitalized are common enough too, underestimate as 2x factor to be safe.
|
|
const commonCases = [START_UPPER, END_UPPER, ALL_UPPER_INVERTED]
|
|
const commonCasesLength = commonCases.length
|
|
for (let i = 0; i < commonCasesLength; i += 1) {
|
|
const regex = commonCases[i]
|
|
if (cleanedWord.match(regex)) {
|
|
return 2
|
|
}
|
|
}
|
|
|
|
// otherwise calculate the number of ways to capitalize U+L uppercase+lowercase letters
|
|
// with U uppercase letters or less. or, if there's more uppercase than lower (for eg. PASSwORD),
|
|
// the number of ways to lowercase U+L letters with L lowercase letters or less.
|
|
return getVariations(cleanedWord)
|
|
}
|