element-portable/src/utils/PasswordScorer.ts
David Langley 491f0cd08a
Change license (#13)
* Copyright headers 1

* Licence headers 2

* Copyright Headers 3

* Copyright Headers 4

* Copyright Headers 5

* Copyright Headers 6

* Copyright headers 7

* Add copyright headers for html and config file

* Replace license files and update package.json

* Update with CLA

* lint
2024-09-09 13:57:16 +00:00

108 lines
4.2 KiB
TypeScript

/*
Copyright 2018-2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
import { zxcvbn, zxcvbnOptions, ZxcvbnResult, TranslationKeys } from "@zxcvbn-ts/core";
import * as zxcvbnCommonPackage from "@zxcvbn-ts/language-common";
import * as zxcvbnEnPackage from "@zxcvbn-ts/language-en";
import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { _t } from "../languageHandler";
import SdkConfig from "../SdkConfig";
zxcvbnOptions.setOptions({
dictionary: {
...zxcvbnCommonPackage.dictionary,
...zxcvbnEnPackage.dictionary,
userInputs: ["riot", "matrix", "element", SdkConfig.get().brand],
},
graphs: zxcvbnCommonPackage.adjacencyGraphs,
useLevenshteinDistance: true,
});
function getTranslations(): TranslationKeys {
return {
warnings: {
straightRow: _t("zxcvbn|warnings|straightRow"),
keyPattern: _t("zxcvbn|warnings|keyPattern"),
simpleRepeat: _t("zxcvbn|warnings|simpleRepeat"),
extendedRepeat: _t("zxcvbn|warnings|extendedRepeat"),
sequences: _t("zxcvbn|warnings|sequences"),
recentYears: _t("zxcvbn|warnings|recentYears"),
dates: _t("zxcvbn|warnings|dates"),
topTen: _t("zxcvbn|warnings|topTen"),
topHundred: _t("zxcvbn|warnings|topHundred"),
common: _t("zxcvbn|warnings|common"),
similarToCommon: _t("zxcvbn|warnings|similarToCommon"),
wordByItself: _t("zxcvbn|warnings|wordByItself"),
namesByThemselves: _t("zxcvbn|warnings|namesByThemselves"),
commonNames: _t("zxcvbn|warnings|commonNames"),
userInputs: _t("zxcvbn|warnings|userInputs"),
pwned: _t("zxcvbn|warnings|pwned"),
},
suggestions: {
l33t: _t("zxcvbn|suggestions|l33t"),
reverseWords: _t("zxcvbn|suggestions|reverseWords"),
allUppercase: _t("zxcvbn|suggestions|allUppercase"),
capitalization: _t("zxcvbn|suggestions|capitalization"),
dates: _t("zxcvbn|suggestions|dates"),
recentYears: _t("zxcvbn|suggestions|recentYears"),
associatedYears: _t("zxcvbn|suggestions|associatedYears"),
sequences: _t("zxcvbn|suggestions|sequences"),
repeated: _t("zxcvbn|suggestions|repeated"),
longerKeyboardPattern: _t("zxcvbn|suggestions|longerKeyboardPattern"),
anotherWord: _t("zxcvbn|suggestions|anotherWord"),
useWords: _t("zxcvbn|suggestions|useWords"),
noNeed: _t("zxcvbn|suggestions|noNeed"),
pwned: _t("zxcvbn|suggestions|pwned"),
},
// We don't utilise the time estimation at this time so just pass through the English translations here
timeEstimation: zxcvbnEnPackage.translations.timeEstimation,
};
}
/**
* Wrapper around zxcvbn password strength estimation
* Include this only from async components: it pulls in zxcvbn
* (obviously) which is large.
*
* @param {string} password Password to score
* @param matrixClient the client of the logged-in user, if any
* @param userInputs additional strings such as the user's name which should be considered a bad password component
* @returns {object} Score result with `score` and `feedback` properties
*/
export function scorePassword(
matrixClient: MatrixClient | null,
password: string,
userInputs: string[] = [],
): ZxcvbnResult | null {
if (password.length === 0) return null;
// copy the supplied array before modifying it
const inputs = [...userInputs];
if (matrixClient) {
inputs.push(matrixClient.getUserIdLocalpart()!);
try {
const domain = matrixClient.getDomain()!;
inputs.push(domain);
} catch {
// This is fine
}
}
zxcvbnOptions.setTranslations(getTranslations());
let zxcvbnResult = zxcvbn(password, inputs);
// Work around https://github.com/dropbox/zxcvbn/issues/216
if (password.includes(" ")) {
const resultNoSpaces = zxcvbn(password.replace(/ /g, ""), inputs);
if (resultNoSpaces.score < zxcvbnResult.score) zxcvbnResult = resultNoSpaces;
}
return zxcvbnResult;
}