From d325fb4e6083aa82e49fc0a363d06f7b9b49b8a0 Mon Sep 17 00:00:00 2001 From: Blase Ur Date: Wed, 2 Aug 2017 15:27:18 -0500 Subject: [PATCH 01/45] Fixing missing type definition that caused a compilation error --- src/ts/ui-misc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ts/ui-misc.ts b/src/ts/ui-misc.ts index 061d25a..a5ad6c7 100644 --- a/src/ts/ui-misc.ts +++ b/src/ts/ui-misc.ts @@ -265,7 +265,7 @@ export module UIMisc { generateCandidateFixed(pw: string, depth: number, originalPW: string): number { // We keep a vector that tracks changes we make to the password for // future highlighting purposes. - var deltas = []; + var deltas: Array = []; // If this is the initial call, initialize that vector if (typeof (this.deltaHighlighted[pw]) === "undefined") { for (var i = 0; i < pw.length; i++) { From d427cdc7f172f5dda113cf99fc3bb15c8af7297f Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Wed, 20 Feb 2019 14:35:20 -0500 Subject: [PATCH 02/45] Changes to make typescript successfully compile on my machine --- src/package.json | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/package.json b/src/package.json index a368c2d..132dc58 100644 --- a/src/package.json +++ b/src/package.json @@ -4,19 +4,21 @@ "description": "Password Meter", "main": "PasswordMeter.js", "devDependencies": { - "@types/core-js": "0.9.36", + "@types/core-js": "latest", "@types/jquery": "latest", "@types/lz-string": "latest", "tsify": "latest", "typescript": "latest", - "babelify": "latest", + "babelify": "7.3.0", "uglifyify": "latest", - "browserify": "latest" + "browserify": "latest", + "@types/node": "latest" }, "dependencies": { + "babel-core": "^6.0.0" }, "scripts": { - "do-browserify" : "browserify ts/*.ts -p [ tsify --noImplicitAny ] -o PasswordMeter.js" + "do-browserify": "browserify ts/*.ts -p [ tsify --noImplicitAny ] -o PasswordMeter.js" }, "browserify": { "transform": [ From c0d63a118fb0b0374ad744fbb57e93f288437ed9 Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Wed, 20 Feb 2019 16:25:37 -0500 Subject: [PATCH 03/45] Added gitignore for password meter generated files. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cfe25b2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +src/PasswordMeter.js +src/node_modules +src/package-lock.json From cb134ef792c86402c44d722b7f843387180864e6 Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Fri, 22 Feb 2019 10:34:28 -0500 Subject: [PATCH 04/45] Implemented minNN guess number cutoff in typescript --- src/ts/config.ts | 275 +++-- src/ts/constants.ts | 2 + src/ts/nn-misc.ts | 262 ++--- src/ts/rulefunctions.ts | 70 +- src/ts/ui-misc.ts | 2230 ++++++++++++++++++++------------------- 5 files changed, 1440 insertions(+), 1399 deletions(-) diff --git a/src/ts/config.ts b/src/ts/config.ts index 40f0b01..8a54d51 100644 --- a/src/ts/config.ts +++ b/src/ts/config.ts @@ -1,152 +1,151 @@ -// test 8 dimensions of composition requirements as follows: -// dimension 1: length (min / max) -// dimension 2: mandatory # of character classes -// dimension 3: mandatory character classes -// dimension 4: forbidden character classes -// dimension 5: forbidden passwords -// dimension 6: permitted/forbidden characters -// dimension 7: repeated consecutive characters -// dimension 8: password - username comparison - -import PasswordMeter = require("./PasswordMeter"); - export module Config { -interface ConfigColor{ - compliant: string; - noncompliant: string; -} + interface ConfigColor { + compliant: string; + noncompliant: string; + } -interface ConfigSymbols { - compliant: string; - noncompliant: string; -} + interface ConfigSymbols { + compliant: string; + noncompliant: string; + } -interface ConfigLength { - active: boolean; - minLength: number; - maxLength: number; -} + interface ConfigLength { + active: boolean; + minLength: number; + maxLength: number; + } -interface ConfigClassCount { - active: boolean; - minCount: number; - maxCount: number; -} + interface ConfigClassCount { + active: boolean; + minCount: number; + maxCount: number; + } -interface ConfigClassBoolean { - active: boolean; - upperCase: boolean; - lowerCase: boolean; - digits: boolean; - symbols: boolean; -} + interface ConfigClassBoolean { + active: boolean; + upperCase: boolean; + lowerCase: boolean; + digits: boolean; + symbols: boolean; + } -interface ConfigForbidPasswords { - active: boolean; - includeLargerList: boolean; -} + interface ConfigForbidPasswords { + active: boolean; + includeLargerList: boolean; + } -interface ConfigForbidChars { - active: boolean; - list: Array; -} + interface ConfigForbidChars { + active: boolean; + list: Array; + } -interface ConfigLimit { - active: boolean; - limit: number; -} + interface ConfigLimit { + active: boolean; + limit: number; + } -export interface ConfigNeuralNetwork { // raise visibility because we pass it on to a dependency - intermediate: string; - file: string; - zigzag: boolean; - scaleFactor: number; -} + interface ConfigThreshold { + active: boolean; + threshold: number; + rejectionFeedback: string; + } -export interface Config { - colors: ConfigColor; - symbols: ConfigSymbols; - remindAgainstReuse: boolean; - ignoredWords: Array; - forbiddenPasswords: Array; - length: ConfigLength; - classCount: ConfigClassCount; - classRequire: ConfigClassBoolean; - classAllow: ConfigClassBoolean; - forbidPasswords: ConfigForbidPasswords; - forbidChars: ConfigForbidChars; - repeatChars: ConfigLimit; - usernameDifference: ConfigLimit; - neuralNetworkConfig: ConfigNeuralNetwork; -} + export interface ConfigNeuralNetwork { // raise visibility because we pass it on to a dependency + intermediate: string; + file: string; + zigzag: boolean; + scaleFactor: number; + } -export var passwordMeterDefaultConfig: Config = { - colors: { // display colors - compliant: "#006600", // by default show completed requirement in green - noncompliant: "#660000", // by default show outstanding requirement in red - }, - symbols: { // display symbols - compliant: "✔ ", // HEAVY CHECK MARK - noncompliant: "❑ ", // LOWER RIGHT SHADOWED WHITE SQUARE - }, - remindAgainstReuse: true, // true to emphasize *not* reusing passwords - ignoredWords: // list of words that should count for nothing in the password - ["pittsburgh", - "steelers", "stillers", "penguins", "pens", "pirates", "bucs", "carnegie", "mellon", - "university"], - forbiddenPasswords: // list of passwords that should be rejected - ["123456", "password", "12345", "12345678", "qwerty", "1234567890", "1234", - "baseball", "dragon", "football", "1234567", "monkey", "letmein", "abc123", - "111111", "mustang", "access", "shadow", "master", "michael", "superman", - "696969", "123123", "batman", "trustno1"], - length: { - active: true, - minLength: 8, - maxLength: 0, // set to 0 if there is no maximum length - }, - classCount: { // number of character classes - active: false, - minCount: 1, // classes are upper case, lower case, digits and symbols (others) - maxCount: 4, - }, - classRequire: { // required character classes - active: false, - upperCase: false, - lowerCase: true, - digits: true, - symbols: false, - }, - classAllow: { // permitted character classes - active: false, - upperCase: true, - lowerCase: true, - digits: true, - symbols: true, - }, - forbidPasswords: { - active: true, - includeLargerList: true, // setting this to true also blacklists tens of thousands - // of common passwords loaded for the common passwords dictionary check - }, - forbidChars: { - active: false, - list: [], - }, - repeatChars: { - active: true, - limit: 3, // prohibit a character being repeated N or more times consecutively - }, - usernameDifference: { - active: true, - limit: 1, // prohibit passwords being N or fewer characters different than username - }, - neuralNetworkConfig: { - intermediate: "basic_3M.info_and_guess_numbers.no_bloomfilter.json", - file: "basic_3M.weight_arch.quantized.fixed_point1000.zigzag.nospace.json", - zigzag: true, - scaleFactor: 300, - }, + export interface Config { + colors: ConfigColor; + symbols: ConfigSymbols; + remindAgainstReuse: boolean; + ignoredWords: Array; + forbiddenPasswords: Array; + length: ConfigLength; + classCount: ConfigClassCount; + classRequire: ConfigClassBoolean; + classAllow: ConfigClassBoolean; + forbidPasswords: ConfigForbidPasswords; + forbidChars: ConfigForbidChars; + repeatChars: ConfigLimit; + usernameDifference: ConfigLimit; + minLogNnGuessNum: ConfigThreshold; + neuralNetworkConfig: ConfigNeuralNetwork; + } -}; + export var passwordMeterDefaultConfig: Config = { + colors: { // display colors + compliant: "#006600", // by default show completed requirement in green + noncompliant: "#660000", // by default show outstanding requirement in red + }, + symbols: { // display symbols + compliant: "✔ ", // HEAVY CHECK MARK + noncompliant: "❑ ", // LOWER RIGHT SHADOWED WHITE SQUARE + }, + remindAgainstReuse: true, // true to emphasize *not* reusing passwords + ignoredWords: // list of words that should count for nothing in the password + ["pittsburgh", + "steelers", "stillers", "penguins", "pens", "pirates", "bucs", "carnegie", "mellon", + "university"], + forbiddenPasswords: // list of passwords that should be rejected + ["123456", "password", "12345", "12345678", "qwerty", "1234567890", "1234", + "baseball", "dragon", "football", "1234567", "monkey", "letmein", "abc123", + "111111", "mustang", "access", "shadow", "master", "michael", "superman", + "696969", "123123", "batman", "trustno1"], + length: { + active: true, + minLength: 8, + maxLength: 0, // set to 0 if there is no maximum length + }, + classCount: { // number of character classes + active: false, + minCount: 1, // classes are upper case, lower case, digits and symbols (others) + maxCount: 4, + }, + classRequire: { // required character classes + active: false, + upperCase: false, + lowerCase: true, + digits: true, + symbols: false, + }, + classAllow: { // permitted character classes + active: false, + upperCase: true, + lowerCase: true, + digits: true, + symbols: true, + }, + forbidPasswords: { + active: true, + includeLargerList: true, // setting this to true also blacklists tens of thousands + // of common passwords loaded for the common passwords dictionary check + }, + forbidChars: { + active: false, + list: [], + }, + repeatChars: { + active: true, + limit: 3, // prohibit a character being repeated N or more times consecutively + }, + usernameDifference: { + active: true, + limit: 1, // prohibit passwords being N or fewer characters different than username + }, + minLogNnGuessNum: { + active: false, + threshold: 7, // prohibit passwords with a NN guess number less than 10^7 + rejectionFeedback: "Not be similar to extremely common passwords", + }, + neuralNetworkConfig: { + intermediate: "basic_3M.info_and_guess_numbers.no_bloomfilter.json", + file: "basic_3M.weight_arch.quantized.fixed_point1000.zigzag.nospace.json", + zigzag: true, + scaleFactor: 300, + }, + }; } diff --git a/src/ts/constants.ts b/src/ts/constants.ts index 4d1475a..f8914ff 100644 --- a/src/ts/constants.ts +++ b/src/ts/constants.ts @@ -14,6 +14,8 @@ export module Constants { export const startASCII = 32; export const endASCII = 126; + export const METER_STRINGENCY_SCALE_FACTOR = 67 / 15; // scale so that guess number of 10^15 ~= 67% of meter; 15 dits * 67 percent/15 dits + export const commonStructures = ["LLLLLL", "LLLLLLLL", "LLLLLLL", "DDDDDDDD", "DDDDDD", "LLLLL", "DDDDDDD", "LLLLLLDD", "LLLLLLLLL", "LLLL", "DDDD", "LLLLLLLD", "LLLLLD", "LLLLLLLLLL", "LLLLLDD", "LLLLDDDD", "LLLLLLD", "LLLLDD", "LLLLLDDD", "DDDDD", "LLLDDD", "LLLDDDD", "DDDDDDDDD", "LLLLLLLLLLL", "DDDDDDL", "LLLLLDDDD", "LLLLDDD", "LLLLLLLDD", "DDDDDDDDDD", "LLLLLLLLLLLL", "LLLLLLDDDD", "DDDDDDDDL", "UUUUUUUU", "LLLLLLDDD", "LLDDDD", "DDDDDDDDDDD", "ULLLLL", "LLLLLLLLDD", "LLLLLLLLD", "ULLLLLLL", "UUUUUU", "ULLLLLLD", "LLLLLLLLLLLLL", "ULLLLLL", "LLLLLLLDDDD", "LLLLLLLDDD", "ULLLLLD", "DDDDLLLL", "LLLLLLLLLLLLLL", "LLLLD", "LLDDDDDD", "DLLLLLLL", "UUUUUUU", "LLLLLLLLLD", "DDLLLLLL", "DDDDLL", "DDDDDDLL", "LDDDDDD", "LLLDDDDD", "ULLLLLDD", "LLLLLLLLDDDD", "DDDLLL", "LLLLLLLLLDD", "DDDDDDDL", "LLLLLLLLLLLLLLL", "DDDDLLL", "DULLLLL", "DULLLLLL", "LLLDDDDDD", "ULLLLD", "LLLLLLLLDDD", "DLLLLL", "DDDDDDLLL", "LLLLDLLL", "LLLLDDDDDD", "ULLLL", "LLLDD", "LDDDDDDD", "LLLDLLLL", "LLLLLLLLLLLLLLLL", "DDLLLL", "LLLDDLLL", "DDDDDDDDDDDD", "DLLLLLL", "DDLLLLL", "LLLLLDLL", "LLLLLLLLLLDD", "LLDDDDD", "LLLLLDDDDDD", "DDDLLLLL", "LDDDDDDDD", "DDDDDDLLLL", "UUUUU", "LLLLLLDL", "LDDDDD", "ULLLDDDD", "ULLLLDDD", "ULLLLLLLL", "LLLLLLLLLDDD", "DDDDDL", "LLLLLLDDDDDD", "LLLLLLLLLLDDDD", "DULLLL", "ULLLLDD", "LLLLDDDDD", "LLLLDL", "LDLLLLLL", "LLDLLLLL", "LLLDLL", "LLDLLL", "LLLLLLLLLLD", "LLLDLLL", "LLLLLDDDDD", "DDDDLLLLL", "LDLDLDLD", "DDDDDDDDLL", "DDDDDDDDLLL", "LLLLLLLLLDDDD", "DDDLLLL", "DDDDDDDDLLLL", "DLLLLLLD", "LLDDD", "LDLDLD", "LLLD", "DDDDDDDDDL", "DLLLDLLL", "LDLLLL", "LLLLDDDDDDDD", "LLLLDLL", "UUUU", "ULLLLDDDD", "LLLLLDL", "ULLLLLLDD", "DDLLLLDD", "LLLLLLDDDDD", "LLDDLL", "DDDDLLLLLL", "DDDDDLLL", "DDDDDDDDDDDL", "DDDDDDDDDDL", "LLLDDDDDDDD", "LDDDDL", "LLLLDDLL", "ULLL", "LLLLLLLLLLLDD", "LLLLLLLLLLLLLLLLL", "DDDDDDLLLLL", "LLLLLLLLLLLLDD", "LLLLLLLLLLLD", "ULLLLLDDDD", "LDDDLL", "ULLLLLLLLL", "ULLLDD", "LLLDDDDDDD", "LLDDDDDDD", "LLLDLLLD", "DDLLLDD", "DDDDDDDLL", "LLDDDDDDDD", "ULLLLLLLD", "LLLLLDDL", "DLDLDLDL", "LLDDDDLL", "DDDDDDDLLL", "DLDLDL", "ULLLLLDDD", "LLLLLDDDDDDDD", "UUUUUUDD", "LLDLLLL", "LLLLLLLLLLDDD", "LDDDDDDL", "DDDDDLL", "ULLLD", "LLLLDDDDDDD", "LLDDLLLL", "LLLDDDLL", "DDDDDDLLLLLL", "DLLLLD", "DLLLL", "LLLLLLLLLLLLLLLLLL", "LLLDDLL", "ULLLLLLLDD", "LLDDLLDD", "UUUUUUUUU", "LLLLLLLLLLLDDDD", "DULLL", "ULLLDDD", "DDLLLLLLL", "LLL", "UUUUDDDD", "DDLLDD", "DDDLLLLLL", "DDDDDDDDLLLLL", "LLLDDL", "DLLLLLD", "DDDDDDDLLLL", "LDLLLLL", "UUUDDDD", "LLLLLLLDDDDDD", "DLLLLLLLL", "LLLLLLLLLLLDDD", "LLLLLLLLLLLLLDD", "LLLLLLDDDDDDDD", "UUUUUD", "UUUUDD", "LDDLLLLL", "LLLLDLLLL", "DDDDLLLLLLL", "LLLLLDDDDDDD", "DDDDL", "UUUDDD", "LLLLLLLLLLLLD", "UUDDDD", "UUUUUUUD", "LLLLLLLLLLLLDDDD", "LDLDLDLDLD", "LDDD", "LLDLLD", "DDDDDDU", "LLLLDDL", "LLLDDDDL", "UUUUUDD", "LLLLLLLDDDDD", "DDLLLLLDD", "UDDDDDD", "LLDD", "LDDDD", "LLDDDLL", "ULLLULLL", "DDDDLLLLLLLL", "LDLLLDLL", "DDDDDLLLL", "LDDLLL", "LLLLLDLD", "ULLLLLLDDD", "ULLLLU", "DDLLL", "LLDDLLL", "ULLLLLLDDDD", "LDDLDD", "LDLLDL", "ULLLLLLLLLL", "LLDLLLDL", "", "LLLLDLLD", "LLDLLDLL", "LLLDL", "LLDLLLLD", "ULDDDDDD", "ULLULL", "LLLDDDLLL", "UUUUUDDD", "LLDLL", "UUUUUUD", "LLLLDDDL", "LLLLLLLLLLLLLD", "LLLLLLLLDDDDDD", "UUUUUUUUUU", "LDLLLLDL", "LLLLDLDL", "LDLLDLLL", "LLLLLLLLLLLLLLLLLLL", "DLDLLLLL", "DDDLLLDDD", "DDDDDLLLLL", "LLLDDDL", "DLLLLDLL", "LLLDLLDL", "LLLLLLLLLLLLDDD", "LDDDDDDDDD", "ULLLLLLLLD", "LDLDLLLL", "LLLLLLLLLLLLLLDD", "DDLLLLLLLL", "LLDLDLLL", "DLLLLLDL", "DDDDDDDDU", "DDDDDDDDLLLLLL", "LDDDDDDDDDD", "LDLLLLLD", "DDLLLLLLDD", "LLDDDL", "LLLDLDLL", "DLLL", "ULLDDDD", "DDLLDLLL", "DLLLLLLLLL", "DLLDLLLL", "DDDLL", "LLLLLLDDDDDDD", "DDD", "LLLLLLLDDDDDDDD", "LLLDLD", "DDLLLLLD", "DLLDLL", "LLLLLLDLL", "UUDDDDDD", "DDDDDDDDDLLL", "LLDDDLLL", "ULLLLLLLLDD", "ULULLL", "DDLLDDLL", "DLLLLLDD", "LDLLL", "DDDDDDDLLLLL", "DDLDDLDDL", "ULULUL", "ULLLUL", "LDLLLD", "UDDDDDDDD", "LLLLLDLLL", "LDLDLL", "ULLLLULL", "DDDDDDDDDDDDD", "ULLLLLLLDDDD", "UUUUDDD", "LLLLLLLLLLLLLLLLLLLL", "DDDDDDDDDDDDDD", "DDDLDDD", "DDLDDL", "DLLLDL", "ULLLUU", "DLDLDLDLDL", "ULLLLLLLDDD", "ULLDDD", "LLLLLLDLLL", "DDDLLLLLLL", "DDDDDDDDDDLL", "DDLLLDDDD", "UDDDDDDD", "ULUULL", "ULULLU", "ULLLLLLLLLD", "ULUULU", "DDDDDDDDDLL", "LLLLLDLLLL", "DDDDDDDDDDDLLLL", "ULUUUL", "ULUUUU", "ULLUUU", "ULLULU", "ULLUUL", "LLDLDL", "LLLLLLLDL", "LLLLLLLS", "LLDL", "LLLLLLLLLLLLLLD", "LDDDDDDDDL", "LDDDLLL", "LLLLLLS", "ULULUU", "LDDDDDDDDDDD", "LLLLLLLLLLLLLDDD", "LLLLLLLLLDDDDDD", "DDDDDDLLLLLLL", "DDDDDDDDDDLLL", "LLLDDLLD", "DDDLLDDD", "LDDLDDLDD", "LLLDLLLLL", "ULLLLLLLLLLL", "LLLLDDLLL", "DDLLLD", "LLLDDDDLLL", "DDDDDDDDDDDLLL", "LDLDLDL", "LLLLLLLLDDDDD", "LLLLSLLL", "LLLLLLLLDDDDDDDD", "DLLLDD", "LLLLDLD", "DDDDDDDDDDDDDDDD", "DLDLLL", "UUUUUDDDD", "DDDDDDDDDDLLLL", "LLLLDLLLLL", "DLLLD", "DDDDDDDU", "DDDDDDUU", "DDDLLLDD", "LLDDDDL", "DLLLLLLLD", "LLLSLLL", "LDDLLLL", "ULLLDDDDDD", "LLLLLLLLLLLLLDDDD", "DDLLLLD", "ULLULLLL", "LLLDDLLLL", "LLLLDDLLLL", "DDDLLLLDDD", "LDLL", "LDDDDDDDL", "LLLDLLLLLL", "DDDDDDDDDLLLL", "LDDDLLDD", "LDDDLLLL", "LLDDLLLD", "DDDDDDDDDDDLL", "LLLDLLDD", "DDLL", "DDDDUU", "DDLDDLDD", "DDDDDDLLLLLLLL", "DDLDDDD", "DDDDLLDD", "LLLLLS", "ULLDDDDDD", "LLDLLDL", "LDLDLDLL", "LLLLDLDD", "LDLLLLLLL", "DDDLLLD", "LLDLLLDD", "ULLDDDDD", "ULLLLLLU", "ULDDDD", "LLLDDLLLDD", "UUUUUUUDD", "LLLLLLLDDDDDDD", "UUUDDDDD", "LLDLLLD", "UUDDDDD", "LDLDL", "UUUUUUUUUUU", "LDLLLLDD", "LLDLLLLLL", "LLLDDLDL", "DLLLDLL", "DLLLLDD", "LLLLLSDD", "DDDDULLL", "DDLLDDDD", "LLLLLLLDLL", "DLLLLDL", "LLLLLLLLDL", "LDLLLDL", "DLDLDLD", "LLDLDD", "LLLDDDDDDDDD", "ULLLLDDDDDD", "LDDDLDDD", "DDDDDDDDDDDDDDD", "DDDDDDDDDDDDL", "ULLULLL", "LDLDLDLDLDLD", "LLLDLLD", "DDDDDDDLLLLLL", "LDDDDDL", "DDDLLLLLLLLL", "LLDDL", "LLLLLLDDL", "LDLLDLL", "LDLLDLDL", "LLLLLLLLLLLLLLLDD", "UULLLLLL", "ULLLLLLLLLDD", "LDDDDLL", "LDLLDLLD", "DDDLDD", "DDLLLLLLLDD", "LLLLLLLLS", "UUUUUUDDDD", "LLLLDDLD", "UDDDDD", "LLDDLDLL", "DDDDDDDDLLLLLLL", "UUUDDDDDD", "DDDDLDDDD", "LLDDLD", "LLLLLDDLLL", "DDLLLDDD", "UUUUUUDDD", "LLLLLDDLL", "LLLLDDDDDDDDDD", "DDDLLLLLLLL", "LLLLLLLLLDDDDD", "LDLLDD", "LLLLLLLLLLLLLLLLLLLLL", "LLLLLLLLLLLLLLLD", "LLLSLLLL", "DDDDLD", "DDLDDD", "DDDDUUUU", "DLDLL", "LDLLLLD", "DLDLLLDL", "LLLLSLLLL", "LDLDLLDL", "DDLDLLLL", "DDDDDDDDDDDLLLLL", "LLLLLLLLLLDDDDDD", "UUUUUUUUUUUU", "LLLDLDL", "LLLLDDDDDDDDD", "DDDDDLLLLLL", "DDULLLLL", "ULLLULL", "LLLLLLLLLLLLLLDDDD", "DLLDLLDL", "LLLDLDLD", "LLLDDDDDDDDDD", "DDDDLLLLDDDD", "LLLLSL", "LDLDLLL", "DLLLLLLLLD", "LDLLLDLD", "DDDDLDD", "ULDDDLL", "LLDLLLLLLL", "LLLLLLSDD", "DLDLLLL", "ULLLLLLLLDDD", "LLDLDLL", "DDDDDDS", "DDLLLLLLLLL", "LDLLLDDL", "ULLLLDLL", "DDLLLDLL", "DDLLDL", "LLLLLSLLL", "DLLLDDLL", "LDLDLDLDL", "DLLLDLDL", "DLLDLLL", "DLLDL", "DLDLDLLL", "LLDDLLD", "DDDLLLLLDDD", "DDSDDSDDDD", "LLDDLLDL", "DLLDLLLD", "DLLLDDD", "LLDLLDDL", "LLLLLU", "DLLDLDLL", "LDDLDL", "LDDLLD", "LLDLLDLD", "DDLLDDD", "DDDDLLLD", "DLLDDL", "ULLLLLDDDDDD", "DDDLDDDL", "DDLLD", "LLLLLDLLLLL", "LLLDDLDD", "LLDLDLLD", "LDDDDLLL", "DLLDDLLL", "LLLLDDDDDDDDDDD", "DLDLLDLL", "LLDDDDDDDDD", "DDDDDDUUU", "DLDDLLLL", "DDDLLD", "LDDLLLLD", "LDLLLLLLLL", "DDDDUUU", "LLDLDLDL", "DLLLLDLD", "DDLLLLDDDD", "ULLLLDDDDD", "LUULDDL", "ULLLDDDDD", "LDDLLLDL", "ULLLLLLLLDDDD", "DDLLLLDL", "DLLLLLLLLLL", "ULLLLLU", "LLLLLSLL", "DLLLLDDL", "LDLDLLLD", "DLDLLLLD", "UUUDD", "LDLDDLLL", "LLLLLLDLLLL", "LDLLD", "DDDDDDUL", "LDLD", "DLLLLDDD", "LDLLDDLL", "UUUUD", "LDDLLDLL", "LLLLLLLLDDDDDDD", "LLLDLDDL", "DLLLDLLD", "DDDDDDDDDDLLLLL", "LLLLLDDDDDDDDD", "DDDDDDDDUU", "LLLLLDDDDDDDDDD", "ULDDDDDDDD", "UUULLL", "LLLLLSLLLLL", "LLLLLSLLLL", "DLDLLD", "LLLSDDDD", "LLDDDDDDLL", "DLLLDDDD", "DLDLD", "ULLLLLLLLLLLL", "LLLLLLULLLLL", "LLDLDDLL", "LLLLLLLLLLLLLLDDD", "DDDDLLD", "LLLDDDLD", "ULLLLULLLL", "LDDLL", "DDLLLDDL", "DDDLLLLD", "DDDL", "ULDDDDDDD", "LLLLLLLU", "DDDLLDD", "LLLLLLLLLLDDDDD", "DDLDD", "LLLLLLLLLLLLLLLLLLLLLL", "UDLLLLLL", "LLLLSDD", "LDDLDLLL", "DLDDLL", "LLLLSLLLLL", "LLLLSLLLLLL", "LLDDDDDDDDDD", "DLDDDD", "ULLLDLLL", "LLLDDDDLL", "DDDDLDDD", "DLDLDLDLDLDL", "ULLLLLUL", "DDLDLL", "UUULLLLL", "UDDDDDDL", "LLLLLLDDDDDDDDD", "LLLLLLLLLS", "LLSLLL", "LLDLD", "DDDLDDDD", "LLLLLLLLLLLLLLLLDD", "LLLDDLD", "LLLLLLSD", "UUUUUUUUDD", "LDLDDD", "LLDLLDD", "DDDDLLLDDDD", "DDLLLLLLLLDD", "LLLLDDDDLLLL", "DDDDDU", "UUUDDDUU", "DDDDDDDDLLLLLLLL", "LLLLDLLLLD", "UUUUUUUUD", "LLLLSDDD", "LLLLLDDDDDDDDDDD", "DDDLLLLLLDDD", "DLLDDD", "DLLDLD", "LLDDLLLLL", "UDDDDDDU", "LSLLLL", "LLLLLLULLLLLL", "DDDDDDDDDLLLLL", "LLLLLLDDLL", "DDDDDDDDS", "LLLLLSDDD", "LDDLLDDL", "ULLULLDD", "DLLLLLLDD", "ULLLLULLL", "LLDLLDDD", "UULLLL", "ULLLULLLL", "LLLLLLSLLL", "LLLDDLLLLL", "UUDDDDDDDD", "LLLLLLU", "DDDDDDLLLLLLLLL", "ULLLDDDDDDDD", "DDLDL", "DLLDD", "LDLDDL", "LDDLDDL", "LLLLLLDDDDDDDDDD", "LLLLLLSLLLLLL", "DDDLD", "DDDDDDLD", "DDLLLLLDDDD", "LDDLDDDD", "UUDDDDDDD", "DUUUUUUU", "LDDL", "DDDUUU", "ULULLLLL", "LDLDLDD", "LLLDDDDDDDDDDD", "DLLDDLLD", "UUUUUUUDDD", "LLLDLDD", "DDDDLLLDD", "LLLLLDDDL", "ULLLLLDL", "ULULULUL", "LLLLLLLDDL", "LDDLLLDD", "ULLLLLLLLLLD", "DDDULLLL", "LLLSLL", "LLLLLLSL", "LLLDDDLLLDDD", "LLLDDDLLLL", "LLLLDDDLLL", "LDLLLDDD", "LLLSLLLLL", "LLLLDDDDL", "LLLLDDDLL", "LDDDL", "LLLLLLULLLLLLL", "DDDDDDDDDDLLLLLL", "LLLLLLLSDD", "UDDDDU", "LLLDLDDD", "LLLLLSLLLLLL", "LLDDLDD", "DLDDL", "LDLLLDD", "LLLLLLDDLLL", "DDLDLLL", "DDDDDDDDDDDU", "LLDDLDL", "DLLDLLD", "LDDDDLDDDD", "LLLLLLSLLLLL", "DDDDDDDDDLLLLLL", "UUUUUUUDDDD", "ULDDDDD", "LLLDLLLDDD", "DDLLDDL", "ULLLLLDDDDD", "LLDDDLLD", "UUUULLLL", "ULLLLLUU", "DDDDDDDLLLLLLL", "LLLLDDDLLLL", "DLDDLD", "DDDDLLDDDD", "DDSDDSDD", "ULLDLLLL", "LDDLDDLD", "DDDDDDDDUUU", "DLLDDLL", "DDDDDDDDDDDDDDDDDD", "LLLLLLLLLLLLLLLDDD", "ULLLU", "LLLLLLDLD", "UUDDDDUU", "LLLLLDDDDL", "LLLLLLLLLLLLLLLDDDD", "LLLSDD", "LLLLLLSLLLL", "LLLLLLLLLDDDDDDD", "LSLLLLL", "LDDDLD", "ULLLLDDDDDDDD", "DDDDLLLLLDDDD", "DDDDDDDDDU", "LLLLSDDDD", "LDDLDDLL", "ULLLLUDD", "LDLLDDDD", "ULLULLLD", "LLLDDDDDDLLL", "LLDDDDDL", "ULLDDLLL", "DDDLDL", "LLLLLSL", "LDLLDLD", "LDLLDLDD", "LDLDLLD", "DLDLDD", "DDDDLLLLLLLLL", "LLLLDDDDLL", "LLLDLLLLD", "DDLLDLL", "DDLLLLLLDDDD", "ULLDD", "UUUDDDDDDDD", "ULULLLL", "DDLDDLLL", "LDLDLLDD", "ULLLULLD", "DLLDLLDLL", "DDUUUUUU", "LDDLLDD", "ULULDDDD", "LLLLLLLLDLL", "LLLLSLL", "LLLLDLLLLLL", "DDLLLLLLLLLL", "LLDLLDLLD", "LLLLLSDDDD", "LLLLLLLLLDL", "DLDLDLDLD", "LLLLLSD", "LLLLLDDLLLL", "DDDDDDDDDDDDLLL", "DLDL", "LLLLDDLLLLL", "LLLLLLLDLLL", "LLSLLLLL", "DDLLLLLLD", "DDLDDDDD", "LDDLLLLLL", "LLDDDDLLL", "DLDDDL", "LLLLLDDLLLLL", "LLLLLLLLLLLLLLLLLDD", "LLLLLLLLLLLDDDDD", "LLLLLLLSLLLLLL", "LDDLLDL", "LLLLLLUU", "DULLLLLD", "UUUUDDDDDD", "DLLD", "UUDDD", "LLLLLLLDLLLL", "LLLLLLLLLDDDDDDDD", "LDLLDDL", "DDULLLL", "ULLLDL", "DLLLDLLLDLLL", "LLLLDDDDLLL", "LDLDLDDD", "LLDLDDDD", "DLDDD", "DDDDDDDDDDU", "LLUULL", "LLLLLLSDDD", "UULLDDDD", "LLLLUU", "LDLDDLDL", "DDDLLLDL", "LLLLLLLLSDD", "DDDLDLLL", "UULLLLL", "ULLLLLLLLLLDDDD", "DDDDDDDDUL", "ULLLDDDLLLL", "LLLSDDD", "DDLDDLL", "DDDSDDD", "LLLULL", "DDDDUL", "DDDDDLLLLLLL", "UUUUDUUU", "DLDLDLL", "LDLDDLDD", "LLLLLLLLLLLDDDDDD", "DDDDULLLL", "ULDLLLLL", "DDLDLD", "DDDDDDLLLLLLLLLL", "DDDDDLDD", "DDDLLLLLDD", "LDLDLDDL", "ULDLDD", "LLLLLLDDDL", "DLLLLDLLL", "LLLUUU", "LLLLLDDDLL", "DDLLDLLD", "DLLLDDDL", "DDDDDDDDDDDDLLLL", "DLLLDDL", "LLDDLDDL", "ULLLULLLLL", "DLDLLLD", "ULLDLL", "DLDLLLDD", "LSLLLLLL", "DLLDDDLL", "DLLLLDLLLL", "DDDLLDLL", "ULLDDDDDDD", "LLLLLLLSD", "LLLLUL", "DLLDLLDD", "LLLSLLLLLL", "UDLLLL", "LLLLLLSLLLLLLL", "UUULLLDD", "DDLDDLD", "LLLLLLLLLLLLLLLLD", "DDDDDDDS", "LULLLL", "LLLLLLSDDDD", "DDUUUUU", "UDDDDDDDDD", "LLSLLLL", "DDDDLLLLDD", "LLLLLLLSLLLLL", "DDDLLLLDD", "LDDLLLD", "LLLLDLLLD", "LLLLULLL", "DDULLL", "DDSULL", "LDDDLLLD", "LDDDDLDD", "DDDDDDDDDDDDLL", "LLLLLLLULLLLL", "ULLLLLLLLLDDDD", "UUUUUDUU", "DDDDDLD", "ULLDDDDDDDD", "LLLLLLLDDDDDDDDD", "ULLLLULLLLL", "DDLLLDL", "LLLLLSLLLLLLL", "UUUDUUUU", "DDUUUU", "DLLLLLLLLLLL", "LDDLD", "LLLLLLULLLL", "LLDLDLDD", "UULLLLDD", "ULUL", "ULLLLUUU", "ULLLDDDDDDD", "LDDDLDLL", "DLDDLDLL", "LDLDDDDD", "LLDDDDDDL", "ULLLLLUD", "DDDDLLLLLLDDDD", "UULLLDDD", "ULLLLLDDDDDDDD", "DLLLDLLLL", "LDDLLDLD", "DLLLLLLDL", "LLDDLLLLLL", "DLDDDLLL", "LLLLLULL", "DDDDDDDUU", "DDDLLLDDDLLL", "UUDDDUU", "LDDLDLDL", "LDDDDDLL", "DDDDDDDDDDDDDDDDDDDD", "UULLUU", "LLDDDLDD", "UUU", "LULULU", "UUUDLLLL", "UDDDUU", "DLLLDDLD", "DDLLDLDL", "DDDUUUUU", "LDLLDDDL", "DLDDDDDD", "SLLLLL", "LLLDLLLLLLL", "UDDDDDDDDL", "LDLLDDLD", "UULLL", "LLDDDLDL", "LLLLLDLLD", "ULLLDLL", "DDLDDLDDDDL", "LLLLU", "UUUUUUDU", "ULLLLLULLLL", "DDLDDDDL", "ULLLLLULLLLL", "DLLDDLDL", "DLLLLLLLLLD", "LLLLLLLSLLLL", "UDDDDDDDDDD", "ULLLLLULLL", "LDDLLDDD", "DLLLDLD", "DDDDDUU", "DDLDDLDDDD", "UUUUUUUUUD", "DLDLLDL", "LLDDDDDDDDLL", "LLDLLLLDL", "LLLLLLLLLLLLLLLLLLLLLLL", "DLLDDLD", "DLDDLLL", "DLDLDDLL", "DDDDULL", "LDDDLLDDD", "LLDDLDLD", "LLLLLLLLLLLLLLLLDDDD", "DDLLLLDDD", "LDLDDDLL", "LLLDDDDLLLL", "DLLDLDL", "DLDLDLLD", "LDLLLLDLL", "LLULLLLL", "UUUUULLL", "UUUUUUUUDDDD", "ULLLLDDDDDDD", "LDDDDDDDDDL", "UDUDUD", "DUUUUU", "LLLLSLLLLLLL", "UDDDD", "DLDDLLDL", "DDLDLDLL", "ULLULULL", "DDDLDDL", "DLLDLDLD", "LLDLDDL", "LLULLL", "UDLDLDLD", "UUULLLL", "LLLLLLLULLLLLL", "DLDDLLLD", "ULLLLDL", "LLDDDDDDDDDDD", "LLDLDDLD", "LLLLLLSLL", "DDLDLLDL", "DDLLLDLD", "DDL", "LLDLDLD", "LDDDDDDDDDDL", "LDDLDLLD", "DLLDDDD", "DDLDLLLD", "ULLDLLL", "DLLLDLDD", "LDLDD", "UDDDDDDDL", "LLLLLLDDLLLL", "DDDDDUUU", "LDDLLLLLLL", "UDUDUDUD", "DDDLDLL", "DLDLLDDL", "LLLLLLSLLLLLLLL", "DLLDLDDL", "ULLULLD", "LLLLDLLDD", "LDDLDLDD", "ULLLLLLLLLLDD", "ULLLLLLDDDDDD", "ULLLLLLLLLLLLL", "ULLSDD", "LDDDLDD", "UDLLLLL", "DLDDDDD", "LLLLLLLLLLDDDDDDDD", "LUUUUU", "DDU", "LULULL", "LLLLLLLLLLLLLLLLLLLLLLLL", "LLLLLLLSLLLLLLL", "LDLDDLLD", "LLLLLLLSLL", "DLDLLDLD", "DLDLLLLLL", "UUUUUUUUUDD", "LDDDLLDL", "UUUUUUUUUUUUU", "DDUUU", "LDLLLLLLD", "LDLDDDD", "DDDDLLDL", "DSDSDDD", "DLDDLLD", "LLLDDDLLLD", "LDDLDDD", "LLLLLLLDLD", "LLULUL", "LLDDLDDD", "ULLLLLULL", "LLLLDDLLLLDD", "LDLDDLL", "LLLDDLLDD", "DLDLDLDD", "LLLLLLLLLSDD", "LLDDDDDLL", "DDDDDLLD", "LLLLLDLDL", "LLLLLLDLLLLL", "UUDUUUUU", "LLLLLLLLSLLLLLL", "LLLLLLUUUUUU", "SSSSSS", "LLLLLLLLLLLLDDDDDD", "DDULL", "LLLLLLLLLLSLLLLL", "DDDDDS", "LLDLDDD", "DLLLLLDLL", "ULLLLUD", "DUUUU", "LLLLLLLLSL", "DLDDLDDL", "LLLLLLLLLLLSLLLL", "LLLLLDDDLLL", "ULDLLL", "ULLLLLLULLLL", "UUUDDDDDDD", "ULLLULLU", "UULLLU", "ULLLULUL", "LDDLDLL", "DUUUUUU", "DDDDLDDDDL", "LLLLLLLLSLLLLL", "DDDLLDL", "LLLLLLLLLDLL", "ULLLLLLDDDDD", "LLLLLLLSLLL", "LLLLLLLLLSLLL", "UDUUUUUU", "LDLDLLLLL", "DDDDDDUUUU", "DULLLULL", "DDDDDDULLL", "LLDLLLLLLLL", "ULLULLUL", "LLDDLLLDD", "LLLLUD", "UUUD", "ULLDDULL", "ULLLLLLLLLDDD", "LLLLLLDDDDL", "DDDDDDDLLLLLLLL", "UULLLLLD", "LDLLDLLLL", "LLLULLLL", "LLDLLLLDLL", "DDLDDLDDLDDL", "LLLLLSLLLLLLLL", "LDLLDDD", "ULULU", "LULLUL", "LLLULU", "LLLLLLLLLLLSLLLLL", "DDDDDDLU", "UULUUL", "LLDDLLDDLLDD", "LLLLLLLSL", "DDLDDLDL", "LLLLLLUD", "UUUUUULL", "UDDDUDDD", "LLLDDDLLLLLL", "ULLLUD", "ULLLDDLL", "LDDDDDDDDDDDD", "UDDDDDDDDDDD", "ULULL", "ULLLLDDL", "DDLLDDDL", "DDDDLDDL", "SLLLLLL", "LLLLLLLDDLL", "DDDDLLLLLDD", "ULULULU", "SLLLLLLL", "LLLLDLLDL", "UUDDUU", "DDLLLLLLLLLDD", "UUUULU", "UUUDDUUU", "UUULUU", "LLUULU", "DLLDLLLLL", "LLUUUU", "ULLULULU", "ULUUUULL", "DDLDDDLL", "LLDLLLLLD", "ULLLDULL", "DDDDLLLLLLLLLL", "ULLULLLU", "LLLLLLLLLLSLLLL", "DULLLLLLL", "ULLUDDDD", "LLLLLDDDDLLLLL", "LLLLDDDDDDDDDDDD", "DDDDU", "DDDULL", "DDULLLDD", "LLLLLLLLSLLLL", "LLDLDDDL", "LLLDLDLLL", "LLLLLLLSDDDD", "LLDDDLD", "UUUUDDDDD", "DSDSDSDDD", "DDDDULLLLL", "DDLDDLLD", "LLLLLLLULLLLLLL", "ULLULLLLL", "ULULLLUL", "LDLLLLLLLLL", "UUUULL", "LLLDLLDLL", "LDLLLLLDL", "ULULULLL", "DDDLLLLLLLDDD", "DDUUUDD", "LLLLLLLLULLLLL", "LDDLDDLDDLDD", "ULLUULLU", "DLLLLLLU", "ULULLLLU", "LDDLDLD", "LLLUDD", "UULULL", "LLLLLLLLLLLLLLLLDDD", "UUUUUDDDDDD", "LLDLLLDLL", "DDDLDDLL", "DDDUUUU", "LDDDLLD", "LLLLLLULLLLLLLL", "DDDDDDULL", "LLLLLLLLSLLL", "UUUUUUUUDDD", "LDLDDLD", "ULLLUULL", "ULULLULL", "LLLLLLLLDLLL", "LLLLLLLLLLSLLL", "LLLLLLLDDLLL", "DDDDDDDDDDS", "LLLLLLLLLLLLDDDDD", "UDDDDDDDDU", "LLLLLLLLLLDL", "ULLLLULU", "LLUUUL", "DUUUUUUD", "LUULUU", "LLLLLLLLLLLSLLL", "ULULUUUL", "LLLLLLLLLLLLSLLL", "LDDDDDDLL", "UUULLLDDD", "ULLLULLLLLL", "DDLLDDLD", "ULULLULU", "LLLLLLLSDDD", "LLLLLLLLLSLLLL", "DDLLDLD", "ULLUL", "LLLLLLLLLLLLLLLLLLDD", "LLLLLLLLLSLLLLLL", "DUDLUDUL", "DLLLLDDDD", "DDLDLLDD", "UUULUL", "LLLLLLLLDDL", "LLLLLLLLLSLLLLL", "ULLUUUUU", "SSSSS", "UULLLULL", "DLDLLDDD", "ULLULLUU", "ULULUULU", "LULUUU", "LLLLLLLLSLLLLLLL", "LLLLLLLSLLLLLLLL", "LLLLLUUU", "LLLDDLLLLLL", "ULLLLUL", "DDUUUUDD", "DDLDDDL", "LDDLDDLDDDD", "LLLLUUUU", "UULLLLLU", "LLLULLL", "ULULLLUU", "ULLUULLL", "DDDDDDDDDDDDDDL", "LUULLU", "LLLDLLLLLD", "LLDDLLDDLL", "LDDLDDLDDL", "LLDDDLLLL", "LLLDLLLDL", "LUUULL", "LUULLL", "DLLDLDD", "UULLUUUL", "ULULLUUL", "LDLDLDLDLDL", "DDLDLDDL", "ULUUULLL", "UULLULLL", "ULLLUUUU", "DDUU", "LLLDDDLLLLL", "LLLLLLUUUUUUU", "UUUDUUU", "LLULUU", "LLLLLLLLLLLSDD", "ULLLLUUL", "ULUULULU", "LLLUUL", "LLLLLDLLLLLL", "LULLLLLL", "UUDUUU", "DDDDLDLL", "LLSLLLLLL", "LLLLDDDLLLLDDD", "UUUULULL", "UUULLUUL", "LLLLLLLLLLLLSLLLLL", "LULLL", "DDDLLLDDDD", "DDDDDDDDUUUU", "LLLLDLDLL", "LSLLL", "DLDLDDDL", "LDDDLLLLL", "LDDDDDDDDDDDL", "UULLLLUL", "UULUUU", "UUULLLLU", "UULULU", "ULUULULL", "UUUUULUU", "UUUDU", "ULUULUUL", "UUULLULL", "ULLUUULU", "ULULULLU", "UULLLLUU", "UUDUU", "DULULLLL", "UULLLUUU", "DDDDLDL", "ULLLULUU", "UUULLLLD", "LLLLLLLDLLLLLL", "LLLLLLLLDLLLLLL", "DDDLDLLD", "DDLLLLLLLD", "LLLLLLLLSLLLLLLLL", "LLDLLDLLL", "UUULULLL", "LLLLLLDDDLLL", "LLLDLLLDD", "UUULUULL", "ULLUULUL", "UULUUULL", "UULLULLU", "LSLLLLLLL", "LLLLSLLLLLLLL", "DLLLLLDLLL", "LDDDLLDDLLL", "LLLSLLLLLLL", "LDLLLDLLL", "DLLLDLLLLL", "LLLLSD", "LLLLLDDDDLL", "LLDDDLLDDD", "LLLLLLDLDL", "ULDDLLLL", "LLLLDDLLLLLL", "LLDLLLLLDL", "UDDUDD", "DDLLDLDD", "LLLLLLDDS", "UUUDDLLL", "ULUULUUU", "DLLDDDDD", "DDUUDD", "UULLULUU", "DDLUL", "DDDDDDDDDDDLLLLLL", "LUUULU", "DULLU", "DULUL", "LLLLLLLLDLLLL", "LLLDDLLLD", "DDDDDDDDULLL", "DDDULLL", "DDDDDDUD", "UULULLLL", "ULLLLLLLU", "ULLULUUL", "ULLUUULL", "LLLUUD", "LLLLLLDLLD", "LLLLLLDDDLL", "UUUUUUUUUUUUUU", "LDDDLDDL", "UDDLLLLL", "UULLLUUL", "DDDLLDDDD", "DDUUL", "ULULDD", "UULULULU", "UDUUU", "DDLLLLLLLDDDD", "ULUUUUUL", "DLDDLLDD", "LSLLDDDD", "DDDDDDDDDDDDDDDDD", "LLULL", "DULLULLL", "LULLLU", "LLLLLLLLLLLSLLLLLL", "LLLLLLLULLLL", "UUUUUL", "ULDDLL", "DLLLLLLLDD", "UULLUULU", "UDDDUUDD", "LLLLLLLLULLLLLL", "DLDDLDL", "UUUUUUDDDDDD", "DDLLU", "DDDLLLLLLLLLL", "ULLLLSDD", "LLLLLLLLU", "LLLLLLLLLLLLLLLLLD", "DDDDDDDDDDDS", "UUULLULU", "LLLLDLLLLLLL", "DDDLLDDL", "DDDDDDULLLL", "LLDLLLDLLL", "DLDLDDD", "LLLLLLLLSD", "UUUUUUUL", "DDDDDLDL", "LLLUL", "UUUUUULU", "DULLLLUL", "LLLLLUDD", "LSLLLLLLLL", "DLDLLDD", "ULLLLLDDDDDDD", "UUULULUL", "LLUUL", "UULULLUL", "LLUUUD", "UUUULUUL", "ULLDULLL", "ULDDDDDDDDD", "DDLLDDLLDD", "ULLUULUU", "ULUULLUL", "ULUUULLU", "UUULUUUU", "UUUUDU", "DDDDLLLLD", "UULUUUUU", "ULULULUU", "DLDLDDL", "LLLLLLULLLLDD", "ULULULDD", "DDDLLLLLLLLDDD", "DDUULLLL", "ULLLULLLDD", "LLLLLDLLLLLD", "ULLLUUUL", "DDLDLDD", "ULUULLUU", "DLLUL", "UUULLLUU", "DDDDSDD", "DDLLDDDDDD", "DDDDDDLLLLDD", "LLLLLLLLLLSLLLLLL", "UUULLLUL", "DDDDDDDUL", "UUULULUU", "LLLLLDDDDLLL", "DLLUU", "DLLLLLLLLLLD", "ULLLLLSD", "LLLLLLLLLLLLSLLLL", "UDDDDUDD", "LLLLLLLLULLLLLLL", "DDLDLLD", "DDDDLLLDDD", "UUUDUU", "ULULUULL", "DDDUU", "LLLLLLLDLLLLLLL", "LUULUL", "UULLUUUU", "DDDDDDLLLLLDD", "DLLULLLL", "DDLDLDLD", "DDDLDDLD", "ULLLULDD", "ULDLLLL", "DDDDUDDD", "LDDLDDDL", "DDLDLDL", "ULLLLLSDD", "UDDDDDU", "ULULLUUU", "LDLDLDLDLDLDLD", "LLLLLLLLLLLLSDD", "DLLLDLLLD", "DLDDDLDD", "ULUUUULU", "UUUUDDDDDDDD", "UUUUUDDDDD", "DUUULLLL", "ULLULUUU", "LDLLLLDLLL", "LLLLLLLLLLLDDDDDDDD", "ULLLLULLLLLL", "LLULU", "DLUULLUL", "LLLLLLULLLLLDD", "UUUUULUL", "ULLLUDDD", "LLLLDLDLLL", "DDUDDUDD", "DULLLULU", "DLLLLLDDDD", "LLLLLDDDDLLLL", "UUULL", "DLLDDLDD", "UUULUULU", "DDDDDDDDDDDDDL", "ULLLUULU", "UULUULLU", "DUULLUUL", "ULLLLLLLDDDDDD", "ULUULLLU", "DLLULULL", "LUULL", "DLDDDLLD", "LLLLLLLLLLSDD", "DDLU", "DULULUUL", "DLDDLDD", "UULLULUL", "DDLDDDLD", "LLLLDDDDUU", "DLULU", "ULUUUUUU", "LLLLLLLLDDLL", "LLLLDLLLDL", "DDUL", "ULULUUUU", "ULUULLLL", "UDDUDDUDD", "LLDDDDLD", "LLULLU", "UDUUUU", "UUUULLUU", "LLLLLLDDDDLLLLLL", "DDDLDLDL", "ULUUULUL", "UUULULLU", "UUDDUUDD", "ULLLLLDDS", "DLLDDDL", "DDDDDDLLLLLLDD", "UULUULLL", "UULULULL", "DLLLULLU", "ULULLLLD", "DULLLLLU", "LLDLDLLLL", "DLDDDDL", "ULULUD", "UUUULLLU", "UUUULLUL", "UUULLUUU", "DUUULLUL", "DUUULULU", "UULLUULL", "DDDDDDLDD", "DDDDUUUUU", "DDDLLLLLD", "LLLLLLUL", "DLLLLLLLDL", "LLDLLLLDD", "DULULLLU", "DDDDLLDDD", "UULUUUUL", "DULULULU", "DDDDLLLLLLLDDDD", "LLDLLLLLLD", "LLLLLDLDD", "UULULLLU", "LLLDDDDLLLLLL", "LLLLLLDDDDDDDDDDD", "DLDLDDDD", "LLLLLLLLLLLLLLLLLDDDD", "DDDDLDLD", "LLDDDDLLLL", "LLLLLLLDDDL", "DDLD", "LLLUU", "DDDLDLD", "DDULU", "DUULLLUL", "UUUUULLU", "DLLDLDDD", "DDLDLDDD", "ULLUUUUL", "DLLUUULU", "ULLU", "DUULLLLL", "UULUULUL", "UULULLUU", "LLLLDU", "DLLUULUU", "DDDDDDDDDLLLLLLL", "DLLLLLUU", "ULUUULUU", "DDDDDDDUUU", "ULDDD", "LLUUU", "DLDLDLDLDLD", "DDLLLDDLL", "LLDDDDDDDLL", "DDDLLDLD", "ULLDULLD", "DLLLULLL", "UULLLULU", "DULULULL", "UULUULUU", "DDLLLLLDDD", "DULULLUL", "UDDUDDDD", "UUUULULU", "DDDDLLLLLLDD", "DUULU", "DLLLLULU", "DDULLLLLL", "DLLLULUU", "DDDUDDDD", "LLLLLDLLDL", "UUDDDDLL", "DLDLLLLLLL", "DDLLLDDLLL", "LLLLLSLLLLLLLLL", "LLLLLLLLLLLLSLLLLLL", "ULLLUDD", "LLLDULLL", "DUUUL", "DDDDDDSS", "UULULUUL", "LLLDDDDDDDDLLL", "DUULLLLU", "LLDLLDLLLL", "DUULLULU", "LLLLLUU", "DDLDDDDDD", "DUUULLUU", "DDLUU", "LLLLDLLDLL", "DLDDDLL", "UUUULUUU", "LLDLDLLLLL", "DLLLU", "LLLLLLLDLLLLLLLL", "LLLLLDLLLD", "LLULLD", "LDLLLLDDL", "DDDLDLDD", "UUULLU", "DDDDDDDDDS", "DUULULUU", "UDDUDDD", "ULLLUUU", "DLULUUUL", "UDDDDL", "DUUUULLU", "LLLLLLLLLDDL", "LLLLLLLLLLSLLLLLLL", "LLLUUUDD", "LDLLLDLLLL", "DLDDDLD", "LDDDDLD", "DULUUULL", "DLLUUULL", "DULUULLU", "UULUUULU", "LLLLLDDS", "ULLLLLDDDLLLL", "ULLDL", "UULLLD", "LLLDDDDLLLLL", "DULLLUUL", "LLLDLLDLLL", "DUULULLL", "UULLUL", "DDDDLLLLLLLLLLL", "ULLLLLLDDDDDDDD", "ULLLLUU", "DLUUULUL", "DULUULLL", "DDDDDDDLDD", "DLLULLLU", "ULLLLULD", "ULLDLLLD", "DULLULUL", "DLLDDDDL", "LUUUUL", "DUULD", "DLUUUULL", "DUUULLLU", "LLLLLLLLLLLLLSLLLLL", "LUUUU", "UULLLDD", "DDULLLLDD", "DLLULL", "UULLDD", "DSULL", "DLLLUULL", "UULULUUU", "ULUUL", "DUUUULUU", "DLULLULL", "UDLLLLLD", "DDLDLLLLL", "UULUL", "ULLLLLLULLL", "LLLLLLDS", "UDDDDDDDU", "LLLLLLLLLDLLL", "DLLUULLL", "LLLDDDDDDDDDDDD", "DLLLLLDDD", "DDDDDDDDDDDDDDDL", "ULUDDD", "DULLUULL", "LLLLLUD", "ULLLLLLLLLLLLLL", "LDDDLDLD", "UUUUDUU", "UDDDDDUD", "DLULLLLU", "LLLDLLDDD", "LLLLLLLLLLLLLLLLLDDD", "ULDDDDLL", "DULLUULU", "DUUUULUL", "LDLLLLLLLD", "LLDLLDDDD", "DDLLDDLLDDLL", "DLULULLL", "DULUULUL", "DULLLU", "DLLLULUL", "DUULLLUU", "LULLUU", "DUULLULL", "DLDDDDLL", "LLSLLLLLLL", "DDDDDDULLLLL", "ULLULLLLLL", "DULUU", "DULLULLU", "LDDDDLLD", "ULULLLDD", "DLLLLLUL", "DUDUDUDU", "LLLLLLDLLLLLL", "ULDDULDD", "DULLUUUL", "LLLLLDDDLLLL", "ULDULL", "LLLLLDDDLLLLL", "DLLLUUUU", "LUDDDDDD", "ULDULD", "UDLLLLDD", "ULLLDLLLL", "DUUULUUU", "ULLD", "UUUDUUUD", "ULLLLLLS", "DUULULUL", "DUULUUUL", "UDDUDDUD", "DLDDDLDL", "UUUUUUUUUDDD", "LLDDDDDDLLL", "DLDDLDDD", "LLLLLLLLLLS", "DDULLDD", "DULULLUU", "DUULULLU", "UUDDUUUU", "LLLLLLLLLLLDL", "DDDDDDLLLLLLLLLLL", "ULLLLUUD", "DLDLLLLLD", "UUUDDDU", "DULUULUU", "LLLLLLLLLLLLLDDDDDD", "ULLLULLLD", "DLLUULLU", "LULUUL", "DUUULUUL", "UUUDDUU", "LLLDLLLDLL", "DUUUUUUL", "DUULL", "LDDLLLDDL", "DDLLLLLLLLLLL", "UUUUDDUU", "DDDDDDDDLLLLLLLLL", "ULLUU", "LLLLULLD", "UUUDDDDU", "LLLLLLLLLSLL", "DDSDDSDDDDS", "DLLUUUUL", "UULUU", "DLUUULLL", "LLLLLLLLDLLLLLLL", "DULULUUU", "DLLDDDLD", "DLUUULUU", "DDDDDDLLD", "DULULU", "ULL", "ULUUU", "ULLDDLL", "DULUUULU", "DUUUUULU", "UUUUUDDU", "LLLLULL", "LLLLDDDDDDLLLL", "UUDD", "DUULUULL", "UUUUL", "DLLLDDLLL", "LLLLLLLLLLLLLDDDDD", "ULULLLD", "ULLLLLDLL", "DDDDDUDD", "LLLLLLDDDDLLL", "DLULLLLL", "DLUULULL", "ULLLLLLLLLLLDD", "DULLLUUU", "LLLDLDLLLL", "LLLLLDLLDD", "ULLLLLLDS", "DULLLLD", "LUUUUUUU", "ULLLLLLLLLLDDD", "ULLUDD", "ULLLLLLLLLLLD", "LLLLUULL", "DLULUULU", "DDDDSDDDD", "DDDUUDDD", "LLLLLLLLLLLLLSLLLL", "DLLLLUUU", "DLLULLUU", "DUUUULLL", "DUULUULU", "LLDDDLLLLL", "LLLDDDLLLLLLLL", "DDDDDDLLLDD", "DUUULULL", "DLDULU", "DLUUULLU", "DULLUUUU", "DUUDU", "LLLLLLLLLLLLSLLLLLLL", "LULULULU", "LLLLLDDLD", "DLUULLLL", "DDDDUUDD", "LLLLLLLLLLSLL", "LULLU", "DLLULLUL", "DULUUUUL", "DDSDDSDDS", "ULLLLLULLLLLDDDD", "ULULUDDD", "ULLLLLUDD", "LDLDDDL", "DUULUUUU", "LLLDDDDDDDLLL", "LLLLLLLLLLLLDDDDDDDD", "DLDDLDLD", "LLLDDDDDLLL", "DUULLUUU", "UDUDDDDD", "LUUUL", "LLLLUDDD", "DULUUUUU", "ULUDDDD", "LDLLDLLDL", "UUULUUUL", "DLDD", "LULUULUL", "LULUL", "DUDUUUUU", "DLLLLULL", "LLLLLLDDLLLLLL", "DDDUDDD", "DLLLLLLDLL", "LLLLLLLLLLLLDL", "LUUULLUU", "DDLLLLLLLLLLDD", "LLLLLLLLLSLLLLLLL", "UDDDDDUU", "LLLLDLLDDDD", "DULLULUU", "LLLLLLSS", "DULLLLUU", "LLLLDDDLLLLL", "DLUULUUU", "LLLLLLLLLLLSLLLLLLL", "UDLDLD", "DUDDDDDD", "UUUDDDLL", "LDLLDLLLLL", "LLLDDDLLLLLLL", "LDLDLLLLLL", "DLULLLUU", "LLLLSS", "LLLLLLLLSDDD", "UUUUUUUUUUUUUUU", "LLLLLLDDLLLLL", "UUDUUUU", "DLULLUUU", "LLLDLLDDDD", "SLLLLLS", "ULULULUD", "LLLLLLDDDDLL", "DDDDLLLLDDD", "LLLLUUU", "UUUDULLL", "DULULL", "LLLLLLLDLLLLL", "LLLUULLL", "LLLLLLULLLLLLLLL", "LLLLLLLLSLL", "UUUUUUUUUUDD", "LLLULLLD", "LDLDDDDL", "LLUUUULL", "ULLDDDLL", "LDLDLDLLL", "LLLLLLLLLDLLLL", "ULULDDD", "LLLLLDLDLL", "LLLLLLLLLLDLLLL", "UDDUDDU", "DLLUUL", "ULLLULLLLLLL", "DDDDDULL", "LLLLLLLLLLLLLSDD", "DLLLLUUL", "LUULU", "DLUUUUUL", "DDDULLLLL", "LLLLLLLLDDDL", "DUUUUULL", "DLUUL", "LLLLLLUUUUUUUU", "LLDDLLDDD", "ULDDDDDDDDDD", "LLLLLLDU", "DLULUULL", "DDDUL", "SLLLLLLLL", "LLUUUUUU", "DLUULLUU", "LLLLLLSLLLLLLLLL", "LLSLLLLLLLL", "UUUDDDLD", "LLLSLLLLLLLL", "LLLLSLLLLLLLLL", "DDUDDDDD", "DLLDLLLLLL", "LULLLLLLDD", "DDLLDDLLL", "LDDLLLLDL", "LLLLLLLDDDLL", "DLLUUUUU", "LLLDLLLLDL", "ULLLLDLD", "DLLLUULU", "LLLLDDDU", "LLLLLLLLLSD", "DLUUUULU", "DLLLLDDLL", "LULLLLLU", "DLLUULUL", "UULLU", "LLLLLLLLLLLSL", "LDLDLDLDLDLDLDLD", "DLLLUL", "ULUUUD", "DLDDDDDL", "ULLLDLLD", "LLLDLLLDLLLD", "DLDLDDLD", "LLLDDDDLLLLLLLL", "LLLLLDDU", "LLLLLLLLSDDDD", "LLDDLLLLD", "DLULLULU", "LLLULLLU", "LLLU", "ULLLLLDS", "LLLLLLLLDLLLLLLLL", "UULLLLD", "DLDUU", "DLULUUUU", "UUDDDDDU", "LLULUD", "LLLLLLULLLDD", "LDLLLLLDLL", "UUUULLLD", "LLLLLLLLLLLLLLLLLLD", "DDUDDU", "DUUUUD", "DLLULUUU", "DDUDDDD", "LSSL", "UULDUU", "LLDDDDLLDDDD", "UDDDDUU", "DDDDDDDDULLLL", "UUUUDDDDDDD", "LLULLLLU", "DLULLUUL", "USLLLLLDDDD", "LLLLLLLDS", "LLLLLLLLDLLLLL", "LLLLLLLLLLDLL", "ULLLLLLLDDDDD", "LLLLLLLLLLSL", "LDDDDLDL", "UUUULLL", "LLLSL", "LLLLDDDDDDDDLLLL", "ULLLLLS", "ULLLLDUL", "DDDUDDDU", "LLUDLU", "UUUDUDD", "DDDDLLLLLLLLDDDD", "DDLLLLLU", "DLLLLLLLLLLLL", "LUULLLUU", "LLULLLL", "UUULU", "UUDDUUU", "LLLDDDDLLLLLLL", "DDDLLLLLLDD", "LLLDLLLLDD", "DULLD", "DLULLL", "DUUUDUUU", "LLDLLLDDDD", "LLLLLLLLLLLLLLLLLLLDD", "LLLLLLLDDDDDDDDDD", "LDLLLLLDD", "LLUULLLL", "UUULLLD", "UUUUUDDDDDDDD", "LDLDLDLDLL", "DDDDDDUUUUU", "DDDDDDDLD", "UDLLL", "UUDDLLLL", "UUDDDDU", "LULLLULL", "DDDDDDDLU", "DLULLU", "LLLLLLLLDDLLL", "LLLLULUU", "DLULLLUL", "LLLDDLLLLD", "DLULL", "DLDLDLDLL", "LLLLLLLLLLLLLLLLLLLLLLLLLL", "DULDL", "ULLLUDDDD", "ULLLDU", "DDDLLLLDDDD", "DULUUU", "DDDUUUDD", "ULLLLDDU", "SDDDDDDS", "LLLUD", "DUULLU", "DLLULUUL", "LDDDDLLLL", "LLLLLLLUUUUUU", "LLLLLLLLLLDLLL", "LDDDDDLD", "LDLLLLLLDL", "DULLUL", "UDULLLLL", "DDUDD", "DLUULUUL", "LLLLDDDDU", "DUUUUDUU", "LLLLDDDDLLLLL", "LLLUUULL", "LLLLLLLLULLLL", "DUUDUUUU", "LDDDLDDDD", "LLLLLLLLLLLSLL", "ULDLLLLU", "DLUULULU", "LDDDLDL", "ULLLLLDU", "LUUUUULL", "LLDULL", "LLLLULLLL"]; export const blacklistedSubstrings = ["12345678", "password", "23456789", "11198", "land", "blue", "04199", "07199", "02199", "06199", "08199", "angel", "10199", "09199", "12199", "11199", "01197", "05197", "07197", "a199", "04197", "03197", "10197", "08197", "123123", "12197", "06197", "master", "dragon", "09197", "fish", "02197", "black", "11197", "a200", "2112", "fire", "mike", "baby", "pussy", "line", "test", "mark", "cher", "wood", "mama", "bear", "cool", "ling", "anne", "fred", "illa", "a198", "anti", "alle", "marc", "monkey", "life", "man1", "dick", "ness", "good", "daniel", "sexy", "o123", "time", "assi", "gold", "shan", "shadow", "rain", "ters", "alli", "ford", "play", "mont", "anta", "mine", "qazwsx", "ache", "stra", "erry", "michael", "dima", "green", "sher", "nick", "shar", "wolf", "ring", "killer", "suck", "tina", "robert", "01196", "even", "elin", "aris", "2211", "dark", "bird", "jordan", "paul", "1108", "scar", "ones", "lock", "123321", "0909", "arri", "mustang", "rose", "shit", "asta", "money", "121212", "0505", "arch", "03196", "football", "stro", "hill", "01019", "letmein", "dman", "chin", "10219", "04196", "05196", "amil", "pant", "baseball", "porn", "david", "james", "onic", "eron", "10419", "mini", "stal", "ison", "abc123", "lover", "ander", "alen", "30319", "t123", "erin", "ina1", "vers", "0303", "ings", "martin", "mega", "olly", "ante", "hello", "11119", "0108", "90519", "00119", "08196", "21219", "shka", "10196", "hunter", "30119", "40419", "00319", "30219", "02196", "yboy", "666666", "10619", "1102", "vlad", "70719", "pers", "1211", "nova", "12196", "10919", "anni", "sara", "lian", "010119", "07196", "30419", "0707", "elli", "oker", "50219", "er123", "atch", "00519", "00419", "rest", "06196", "50319", "side", "na19", "60619", "1107", "50419", "1210", "00619", "50819", "80319", "11196", "90919", "1109", "tran", "arma", "anton", "30519", "50719", "andrew", "l123", "09196", "50119", "31019", "enny", "0808", "40219", "90619", "01119", "80219", "34567890", "fuckyou", "70219", "00719", "40519", "anch", "sweet", "30719", "80519", "51219", "40619", "80419", "soccer", "21119", "2108", "00819", "70419", "60319", "1204", "60519", "80819", "1205", "1002", "elly", "race", "00919", "7777777", "60219", "stic", "steve", "40319", "70519", "west", "41019", "90419", "30619", "thomas", "01219", "51019", "boob", "tche", "30819", "less", "assa", "60719", "allo", "ital", "poli", "light", "50919", "lion", "30919", "50619", "90319", "70319", "2109", "80119", "ment", "70919", "70119", "60419", "60119", "40719", "40819", "81219", "80719", "0404", "70819", "1208", "0112", "31219", "0107", "asti", "90119", "harley", "each", "70619", "40119", "51119", "0304", "80619", "90719", "bone", "well", "41219", "0606", "80919", "71019", "10101", "1206", "phil", "0105", "brand", "1209", "61219", "1202", "90819", "1105", "696969", "71119", "lick", "ista", "11111111", "91019", "lisa", "more", "0110", "1005", "123qwe", "91219", "1106", "alis", "60819", "0106", "60919", "1000", "41119", "stre", "arry", "1207", "llin", "1007", "charlie", "enko", "40919", "1203", "1004", "k123", "1110", "31119", "71219", "long", "61019", "buster", "apple", "1003", "wing", "91119", "ivan", "1123", "reat", "1103", "81019", "61119", "tori", "0506", "batman", "stri", "2212", "anov", "sion", "2107", "leon", "1104", "81119", "isha", "2102", "a197", "power", "summer", "superman", "anya", "qwertyui", "sing", "3108", "pepper", "1312", "2311", "george", "ence", "nker", "lore", "2110", "tech", "alan", "3112", "87654321", "1006", "card", "2106", "1008", "part", "ryan", "ross", "123a", "liver", "amin", "gran", "1402", "cock", "aron", "william", "ssie", "gene", "2512", "2301", "01200", "elan", "ipper", "ding", "para", "rish", "maria", "nson", "dave", "frank", "sasha", "1311", "2103", "moon", "rill", "buck", "tigger", "amel", "mara", "hand", "2105", "1812", "ollo", "2309", "roni", "kate", "1512", "happy", "2525", "2505", "0405", "1301", "21985", "redd", "2202", "arth", "terr", "iloveyou", "hockey", "2310", "mper", "2501", "2210", "3012", "per1", "2206", "adam", "3107", "abri", "tron", "emen", "0123", "olli", "11991", "isto", "game", "cent", "1009", "3110", "2305", "achi", "arta", "emin", "21990", "1310", "ladi", "hawk", "gfhjkm", "moni", "21989", "gate", "ines", "ing1", "lone", "llen", "ania", "elis", "mary", "alina", "2412", "ardo", "tall", "itte", "crea", "mani", "2204", "indi", "dogg", "1478", "shel", "0502", "0305", "tree", "ning", "ation", "peter", "real", "scott", "miss", "ucki", "sant", "slav", "liza", "erna", "3010", "olle", "2510", "oria", "enne", "meli", "asca", "0308", "0708", "chie", "access", "1510", "reds", "bass", "justin", "esse", "sche", "1305", "0508", "roll", "1412", "jxrf", "2511", "sman", "2104", "1504", "0905", "niko", "hammer", "arre", "ender", "2303", "erto", "0507", "hall", "1410", "2207", "2410", "1502", "1501", "svet", "sama", "2203", "1303", "ingo", "bitch", "1308", "2205", "1503", "esta", "0501", "1511", "98765432", "1404", "222222", "112233", "2503", "ress", "m123", "2504", "0212", "pres", "2304", "f123", "ming", "lucky", "lass", "fuckme", "jessica", "1307", "1306", "lash", "1302", "0211", "an19", "tlan", "jennifer", "1405", "link", "acker", "2306", "0306", "ener", "harr", "0301", "0503", "0302", "marl", "1235", "0509", "0809", "wild", "1612", "21984", "lori", "1411", "2411", "cola", "ger1", "andrea", "1221", "21992", "0310", "avis", "0803", "snow", "came", "3003", "1507", "illo", "mist", "sandr", "cand", "rate", "1711", "silver", "hant", "1508", "daddy", "3001", "franc", "unny", "90219", "taylor", "1304", "2401", "ashi", "3004", "freedom", "1704", "3105", "dead", "2208", "2509", "0607", "amanda", "0307", "joshua", "11984", "1805", "arie", "asse", "1403", "trin", "2209", "1705", "yman", "rett", "kell", "jeff", "0609", "inst", "2502", "stas", "matthew", "lanc", "0608", "2507", "alia", "1605", "0406", "alie", "2404", "tana", "bble", "ngle", "21991", "1801", "2307", "face", "stone", "1611", "1309", "1408", "2606", "hone", "1401", "mash", "anas", "mann", "aren", "wertyuio", "son1", "2508", "8888888", "00219", "3006", "0504", "nicole", "1712", "1213", "1707", "poop", "1407", "asper", "3103", "dallas", "erri", "dream", "denis", "teri", "2805", "mina", "ader", "diamond", "ride", "eral", "asshole", "0912", "ashley", "team", "cheese", "bobb", "2506", "1406", "1710", "11983", "thunder", "ister", "hero", "roman", "er19", "2405", "chen", "3005", "21983", "n200", "ginger", "serge", "0908", "2707", "kiss", "1811", "1604", "2406", "smoke", "0309", "lord", "maggie", "trustno1", "2611", "1509", "mila", "wall", "2601", "s200", "pack", "1802", "arme", "trac", "1703", "2909", "0311", "44444", "orne", "2812", "1606", "arne", "i123", "dude", "2711", "cookie", "1702", "2308", "kara", "0512", "sere", "1706", "sunshine", "holl", "tell", "1601", "2403", "101198", "1803", "ertyuiop", "wind", "2801", "1610", "2802", "1603", "2701", "ers1", "anny", "2612", "21982", "ound", "radi", "1506", "nman", "0407", "arro", "0408", "0510", "stat", "mail", "11992", "1804", "0807", "2808", "1602", "1810", "east", "2703", "2811", "nika", "enda", "astr", "barb", "victor", "osto", "abel", "2710", "2905", "ember", "0709", "1806", "ckle", "0711", "1409", "2901", "0312", "1808", "ker1", "2605", "rena", "arke", "olga", "n199", "colo", "0410", "ckie", "rach", "2904", "2603", "0403", "dina", "2704", "2803", "alon", "corn", "2712", "ally", "papa", "0906", "anthony", "otte", "icks", "rona", "0704", "2804", "audi", "2810", "0702", "2602", "iner", "cart", "2604", "11982", "reak", "2702", "russ", "bron", "tain", "0605", "0910", "hbyf", "1709", "pimp", "bond", "03200", "ristin", "1608", "0602", "devil", "2903", "shot", "phan", "08200", "etro", "2610", "05200", "1230", "lant", "2402", "house", "aran", "ana1", "enter", "mali", "slan", "2408", "2407", "01195", "erse", "ardi", "159753", "gust", "cali", "kova", "azer", "e200", "1222", "chil", "andra", "2705", "0610", "chelsea", "princess", "0902", "1809", "ermi", "2607", "ango", "oose", "0710", "3007", "hack", "atan", "0402", "11980", "0511", "04200", "adri", "0401", "on12", "nokia", "lady", "0805", "onde", "0601", "0412", "z123", "essa", "0603", "0810", "plan", "0411", "michelle", "maks", "inde", "2906", "blow", "nasty", "0701", "computer", "aine", "mira", "ucks", "core", "2912", "qwerty1", "2409", "1708", "lson", "aint", "0812", "0911", "2709", "1609", "toni", "iron", "eave", "1088", "ture", "oner", "some", "0705", "tere", "onta", "skin", "vent", "3009", "fast", "merlin", "4123", "1807", "0706", "0802", "0901", "1607", "2910", "0806", "0904", "11981", "atur", "02200", "09200", "2911", "tten", "elena", "0612", "white", "manu", "zxcvbnm", "yankees", "0604", "blin", "ammy", "2907", "samm", "0001", "nica", "acha", "2609", "starwars", "oleg", "1018", "2807", "0801", "alls", "water", "12200", "guitar", "boom", "tara", "0409", "0611", "0804", "mate", "2809", "nell", "rton", "boot", "ffff", "vill", "2708", "bles", "maxim", "ster1", "3008", "eeee", "0907", "flor", "riel", "rebe", "maha", "lton", "2468", "berg", "0712", "2806", "chicken", "tony", "jackson", "tick", "cham", "igma", "avel", "anut", "ales", "lane", "ichi", "2608", "nche", "welcome", "0903", "2706", "ckers", "lari", "onne", "inka", "apri", "kari", "dann", "07200", "adis", "10200", "call", "pion", "london", "pink", "ddie", "0703", "erson", "sport", "eren", "peac", "1qaz2wsx", "11200", "1029", "03195", "beer", "lala", "sssss", "metal", "opper", "ydog", "brown", "carol", "buff", "r200", "amor", "ennis", "cros", "brad", "2424", "init", "anes", "frog", "esto", "06200", "igor", "fant", "21993", "12011", "13579", "ncc1701", "cast", "eddy", "rush", "n198", "rris", "stel", "05195", "kins", "11993", "enta", "0000000", "magic", "kman", "vert", "10195", "2908", "4789", "ease", "tera", "arsenal", "0811", "them", "erre", "rter", "1100", "21980", "5150", "rome", "6123", "sham", "1194", "lman", "bigdog", "brian", "uffy", "jake", "greg", "poll", "moto", "aser", "21981", "rando", "rash", "8963", "ooke", "sparky", "oger", "jason", "wwww", "golfer", "jane", "arat", "eagles", "rado", "ping", "scooter", "assword1", "medi", "lera", "poke", "nett", "arge", "sten", "high", "cont", "ddog", "user", "ambo", "anim", "phoenix", "3344", "nity", "mars", "oren", "ashe", "octo", "orma", "work", "stud", "conn", "2369", "coll", "der1", "spider", "7896", "onte", "y200", "teen", "elvi", "sting", "hanna", "lips", "rida", "marina", "yama", "term", "tigers", "kenn", "brit", "10203", "anad", "ooper", "08195", "atte", "bast", "vika", "billy", "ferrari", "ishi", "kkkk", "river", "tttt", "llar", "lakers", "rend", "04195", "11195", "able", "rita", "trip", "nice", "ilan", "barn", "seve", "usty", "bbie", "boss", "dash", "iris", "itan", "sana", "cass", "ka19", "nina", "feli", "soni", "anil", "ussi", "aram", "ampi", "ablo", "olla", "ton1", "toma", "gman", "rama", "02195", "spri", "isco", "rack", "mers", "admi", "lade", "olan", "333333", "inal", "tani", "1089", "1078", "lana", "temp", "lly1", "unner", "09195", "adin", "12195", "9090", "rent", "man2", "honda", "tany", "na12", "131313", "4545", "jami", "nake", "r1234", "ples", "acki", "vova", "back", "ghbdtn", "g123", "hema", "estr", "onald", "stia", "5252", "book", "cccc", "dale", "secret", "1515", "anis", "mana", "anal", "rell", "rion", "1415", "corvette", "emil", "madd", "tink", "icky", "h123", "103198", "tine", "surf", "ssan", "bang", "speed", "1128", "onnie", "bubba", "23232", "best", "iant", "lter", "hhhh", "nathan", "gent", "gina", "vera", "eart", "riss", "apol", "marine", "llis", "ager", "9999999", "spec", "renc", "q1w2e3r4", "lley", "llll", "07195", "arad", "mous", "iann", "rola", "iter", "aper", "fylh", "slayer", "anet", "erpo", "trav", "carlo", "rrrr", "orange", "lent", "herm", "spir", "cana", "1232", "kola", "adim", "01010", "alexand", "1414", "ass1", "alic", "mish", "a196", "mily", "drum", "ter2", "smith", "11979", "tits", "asia", "acka", "21994", "dger", "r199", "moll", "ores", "egor", "ishe", "x123", "tyle", "rangers", "osta", "alpha", "haha", "jesus", "wer1", "herr", "nders", "020219", "clar", "buddy", "olas", "tian", "lovem", "vfvf", "rney", "ley1", "mans", "oopy", "rami", "orth", "lice", "ttie", "mero", "babe", "o200", "carr", "barr", "lder", "brook", "klas", "nikita", "acer", "anic", "2334", "21978", "open", "er20", "er11", "ina2", "cowboys", "mano", "an123", "read", "anit", "bara", "rsch", "iber", "ties", "gian", "field", "obby", "q123", "outh", "ilia", "anci", "anga", "na20", "32323", "down", "ravi", "ktor", "llan", "ine1", "bren", "112198", "amat", "21979", "beat", "3141", "ndia", "11978", "solo", "road", "alma", "amma", "steph", "internet", "nich", "bbbbb", "nite", "vita", "arde", "form", "rans", "ndro", "austin", "enna", "mall", "bloo", "ants", "107198", "endo", "1087", "valer", "icia", "mack", "ommy", "anana", "erbo", "simp", "dent", "arty", "1191", "mach", "asha1", "cris", "appe", "simon", "nard", "alker", "lovel", "arga", "icker", "06195", "mela", "music", "teme", "bigg", "chik", "ler1", "bite", "rocke", "nkin", "ver1", "lica", "domin", "geni", "105198", "aska", "izard", "coco", "banan", "tomm", "11994", "tasha", "gang", "anka", "pook", "petr", "101199", "stya", "oone", "illie", "inner", "adma", "icho", "iman", "donn", "0100", "5123", "inky", "etta", "123654", "gand", "tewa", "9632", "slut", "maverick", "lama", "amber", "mala", "ksan", "mona", "mino", "ddddd", "bart", "8097", "eres", "lolo", "qazxsw", "arks", "olina", "scha", "brie", "8098", "ugar", "richard", "here", "ntan", "hamp", "ysta", "marg", "mmmmm", "01020", "crazy", "oles", "soft", "wins", "drey", "ney1", "pire", "gera", "3000", "serv", "eddi", "mercedes", "alte", "1321", "dust", "020319", "020419", "spank", "unda", "1017", "qweasd", "erbe", "yfcn", "magn", "shor", "horse", "aaaaaaa", "bern", "reme", "lett", "snoop", "artem", "egas", "guar", "plat", "bandit", "nsta", "2580", "rdon", "s199", "108198", "dona", "horny", "asil", "ordo", "nny1", "1472", "hear", "walk", "abbi", "otto", "baba", "8912", "ickl", "boog", "inha", "erica", "ical", "1028", "10120", "1098", "kota", "ican", "dest", "harm", "raci", "onco", "rice", "evel", "789456", "qwas", "post", "tard", "atar", "unch", "aleks", "arah", "hers", "whatever", "amba", "guin", "ellow", "mode", "1q2w3e", "doug", "natas", "ffin", "8050", "tele", "winn", "1593", "202198", "burn", "a111", "steelers", "lvin", "nada", "veta", "erti", "nna1", "madi", "ulle", "zzzzzz", "ena1", "duck", "4242", "indo", "oron", "matrix", "fhby", "11995", "020819", "9119", "andal", "hoot", "eway", "abcde", "deli", "chas", "issi", "pand", "iden", "orte", "list", "rost", "laster", "punk", "nior", "heri", "polo", "nand", "kitty", "butter", "rini", "cking", "110198", "yana", "olive", "start", "linda", "1090", "pala", "051987", "21977", "1717", "chuc", "rule", "020519", "nima", "entr", "ailey", "ador", "haro", "turn", "eder", "atti", "brea", "koff", "hans", "vero", "mati", "julia", "arce", "izza", "7891", "fucker", "011990", "orri", "erik", "leas", "mother", "natali", "thead", "arco", "rant", "erta", "b123", "020119", "gator", "heel", "ard1", "grea", "anat", "mer1", "vfrc", "020619", "olden", "ick1", "help", "bbit", "mera", "akot", "pool", "erst", "erni", "8951", "inch", "lame", "nchi", "death", "5555555", "1058", "kati", "011987", "aras", "lexi", "rrie", "ierr", "mili", "dboy", "ates", "kristi", "perf", "case", "bean", "asto", "randy", "oris", "iles", "falcon", "1516", "5050", "llio", "nati", "inni", "91989", "anki", "rame", "kevin", "207198", "a2010", "lest", "a123456", "rega", "friend", "chevy", "aval", "andon", "red1", "verp", "lava", "omar", "kiri", "as12", "cara", "amir", "olit", "hani", "annon", "tive", "okey", "nther", "1092", "estin", "ickey", "204198", "11977", "unit", "dance", "031988", "arba", "trai", "juan", "d1234", "rger", "11975", "1079", "020719", "dell", "rabb", "rmin", "thor", "rlan", "jean", "jone", "scorpio", "11976", "p123", "shal", "erlo", "nest", "hele", "5566", "en12", "want", "ayne", "est1", "erem", "issy", "208198", "ygir", "burg", "s1234", "forever", "ions", "enka", "flower", "uren", "sass", "051990", "ashk", "theb", "isse", "scho", "2119", "camp", "031987", "201198", "tima", "0012", "ophi", "les1", "rene", "9874", "late", "oome", "205198", "chip", "hica", "ento", "loves", "2131", "pace", "21976", "inke", "ction", "little", "duke", "206198", "elic", "onat", "ancer", "sala", "doll", "onik", "eria", "cord", "eanu", "chang", "gord", "kaka", "diab", "asdfghj", "elia", "1237", "umpe", "dies", "alam", "gala", "fort", "nine", "11121", "1118", "rker", "2128", "071987", "avan", "soph", "oshi", "knight", "bomb", "arra", "jimmy", "1314", "1285", "mple", "like", "imbo", "bigt", "1324", "dodge", "rchi", "fend", "ikol", "1129", "ocky", "r198", "1022", "lege", "inat", "llo1", "bber", "041988", "rade", "ebel", "kass", "robi", "elec", "hari", "aldo", "otti", "stef", "ssma", "erda", "luca", "samu", "leri", "tati", "ears", "adel", "frea", "iano", "ya19", "offe", "yell", "ochka", "geli", "esha", "15051", "dmin", "morgan", "bella", "onna", "21995", "8910", "31991", "ameri", "annah", "isla", "truck", "asmin", "071986", "020919", "anthe", "s198", "compa", "beth", "041986", "a777", "121987", "061986", "raider", "grac", "atash", "051988", "stle", "joke", "041987", "male", "4455", "driv", "tita", "051986", "nato", "amal", "0010", "3030", "patrick", "09876", "jjjjj", "charle", "item", "41984", "edog", "1290", "121986", "stop", "demon", "ious", "lissa", "cheste", "5935", "4725", "chol", "warr", "atro", "entin", "umbe", "ma19", "22011", "tata", "asan", "host", "skip", "on19", "lipp", "abra", "nish", "alib", "erro", "ench", "mpir", "1190", "1077", "10111", "10121", "dogs", "lphin", "nnet", "ippy", "berl", "71990", "llet", "011988", "junio", "203198", "41985", "arit", "71985", "cons", "ronc", "craft", "ongo", "ingl", "1086", "ka12", "iking", "81990", "ooooo", "ergi", "ritt", "hester", "10011", "031986", "cats", "brav", "011986", "7258", "2123", "k199", "lita", "81985", "011985", "0990", "johnny", "terp", "samsung", "mang", "city", "71989", "micke", "huck", "91986", "etty", "desi", "aura", "021019", "oser", "fall", "key1", "ssin", "timo", "joseph", "viki", "orgi", "061987", "world", "anja", "iabl", "hjcn", "mass", "hank", "5454", "anky", "comm", "21975", "051985", "91988", "81987", "arsh", "fami", "q2w3e4r", "051989", "obra", "twin", "011989", "gabr", "rles", "muff", "elove", "209198", "61990", "1127", "071988", "qqqqqq", "imbe", "erty12", "baile", "061988", "ilip", "rico", "dward", "rova", "erde", "ghjc", "lect", "eone", "cky1", "irina", "0019", "monster", "9357", "oster", "lish", "edwar", "3698", "shing", "inho", "idas", "1245", "01041", "shak", "1038", "ppppp", "girls", "5656", "45612", "yste", "5000", "smar", "amie", "ners", "raven", "pean", "meric", "ulie", "laure", "look", "n1234", "210198", "101987", "2344", "idge", "ymrf", "rpoo", "31985", "ffer", "081988", "viper", "tton", "thing", "031990", "choo", "101986", "41990", "oodl", "right", "miller", "31989", "evan", "onto", "bian", "eigh", "manc", "lace", "lema", "ggggg", "heather", "nnnn", "tenn", "orin", "emar", "ssio", "hort", "loui", "camaro", "squi", "carm", "31983", "061985", "8908", "inga", "2341", "kath", "7852", "kbyf", "stea", "view", "lldog", "pson", "ty123", "ris1", "ert1", "1234q", "eles", "ouch", "20011", "hman", "ova1", "arik", "dirt", "1188", "8904", "name", "ooby", "christi", "dria", "ethe", "plea", "ra19", "1080", "boro", "dako", "pain", "earl", "rple", "ocket", "deep", "livi", "elon", "01031", "1068", "61989", "sabe", "01021", "tyrj", "hark", "ontr", "rink", "vfhb", "amant", "utch", "in12", "lean", "01091", "hara", "nsto", "rocks", "e1234", "20021", "dolphi", "asda", "iell", "anin", "fghjk", "icki", "albert", "rato", "latin", "bulldo", "1082", "505198", "popo", "ceman", "eras", "dog1", "23021", "mell", "71983", "mario", "ber1", "smile", "rlos", "hane", "roke", "1016", "homer", "ntai", "xxxxxxx", "winte", "storm", "lova", "purpl", "kare", "41991", "coob", "091987", "nita", "count", "021988", "okin", "2342", "081989", "diana", "ione", "ntha", "pira", "pear", "dawg", "beav", "imal", "obbi", "aroli", "71984", "2333", "081986", "tdog", "bigbo", "rove", "erba", "blad", "bett", "usha", "ndri"]; diff --git a/src/ts/nn-misc.ts b/src/ts/nn-misc.ts index 30b0220..58e73d9 100644 --- a/src/ts/nn-misc.ts +++ b/src/ts/nn-misc.ts @@ -3,137 +3,139 @@ import Constants = require("./constants"); import Config = require("./config"); declare class NeuralNetworkClient { - constructor(cb: (n: number, s: string) => void, config: Config.Config.ConfigNeuralNetwork); - query_guess_number(pw: string): void; + constructor(cb: (n: number, s: string) => void, config: Config.Config.ConfigNeuralNetwork); + query_guess_number(pw: string): void; } export module NeuralNetwork { - var verboseMode = false; - // In case neural nets don't load, don't wait to give a score - var neverHeardFromNN = true; - - // Helper function designed to post-process neural network guess numbers - // to account for capitalization. - // It scales guess numbers by 1.5 if they capitalize the first character, - // by 2 if they capitalize all characters, by 10 if they use any other pattern, - // and 1 if there are no uppercase characters. - function uppercasePredictabilityPostProcessing(pw: string): number { - // Start by assuming no uppercase at all - var scalingFactor = 1; - var allButFirstChar = pw.substr(1); - // Check if first character is uppercase, and that no others are - if ((pw.charAt(0) === pw.charAt(0).toUpperCase() - && pw.charAt(0) !== pw.charAt(0).toLowerCase()) - && (allButFirstChar === allButFirstChar.toLowerCase())) { - scalingFactor = 1.5; - // Check if `all uppercase' (>=3 characters uppercase and no lowercase letters) - } else if (pw.search(/[a-z]/) == -1) { - // First delete all uppercase characters - var pwNoUppercase = pw.replace(Constants.Constants.UPPERCASE_LETTERS_GLOBAL, ""); - // Check if password is now 3+ characters shorter - if (pw.length >= (pwNoUppercase.length + 3)) { - scalingFactor = 2; - } - // Check if there are uppercase characters that don't fit into those two patterns - } else if (pw !== pw.toLowerCase()) { - scalingFactor = 10; - } - return scalingFactor; - } - - // Math.log10 is not universal yet - function log10(x: number): number { - return Math.log(x) / Math.LN10; - } - - // The main callback function for the neural network evaluation. - // When it returns, it will display the rating (update the UI). - function nnCallback(result: number, password: string): void { - // Make 10^15 guesses fill 2/3rds of meter - const scaleToMeter = 67 / 15; - - var UI = PasswordMeter.PasswordMeter.instance.getUI(); - result = result * uppercasePredictabilityPostProcessing(password); - if (verboseMode) { - console.log(password + " is NN guess # " + result); - } - neverHeardFromNN = false; - var value = log10(result) * scaleToMeter; - // With estimates, we can get fractional/negative guess numbers - // for terrible passwords, so compensate to have a very small number - if (result <= 1) { - value = log10(1.1) * scaleToMeter; - } - if (isNaN(result)) { - value = -1; - } - // Neural nets give infinity for empty passwords, hence check length - if (password.length > 0 && result == Number.POSITIVE_INFINITY) { - value = 100; - } - UI.setNeuralnetMapping(password, value); - UI.displayRating(password); - } - - // potentialTODO except for the logging, this looks exactly the same as above - // This alternate callback function is used instead when evaluating - // concrete suggestions for a better password - export function nnFixedCallback(result: number, password: string): void { - // Make 10^15 guesses fill 2/3rds of meter - const scaleToMeter = 67 / 15; - - var UI = PasswordMeter.PasswordMeter.instance.getUI(); - result = result * uppercasePredictabilityPostProcessing(password); - if (verboseMode) { - console.log("Fixed possibility " + password + " is NN guess # " + result); - } - neverHeardFromNN = false; - var value = log10(result) * scaleToMeter; - - // With estimates, we can get fractional/negative guess numbers - // for terrible passwords, so compensate to have a very small number - if (result <= 1) { - value = log10(1.1) * scaleToMeter; - } - if (isNaN(result)) { - value = -1; - } - // Neural nets give infinity for empty passwords, hence check length - if (password.length > 0 && result == Number.POSITIVE_INFINITY) { - value = 100; - } - UI.setNeuralnetMapping(password, value); - UI.synthesizeFixed(password); - } - - export class NeuralNetworkInterface { - nnfixed: NeuralNetworkClient; - nn: NeuralNetworkClient; - - constructor(nn: NeuralNetworkClient, nnfixed: NeuralNetworkClient) { - this.nn = nn; - this.nnfixed = nnfixed; - } - - public heardFromNn(): boolean { - return !neverHeardFromNN; - } - } - - (function () { - var registry = PasswordMeter.PasswordMeter.instance; - var jquery = registry.getJquery(); - var lzstring = registry.getLzstring(); - var config = registry.getConfig(); - - var neuralNetworkConfig = config.neuralNetworkConfig; - - var verboseMode = false; - var nnFixed = new NeuralNetworkClient(nnFixedCallback, neuralNetworkConfig); - var nn = new NeuralNetworkClient(nnCallback, neuralNetworkConfig); - var instance = new NeuralNetworkInterface(nn, nnFixed); - - registry.setNN(instance); - }()) - + // In case neural nets don't load, don't wait to give a score + var neverHeardFromNN = true; + + // mapping of passwords to score based on neural networks + // TODO(josh): use Least Recently Used cache so mapping doesn't grow too large + var neuralNetMapping: { [key: string]: number } = {}; + + // Helper function designed to post-process neural network guess numbers + // to account for capitalization. + // It scales guess numbers by 1.5 if they capitalize the first character, + // by 2 if they capitalize all characters, by 10 if they use any other pattern, + // and 1 if there are no uppercase characters. + function uppercasePredictabilityPostProcessing(pw: string): number { + // Start by assuming no uppercase at all + var scalingFactor = 1; + var allButFirstChar = pw.substr(1); + // Check if first character is uppercase, and that no others are + if ((pw.charAt(0) === pw.charAt(0).toUpperCase() + && pw.charAt(0) !== pw.charAt(0).toLowerCase()) + && (allButFirstChar === allButFirstChar.toLowerCase())) { + scalingFactor = 1.5; + // Check if `all uppercase' (>=3 characters uppercase and no lowercase letters) + } else if (pw.search(/[a-z]/) == -1) { + // First delete all uppercase characters + var pwNoUppercase = pw.replace(Constants.Constants.UPPERCASE_LETTERS_GLOBAL, ""); + // Check if password is now 3+ characters shorter + if (pw.length >= (pwNoUppercase.length + 3)) { + scalingFactor = 2; + } + // Check if there are uppercase characters that don't fit into those two patterns + } else if (pw !== pw.toLowerCase()) { + scalingFactor = 10; + } + return scalingFactor; + } + + // Math.log10 is not universal yet + export function log10(x: number): number { + return Math.log(x) / Math.LN10; + } + + // 1. if NN num is a finite number but negative or 0, map to log10(1.1) ~= 0.04 + // 2. as long as password is not empty string (""), if NN is +infinity, then map to 100 percent + // (due to NN bug, empty string maps to positive +infinity also; don't map to 100 for that case) + // 3. if NN is not a number + function postProcessNnNumAndCache(result: number, password: string): void { + result = result * uppercasePredictabilityPostProcessing(password); + neverHeardFromNN = false; + var value = log10(result); + + // With estimates, we can get fractional/negative guess numbers + // for terrible passwords, so compensate to have a very small number + if (result <= 1) { + value = log10(1.1); + } + // Neural nets give infinity for empty passwords, hence check length + if (password.length > 0 && result == Number.POSITIVE_INFINITY) { + value = 100; + } + // if result is undefined for some reason, just store -1 + // as NN, so meter will ignore that passwords NN number + if (isNaN(result)) { + value = -1; + } + + var nni = PasswordMeter.PasswordMeter.instance.getNN(); + nni.setNeuralNetNum(password, value); + } + + // The main callback function for the neural network evaluation. + // When it returns, it will display the rating (update the UI). + function nnCallback(result: number, password: string): void { + postProcessNnNumAndCache(result, password); + + var UI = PasswordMeter.PasswordMeter.instance.getUI(); + UI.displayRating(password); + } + + // This alternate callback function is used instead when evaluating + // concrete suggestions for a better password + export function nnFixedCallback(result: number, password: string): void { + postProcessNnNumAndCache(result, password); + + var UI = PasswordMeter.PasswordMeter.instance.getUI(); + UI.synthesizeFixed(password); + } + + export class NeuralNetworkInterface { + nn: NeuralNetworkClient; + nnfixed: NeuralNetworkClient; + + constructor(nn: NeuralNetworkClient, nnfixed: NeuralNetworkClient) { + this.nn = nn; + this.nnfixed = nnfixed; + } + + public heardFromNn(): boolean { + return !neverHeardFromNN; + } + + // set the mapping from the neural network + public setNeuralNetNum(pw: string, value: number): void { + neuralNetMapping[pw] = value; + } + + // set the mapping from the neural network + public getNeuralNetNum(pw: string): number { + return neuralNetMapping[pw]; + } + + // initiate NN guess number lookup + public queryGuessNumber(pw: string, isConcreteSuggestionCandidate: boolean): void { + if (isConcreteSuggestionCandidate) { + this.nnfixed.query_guess_number(pw); + } else { + this.nn.query_guess_number(pw); + } + } + } + + (function() { + var registry = PasswordMeter.PasswordMeter.instance; + var config = registry.getConfig(); + + var neuralNetworkConfig = config.neuralNetworkConfig; + var nnFixed = new NeuralNetworkClient(nnFixedCallback, neuralNetworkConfig); + var nn = new NeuralNetworkClient(nnCallback, neuralNetworkConfig); + var instance = new NeuralNetworkInterface(nn, nnFixed); + registry.setNN(instance); + }()) } diff --git a/src/ts/rulefunctions.ts b/src/ts/rulefunctions.ts index cf10538..e78d905 100644 --- a/src/ts/rulefunctions.ts +++ b/src/ts/rulefunctions.ts @@ -1,12 +1,9 @@ import PasswordMeter = require("./PasswordMeter"); import Config = require("./config"); import Helper = require("./helper"); -import Dictionaries = require("./dict-misc"); import Constants = require("./constants"); +import NeuralNetwork = require("./nn-misc"); -/* ************** */ -/* Rule Functions */ -/* ************** */ export module RuleFunctions { interface ResultsDetail { compliance: { [key: string]: boolean }; @@ -415,6 +412,33 @@ export module RuleFunctions { compliance["usernameDifference"] = compliant; } + // min NN guess number requirement + if (config.minLogNnGuessNum.active) { + var compliant = false; + var thisExplanation = ""; + var minLogNnGuessNum = config.minLogNnGuessNum.threshold; + var nni = PasswordMeter.PasswordMeter.instance.getNN(); + var conservativeNnNum = nni.getNeuralNetNum(pw); + var unconservativeNnNum = conservativeNnNum + NeuralNetwork.NeuralNetwork.log10(config.neuralNetworkConfig.scaleFactor); + + if (conservativeNnNum < 0) { + console.log("looking up NN guess number: " + pw); + } else if (conservativeNnNum > minLogNnGuessNum) { + compliant = true; + console.log("high enough NN guess number: " + pw + " (" + conservativeNnNum + + " > " + minLogNnGuessNum + ") [unconservative NN guess number: " + unconservativeNnNum + "]"); + } else { + console.log("too low NN guess number: " + pw + " (" + conservativeNnNum + + " < " + minLogNnGuessNum + ") [unconservative NN guess number: " + unconservativeNnNum + "]"); + thisExplanation = "" + noncompliantSymbol + config.minLogNnGuessNum.rejectionFeedback; + } + + if (!compliant) { + explanation["minLogNnGuessNum"] = thisExplanation; + } + compliance["minLogNnGuessNum"] = compliant; + } + // potentialTODO reduce operation var overallCompliance: boolean = true; for (const item in compliance) { @@ -1217,7 +1241,7 @@ export module RuleFunctions { pluralSuffix = "s"; } var sensitiveText = "Have more variety than repeating the same " + uniques.length + - " character" + pluralSuffix + " ("+Helper.Helper.boldAll(uniques.sort()).toHumanString()+")"; + " character" + pluralSuffix + " (" + Helper.Helper.boldAll(uniques.sort()).toHumanString() + ")"; reasonWhy = "Passwords that use only a few different characters are easy for " + "attackers to guess"; } @@ -1540,7 +1564,7 @@ export module RuleFunctions { pw = pw.replace(/[-_ ]/g, ""); // remove characters that could delimit words //20mostCommon var pwParts = pw.split(/[^a-z012345!&@$]+/); // split password into parts that might contain dictionary words post-substitution; discard non-letters that won't be reverse substituted var pwParts = pw.split(/[^a-z01345@$]+/); // split password into parts that might contain dictionary words post-substitution; discard non-letters that won't be reverse substituted - pwParts = pwParts.filter(function (e) { + pwParts = pwParts.filter(function(e) { return e }); // this removes empty strings, etc. var listofSS = pwParts.listSubstringsMinMax(1, undefined); // returns substrings in descending order of length @@ -1581,7 +1605,7 @@ export module RuleFunctions { var ssLocation = pwParts[z].indexOf(foundMatch); if (ssLocation > -1) { // remove; leave remainder of string pwParts.splice(z, 1, pwParts[z].substring(0, ssLocation), pwParts[z].substring(ssLocation + foundMatch.length)); - pwParts = pwParts.filter(function (e) { + pwParts = pwParts.filter(function(e) { return e }); break; @@ -1611,7 +1635,7 @@ export module RuleFunctions { wordsTheyShouldNotHaveUsed[i].length); } } - sensitiveText = "Don't use site-specific terms ("+Helper.Helper.boldAll(wordsTheyShouldNotHaveUsed.removeDuplicates()).toHumanString()+")"; + sensitiveText = "Don't use site-specific terms (" + Helper.Helper.boldAll(wordsTheyShouldNotHaveUsed.removeDuplicates()).toHumanString() + ")"; reasonWhy = "Attackers target their attacks to words used on a particular service"; } @@ -1665,7 +1689,7 @@ export module RuleFunctions { // split the password: pw = pw.replace(/[-_ ]/g, ""); // remove characters that could delimit words var pwParts = pw.split(/[^A-Za-z012345!&@$]+/); // split password into parts that might contain dictionary words post-substitution; discard non-letters that won't be reverse substituted - pwParts = pwParts.filter(function (e) { + pwParts = pwParts.filter(function(e) { return e }); // this removes empty strings, etc. @@ -1761,7 +1785,7 @@ export module RuleFunctions { var ssLocation = pwParts[z].indexOf(foundMatch); if (ssLocation > -1) { // remove; leave remainder of string pwParts.splice(z, 1, pwParts[z].substring(0, ssLocation), pwParts[z].substring(ssLocation + foundMatch.length)); - pwParts = pwParts.filter(function (e) { + pwParts = pwParts.filter(function(e) { return e }); // that cleared out empty strings etc @@ -1782,11 +1806,11 @@ export module RuleFunctions { var complaintLength = 0; // keep track of how many characters were in a wordlist var complaintTokens = 0; // keep track of how many separate tokens (words) were used - var boldList = function (foo: Array): string { + var boldList = function(foo: Array): string { return Helper.Helper.boldAll(foo.removeDuplicates()).toHumanString(); }; - var fillComplaints = function (array: Array, text: string): void { + var fillComplaints = function(array: Array, text: string): void { if (array.length > 0) { publicComplaints.push(text); for (var i = 0; i < array.length; i++) { @@ -1853,7 +1877,7 @@ export module RuleFunctions { var passwordParts = [pw]; // as we start removing things, keep an array of the remaining parts - var dateanalyze = function (rx: RegExp): void { + var dateanalyze = function(rx: RegExp): void { var resultObj = helper.matchHelper(passwordParts, rx); if (resultObj.score > 0) { score += resultObj.score; @@ -1877,45 +1901,45 @@ export module RuleFunctions { // identify dates YYYYMMDD without delimiters? // identify dates MM-DD-YYYY with delimiters - var rx = new RegExp(MM+DEL+DD+DEL+YYYY, "g"); + var rx = new RegExp(MM + DEL + DD + DEL + YYYY, "g"); dateanalyze(rx); // identify dates DD-MM-YYYY with delimiters - var rx = new RegExp(DD+DEL+MM+DEL+YYYY, "g"); + var rx = new RegExp(DD + DEL + MM + DEL + YYYY, "g"); dateanalyze(rx); // identify dates MM-DD-YY with delimiters - var rx = new RegExp(MM+DEL+DD+DEL+YY, "g"); + var rx = new RegExp(MM + DEL + DD + DEL + YY, "g"); dateanalyze(rx); // identify dates DD-MM-YY with delimiters - var rx = new RegExp(DD+DEL+MM+DEL+YY, "g"); + var rx = new RegExp(DD + DEL + MM + DEL + YY, "g"); dateanalyze(rx); // identify dates MMDDYYYY without delimiters - var rx = new RegExp(MM+DD+YYYY, "g"); + var rx = new RegExp(MM + DD + YYYY, "g"); dateanalyze(rx); // identify dates DDMMYYYY without delimiters - var rx = new RegExp(DD+MM+YYYY, "g"); + var rx = new RegExp(DD + MM + YYYY, "g"); dateanalyze(rx); // in the future, maybe consider identifying dates MMDDYY without any delimiters, but there seem to be lots of false positives // identify spelled-out months and recent year (4 digits) - var rx = new RegExp(MMMM+YYYY, "ig"); + var rx = new RegExp(MMMM + YYYY, "ig"); dateanalyze(rx); // identify spelled-out months and recent year (2 digits) - var rx = new RegExp(MMMM+YY, "ig"); + var rx = new RegExp(MMMM + YY, "ig"); dateanalyze(rx); // identify dates MM-DD with delimiters/ - var rx = new RegExp(MM+DEL+DD, "g"); + var rx = new RegExp(MM + DEL + DD, "g"); dateanalyze(rx); // identify dates DD-MM with delimiters/ - var rx = new RegExp(DD+DEL+MM, "g"); + var rx = new RegExp(DD + DEL + MM, "g"); dateanalyze(rx); // identify recent years between 1900 and 2049 diff --git a/src/ts/ui-misc.ts b/src/ts/ui-misc.ts index a5ad6c7..a477710 100644 --- a/src/ts/ui-misc.ts +++ b/src/ts/ui-misc.ts @@ -5,1115 +5,1129 @@ import LZString = require("lz-string"); import PasswordMeter = require("./PasswordMeter"); import Config = require("./config"); import RuleFunctions = require("./rulefunctions"); +import NeuralNetwork = require("./nn-misc"); +import Constants = require("./constants"); export module UIMisc { - export class UIMisc { - helper: Helper.Helper.Helper; - $: JQueryStatic; - verboseMode: boolean; - - // Global variable to retain the password when the modal was opened, - // so that we later know whether or not to show a 'discard' button - private pwWhenModalOpened: string = ""; - - // Global variable indicating whether they ever clicked the concerete suggestion. - // If so, don't show them another fixed password unless they drop - // below the 2/3rds threshold. - private tookSuggestion: boolean = false; - - // Global variable to store what password's rating is currently shown - private previouslyRated: string = ""; - - // Previously computed information about password scores and feedback - // To avoid scoring things multiple times, store mappings in associative arrays - // -1 means that we already spawned a thread to perform this calculation, so don't duplicate it - // Mapping of passwords to score based on advanced heuristics - private heuristicMapping: {[key: string]: number} = {}; - // Mapping of passwords to score based on neural networks - private neuralnetMapping: {[key: string]: number} = {}; - // Mapping of passwords to public/sensitive feedback - // potentialTODO that could get expensivex - // potentialTODO structure this - private feedbackMapping: {[key: string]: string} = {}; - - // Previously computed information about concrete suggestions - // Mapping of passwords to a potential concrete suggestion. - // If the suggestion is scored highly enough, then store it in fixedpwMapping. - private recommendedFixes: {[key: string]: string} = {}; - // To avoid excess computation, keep track of how many tries we've made - // trying to generate a strong concerete suggestion. If too many, - // give up rather than potentially cause UI lag. - private recommendedFixesTries: {[key: string]: number} = {}; - // Keep track of the previous candidate we tried for the concrete suggestion. - // If insufficiently strong, we'll want to modify it - private previousCandidate: {[key: string]: string} = {}; - // Final mapping of password to (pre-validated) stronger concrete suggestion - private fixedpwMapping: {[key: string]: string} = {}; - // How the concrete suggestion was modified from the original (for highlights) - private deltaHighlighted: {[key: string]: Array} = {}; - - // Globally keep track of whether the password is in compliance with the - // composition policy. We use this to decide whether to let them continue. - // We store this in a global to avoid double-calling the function each time. - private inCompliance: boolean = false; - - constructor(verboseMode: boolean) { - var registry = PasswordMeter.PasswordMeter.instance; - this.helper = registry.getHelper(); - this.$ = registry.getJquery(); - this.verboseMode = verboseMode; - } - - onReady(): void { - // Make the non-modal (feedback box) appear - this.$(".pop").fadeIn(); - // Reset hide/show checkbox in case they reloaded the page - // and call the function that shows password/******** based on it - this.$("#showHidePWNonModal").prop("checked", false); - this.toggleShowHideNonModal(); - // Rate the password in the box (if any) - this.spawnRating(); - } - - // This function switches between the password being ***** and shown in non-modal - toggleShowHideNonModal(): void { - if (this.$("#showHidePWNonModal").prop("checked")) { - this.$("#pwbox").prop("type", "text"); - this.$("#pwboxModal").prop("type", "text"); - // Make non-modal and modal checkboxes match - this.$("#showHidePWModal").prop("checked", true); - } else { - this.$("#pwbox").prop("type", "password"); - this.$("#pwboxModal").prop("type", "password"); - // Make non-modal and modal checkboxes match - this.$("#showHidePWModal").prop("checked", false); - } - this.spawnRating(); - } - - // This function switches between the password being ***** and shown in modal - toggleShowHideModal(): void { - if (this.$("#showHidePWModal").prop("checked")) { - this.$("#pwbox").prop("type", "text"); - this.$("#pwboxModal").prop("type", "text"); - // Make non-modal and modal checkboxes match - this.$("#showHidePWNonModal").prop("checked", true); - } else { - this.$("#pwbox").prop("type", "password"); - this.$("#pwboxModal").prop("type", "password"); - // Make non-modal and modal checkboxes match - this.$("#showHidePWNonModal").prop("checked", false); - } - this.spawnRating(); - } - - // Function called when the modal window is opened. - // Save what the password is at this point and transfer - // the password from the main window to the modal - storepw(): void { - var pw = this.$("#pwbox").val() as string; - this.pwWhenModalOpened = pw; - this.$("#pwboxModal").val(pw); - } - - // Show the discard button in the modal only if they edited the password field - enableDiscard(): void { - // If they haven't changed the password since opening the modal - if (this.$("#pwboxModal").val() === this.pwWhenModalOpened) { - this.$("#discardButton").hide(); - this.$("#keepButton").html("OK"); - } else { - this.$("#discardButton").show(); - this.$("#keepButton").html("Keep Changes"); - } - } - - // They chose to keep their modal-modified password, - // so transfer it to the main window - keeppw(): void { - this.$("#pwbox").val(this.$("#pwboxModal").val()); - } - - // If they click the concrete suggestion in the non-modal, put it in the password field - fixPWNonModal(): void { - // Note for later that they have taken a suggestion - this.tookSuggestion = true; - var newpw = this.$("#nonmodalFixedPW").text(); - this.$("#pwbox").val(newpw); - // Update the rating - this.spawnRating(); - } - - // If they click the concrete suggestion in the modal, put it in the password field - fixPWModal(): void { - this.tookSuggestion = true; - var pw = this.$("#modalFixedPW").text(); - this.$("#pwboxModal").val(pw); - this.spawnRating(); - this.enableDiscard(); - } - - // Set up the modal when they are initially showing it - showModal(): void { - this.storepw(); - this.$("#discardButton").hide(); - this.$("#keepButton").html("OK"); - this.$("#myModal").show(); - } - - // To save computation, only rate the password if it has changed - mayberate(): void { - if (this.$("#pwbox").val() !== this.previouslyRated) { - this.previouslyRated = this.$("#pwbox").val() as string; - this.spawnRating(); - } - } - - // When they try to submit, decide whether to let them continue - continueCheck(triedToSubmit: boolean): void { - var compliantOverall = true; - // Make sure username is non-empty - if (triedToSubmit) { - var username = this.$("#usernamebox").val() as string; - if (username.length < 1) { - this.$("#usernameTooShort").show(); - compliantOverall = false; - } else { - this.$("#usernameTooShort").hide(); - } - } - - // Check compliance with the password-composition policy - if (!this.inCompliance) { - compliantOverall = false; - // Also hide confirmation error messages - this.$("#confirmDoesNotMatch").hide(); - // Only turn red when they try to submit - if (triedToSubmit) { - this.$("#feedbackHeaderText").css({ - "color": "red", - "font-weight": "bold" - }); - this.$("#passwordNonCompliant").show(); - } - } else { - // It is in compliance, so turn everything back to normal - this.$("#feedbackHeaderText").css({ - "color": "", - "font-weight": "" - }); - this.$("#passwordNonCompliant").hide(); - } - // Check that the confirm box matches the password - if (this.$("#pwbox").val() !== this.$("#confirmbox").val()) { - compliantOverall = false; - // Only show the error when they try to submit a compliant pw - if (triedToSubmit && this.inCompliance) { - this.$("#confirmDoesNotMatch").show(); - } - } else { - this.$("#confirmDoesNotMatch").hide(); - } - // If meets policy, matches confirm, and they hit submit, let them - if (triedToSubmit && compliantOverall) { - alert("this would be submitted"); - } - } - - // The main function for starting the password-rating process. - // This function determines whether we've already calculated scores for - // a given password using both heuristics and neural networks. - // If so, call the function to show results. - // If not (undefined mappings), change the mappings temporarily to -1 - // and spawns the ratings. - // When those functions return, display will be called via callbacks. - spawnRating(): void { - var pw = ""; - var nni = PasswordMeter.PasswordMeter.instance.getNN(); - var nn = nni.nn; - if (this.$("#myModal").data("bs.modal") && this.$("#myModal").data("bs.modal").isShown) { - pw = this.$("#pwboxModal").val() as string; - } else { - pw = this.$("#pwbox").val() as string; - } - var username = this.$("#usernamebox").val() as string; - var ratingsComplete = 0; - if (typeof (this.neuralnetMapping[pw]) === "undefined") { - // Signal that we are calculating it to avoid duplicate work - this.neuralnetMapping[pw] = -1; - // Asynchronously calculate neural network guess number - nn.query_guess_number(pw); - } else if (this.neuralnetMapping[pw] >= 0) { - ratingsComplete++; - } - if (typeof (this.heuristicMapping[pw]) === "undefined") { - this.queryHeuristicGuessNumber(pw, username, true); - } else if (this.heuristicMapping[pw] >= 0) { - ratingsComplete++; - } - // If we have both ratings, or neural nets doesn't seem to work - // on this browser, or the password is empty, display the rating. - if (pw.length === 0 || !nni.heardFromNn() || ratingsComplete === 2) { - this.displayRating(pw); - } - } - - // This function tries to generate a candidate for the conrete suggestion - // following randomly chosen modification strategies. - // It requires the current candidate (pw), the current recursion depth (depth) - // to avoid causing lag, and the original version of the password (originalPW) - generateCandidateFixed(pw: string, depth: number, originalPW: string): number { - // We keep a vector that tracks changes we make to the password for - // future highlighting purposes. - var deltas: Array = []; - // If this is the initial call, initialize that vector - if (typeof (this.deltaHighlighted[pw]) === "undefined") { - for (var i = 0; i < pw.length; i++) { - deltas[i] = 0; - } - } else { - deltas = this.deltaHighlighted[pw]; - } - - // Get the current modification of the password - var modifiedPW = pw; - if (typeof (this.previousCandidate[pw]) !== "undefined") { - // We may have already moved digits or symbols - modifiedPW = this.previousCandidate[pw]; - deltas = this.deltaHighlighted[modifiedPW]; - } - - // Randomly select one of the strategies in a biased way - var selection = Math.floor(8 * Math.random()); - // Strategy A: toggle case - if (selection === 0 || selection === 1) { - var pwLen = modifiedPW.length; - var loc = Math.floor(pwLen * Math.random()); - if (modifiedPW.charCodeAt(loc) >= 65 && modifiedPW.charCodeAt(loc) <= 90) { - modifiedPW = modifiedPW.replaceAt(loc, String.fromCharCode(modifiedPW.charCodeAt(loc) + 32)); - deltas[loc] = 1; - } else if (modifiedPW.charCodeAt(loc) >= 97 && modifiedPW.charCodeAt(loc) <= 122) { - modifiedPW = modifiedPW.replaceAt(loc, String.fromCharCode(modifiedPW.charCodeAt(loc) - 32)); - deltas[loc] = 1; - } - // Strategy B: substitute character - } else if (selection === 2 || selection === 3) { - var char1 = 32 + Math.floor(Math.random() * 95); - var loc1 = Math.floor((modifiedPW.length) * Math.random()); - if (modifiedPW.charCodeAt(loc1) !== char1) { - deltas[loc1] = 1; - } - modifiedPW = modifiedPW.replaceAt(loc1, String.fromCharCode(char1)); - // Strategy C: insert character - } else if (selection >= 4) { - var char1 = 32 + Math.floor(Math.random() * 95); - var loc1 = Math.floor((modifiedPW.length + 1) * Math.random()); - modifiedPW = modifiedPW.slice(0, loc1) + String.fromCharCode(char1) + modifiedPW.slice(loc1); - deltas = deltas.slice(0, loc1).concat(1, deltas.slice(loc1)); - } - - // Check the modification's compliance with the password-composition policy - var currentUsername = this.$("#usernamebox").val() as string; - - var verified = RuleFunctions.RuleFunctions.verifyMinimumRequirements(modifiedPW, currentUsername); - if (verified.compliant) { - // If it complies with the policy - this.recommendedFixes[originalPW] = modifiedPW; - this.deltaHighlighted[modifiedPW] = deltas; - if (this.verboseMode) { - console.log("identified " + modifiedPW + " as a potential fix for " + originalPW); - } - if (typeof (this.recommendedFixesTries[originalPW]) === "undefined") { - this.recommendedFixesTries[originalPW] = 1; - } else { - this.recommendedFixesTries[originalPW] = this.recommendedFixesTries[originalPW] + 1; - } - this.spawnFixedRating(modifiedPW); // score the candidate in the background - // If it does not comply, recursively calls itself to try again. - } else { - depth++; - if (depth < 8) { - this.generateCandidateFixed(pw, depth, originalPW); - } - } - return 1; - } - - // A modification of the main function for starting the password-rating process - // that instead works to score a candidate concrete suggestion we've auto-generated. - // This function determines whether we've already calculated scores for - // a given password using both heuristics and neural networks. - // If so, call the function to show results. - // If not (undefined mappings), change the mappings temporarily to -1 - // and spawn the ratings. - // When those functions return, display will be called via callbacks. - spawnFixedRating(pw: string): void { - var nni = PasswordMeter.PasswordMeter.instance.getNN(); - var nnFixed = nni.nnfixed; - var username = this.$("#usernamebox").val() as string; - if (typeof (this.neuralnetMapping[pw]) === "undefined") { - this.neuralnetMapping[pw] = -1; // signal that we are calculating it to avoid duplicate work - nnFixed.query_guess_number(pw); // asynchronously calculate neural network guess number - } - if (typeof (this.heuristicMapping[pw]) === "undefined") { - this.queryHeuristicGuessNumber(pw, username, false); - // To avoid duplicating call when the heuristic function returns - } else if (this.neuralnetMapping[pw] >= 0 && this.heuristicMapping[pw] >= 0) { - this.synthesizeFixed(pw); - } - } - - // Called when we return new guessing evaluations of a concrete suggestion, - // this function synthesizes the results and (if the concrete suggestion is - // sufficiently strong) updates the array mapping passwords to suggested ones. - // It can only synthesize results, though, if both heuristics and neural - // networks have returned. - synthesizeFixed(fixedpw: string): number { - var overallScore: number = 0; - var numberOfScores: number = 0; - var changedAnyMappings: boolean = false; - if (typeof (this.heuristicMapping[fixedpw]) !== "undefined" - && this.heuristicMapping[fixedpw] >= 0) { - numberOfScores++; - overallScore = this.heuristicMapping[fixedpw]; - } - if (typeof (this.neuralnetMapping[fixedpw]) !== "undefined" - && this.neuralnetMapping[fixedpw] >= 0 && isFinite(this.neuralnetMapping[fixedpw])) { - numberOfScores++; - if (overallScore === 0 - || (overallScore > 0 && this.neuralnetMapping[fixedpw] < overallScore)) { - overallScore = this.neuralnetMapping[fixedpw]; - } - } - if (this.verboseMode) { - console.log("potential fixed " + fixedpw + " from heuristic (" - + this.heuristicMapping[fixedpw] + ") and neural nets (" - + this.neuralnetMapping[fixedpw] + ")" + " " + numberOfScores); - } - // When we have a sufficiently strong concrete suggestion, - // find all original passwords that include that as a potential fix - // and set it as the mapping - if (numberOfScores === 2 && overallScore >= 67) { - if (this.verboseMode) { - console.log(fixedpw + " is a plausible fix above the 2/3rds threshold"); - } - for (var j in this.recommendedFixes) { - if (this.recommendedFixes[j] === fixedpw - && typeof (this.fixedpwMapping[j]) === "undefined") { - // Now check to make sure this improves the original password - var originalOverallScore: number = 0; - if (typeof (this.heuristicMapping[j]) !== "undefined" - && this.heuristicMapping[j] >= 0) { - originalOverallScore = this.heuristicMapping[j]; - } - if (typeof (this.neuralnetMapping[j]) !== "undefined" - && this.neuralnetMapping[j] >= 0 - && isFinite(this.neuralnetMapping[j])) { - if (originalOverallScore === 0 - || (originalOverallScore > 0 - && this.neuralnetMapping[j] < originalOverallScore)) { - originalOverallScore = this.neuralnetMapping[j]; - } - } - if (overallScore > (originalOverallScore + 15)) { - this.fixedpwMapping[j] = fixedpw; - if (this.verboseMode) { - console.log("mapping " + j + " to " + fixedpw); - } - changedAnyMappings = true; - } else { - if (this.verboseMode) { - console.log("not mapping " + j + " to " + fixedpw + " because it is not enough of an improvement " + originalOverallScore + " --> " + overallScore); - } - } - } - } - // Re-rate things and thus display if we have changed any mappings - if (changedAnyMappings) { - this.spawnRating(); - } - return 1; - } - // Try recursively adding more to the password (to a depth), - // but only if it's still the current password (avoid extra computation) - var currentpw = this.$("#pwbox").val() as string; - // If the modal is open, the current password is actually what's there - if (this.$("#myModal").data("bs.modal") && this.$("#myModal").data("bs.modal").isShown) { - currentpw = this.$("#pwboxModal").val() as string; - } - if (this.recommendedFixes[currentpw] === fixedpw - && numberOfScores === 2 - && typeof (this.fixedpwMapping[currentpw]) === "undefined" - && typeof (this.recommendedFixesTries[currentpw]) !== "undefined" - && this.recommendedFixesTries[currentpw] < 8) { - // Try to generate a better concrete suggestion - if (this.verboseMode) { - console.log("trying again on " + fixedpw + " as current password is " + currentpw); - } - this.generateCandidateFixed(fixedpw, 0, currentpw); - } - return 1; - } - - // A function used to avoid showing redundant text feedback - // generated by different scoring functions. - // Returns true (redundant with previous feedback) or false (not redundant). - redundant(problemText: string, arrayOfProblems: Array): boolean { - // Lowercase since some rule functions lowercase feedback - problemText = problemText.toLowerCase(); - for (var i = 0; i < arrayOfProblems.length; i++) { - arrayOfProblems[i] = arrayOfProblems[i].toLowerCase(); - if (arrayOfProblems[i].length > 0 && problemText.length > 0) { - if ((arrayOfProblems[i].indexOf(problemText) >= 0 - && problemText.length >= 0.7 * arrayOfProblems[i].length) - || (problemText.indexOf(arrayOfProblems[i]) >= 0 - && arrayOfProblems[i].length >= 0.7 * problemText.length)) { - return true; - } - } - } - return false; - } - - // This function calculates the advanced heuristics. - // It requires the password (pw), the username (username), - // and a boolean for which: - // *true indicates this is the primary password, so potentially change - // the bar when done calculating - // *false indicates we are rating a candidate concrete suggestion - queryHeuristicGuessNumber(pw: string, username: string, primaryPassword: boolean): void { - // Used to make 10^{15} fill 2/3rds of the bar - var scalingFactor = 67 / 15; - // We overwrite the password if they use contextual or blacklisted content - // and we need the original to make the correct mappings - var originalPW = pw; - var publictips: Array = []; - var sensitivetips: Array = []; - var reasonWhy: Array = []; - var problemText: Array = []; - - // Return JSON objects from all of the rule functions - var contextualObj = RuleFunctions.RuleFunctions.contextual(pw, [username]); - pw = contextualObj.remaining; - // If their whole password is contextual, we hit a type error - if (typeof (pw) === "undefined") { - pw = ""; - } - var blacklistObj = RuleFunctions.RuleFunctions.blacklist(pw); - pw = blacklistObj.remaining; - // If their whole password is blacklisted, we hit a type error - if (typeof (pw) === "undefined") { - pw = ""; - } - - var lenObj = RuleFunctions.RuleFunctions.pwLength(pw); - var classObj = RuleFunctions.RuleFunctions.characterClasses(pw); - var duplicatedObj = RuleFunctions.RuleFunctions.duplicatedCharacters(pw); - var repeatObj = RuleFunctions.RuleFunctions.repeats(pw); - var patternsObj = RuleFunctions.RuleFunctions.keyboardPatterns(pw); - var sequenceObj = RuleFunctions.RuleFunctions.repeatedSections(pw); - var structureObj = RuleFunctions.RuleFunctions.structurePredictable(pw); - var upperPredictableObj = RuleFunctions.RuleFunctions.uppercasePredictable(pw); - var digitsPredictableObj = RuleFunctions.RuleFunctions.digitsPredictable(pw); - var symbolsPredictableObj = RuleFunctions.RuleFunctions.symbolsPredictable(pw); - var upperObj = RuleFunctions.RuleFunctions.countUC(pw); - var lowerObj = RuleFunctions.RuleFunctions.countLC(pw); - var digitObj = RuleFunctions.RuleFunctions.countDIGS(pw); - var symbolObj = RuleFunctions.RuleFunctions.countSYMS(pw); - var dateObj = RuleFunctions.RuleFunctions.identifyDates(pw); - var minimumObj = RuleFunctions.RuleFunctions.verifyMinimumRequirements(pw, username); - var alphabeticsequenceObj = RuleFunctions.RuleFunctions.alphabeticSequenceCheck(pw); - var commonsubstringObj = RuleFunctions.RuleFunctions.commonSubstringCheck(pw); - var dictionaryCheckObj = RuleFunctions.RuleFunctions.combinedDictCheck(pw); - var substringArrayNoFilter = pw.listSubstringsNoFilter(4); - var commonpwObj = RuleFunctions.RuleFunctions.commonPwCheck(substringArrayNoFilter); - // Take the coefficients from our regression - var coefficients = [1.530, 0.3129, 0.9912, 0.04637, -0.03885, -0.1172, -0.2976, -0.0008581, -0.3008, -0.5566, 0, 0.9108, 0.7369, 0.7578, 0, -0.1213, -0.2402, -0.1364, -0.5534, 1.927, 0.001496, -0.3946]; - var subscores: Array = [1, lenObj.length, classObj.count, duplicatedObj.count, - repeatObj.count, patternsObj.score, sequenceObj.count, structureObj.score, - upperPredictableObj.score, digitsPredictableObj.score, symbolsPredictableObj.score, - upperObj.count, lowerObj.count, digitObj.count, symbolObj.count, dateObj.count, - alphabeticsequenceObj.count, commonsubstringObj.count, dictionaryCheckObj.length, - dictionaryCheckObj.dictionaryTokens, dictionaryCheckObj.substitutionCommonness, - commonpwObj.length]; - // The first value is the intercept - var overallScore = coefficients[0]; - // Take the remaining coefficients and multiply by the rule function score - for (var i = 1; i < coefficients.length; i++) { - overallScore += coefficients[i] * subscores[i]; - } - overallScore = overallScore * scalingFactor; - if (overallScore < (pw.length / 2)) { - overallScore = pw.length / 2; - } else if (overallScore > 100) { - overallScore = 100; - } - - // Save non-empty text feedback from the rule functions - if (contextualObj.publicText.length > 0) { - publictips.push(contextualObj.publicText); - sensitivetips.push(contextualObj.sensitiveText); - reasonWhy.push(contextualObj.reasonWhy); - problemText.push(contextualObj.problemText); - } - if (blacklistObj.publicText.length > 0) { - publictips.push(blacklistObj.publicText); - sensitivetips.push(blacklistObj.sensitiveText); - reasonWhy.push(blacklistObj.reasonWhy); - problemText.push(blacklistObj.problemText); - } - if (dictionaryCheckObj.publicText.length > 0 - && !this.redundant(dictionaryCheckObj.problemText, problemText)) { - publictips.push(dictionaryCheckObj.publicText); - sensitivetips.push(dictionaryCheckObj.sensitiveText); - reasonWhy.push(dictionaryCheckObj.reasonWhy); - problemText.push(dictionaryCheckObj.problemText); - } - if (patternsObj.publicText.length > 0) { - publictips.push(patternsObj.publicText); - sensitivetips.push(patternsObj.sensitiveText); - reasonWhy.push(patternsObj.reasonWhy); - problemText.push(patternsObj.problemText); - } - if (repeatObj.publicText.length > 0) { - publictips.push(repeatObj.publicText); - sensitivetips.push(repeatObj.sensitiveText); - reasonWhy.push(repeatObj.reasonWhy); - problemText.push(repeatObj.problemText); - } - if (dateObj.publicText.length > 0) { - publictips.push(dateObj.publicText); - sensitivetips.push(dateObj.sensitiveText); - reasonWhy.push(dateObj.reasonWhy); - problemText.push(dateObj.problemText); - } - if (sequenceObj.publicText.length > 0) { - publictips.push(sequenceObj.publicText); - sensitivetips.push(sequenceObj.sensitiveText); - reasonWhy.push(sequenceObj.reasonWhy); - problemText.push(sequenceObj.problemText); - } - if (alphabeticsequenceObj.publicText.length > 0) { - publictips.push(alphabeticsequenceObj.publicText); - sensitivetips.push(alphabeticsequenceObj.sensitiveText); - reasonWhy.push(alphabeticsequenceObj.reasonWhy); - problemText.push(alphabeticsequenceObj.problemText); - } - if (commonpwObj.publicText.length > 0 && !this.redundant(commonpwObj.problemText, problemText)) { - publictips.push(commonpwObj.publicText); - sensitivetips.push(commonpwObj.sensitiveText); - reasonWhy.push(commonpwObj.reasonWhy); - problemText.push(commonpwObj.problemText); - } - if (upperPredictableObj.publicText.length > 0) { - publictips.push(upperPredictableObj.publicText); - sensitivetips.push(upperPredictableObj.sensitiveText); - reasonWhy.push(upperPredictableObj.reasonWhy); - problemText.push(upperPredictableObj.problemText); - } - if (digitsPredictableObj.publicText.length > 0) { - publictips.push(digitsPredictableObj.publicText); - sensitivetips.push(digitsPredictableObj.sensitiveText); - reasonWhy.push(digitsPredictableObj.reasonWhy); - problemText.push(digitsPredictableObj.problemText); - } - if (symbolsPredictableObj.publicText.length > 0) { - publictips.push(symbolsPredictableObj.publicText); - sensitivetips.push(symbolsPredictableObj.sensitiveText); - reasonWhy.push(symbolsPredictableObj.reasonWhy); - problemText.push(symbolsPredictableObj.problemText); - } - if (duplicatedObj.publicText.length > 0) { - publictips.push(duplicatedObj.publicText); - sensitivetips.push(duplicatedObj.sensitiveText); - reasonWhy.push(duplicatedObj.reasonWhy); - problemText.push(duplicatedObj.problemText); - } - if (lenObj.publicText.length > 0) { - publictips.push(lenObj.publicText); - sensitivetips.push(lenObj.sensitiveText); - reasonWhy.push(lenObj.reasonWhy); - //problemText.push(lenObj.problemText); - } - if (symbolObj.publicText.length > 0) { - publictips.push(symbolObj.publicText); - sensitivetips.push(symbolObj.sensitiveText); - reasonWhy.push(symbolObj.reasonWhy); - //problemText.push(symbolObj.problemText); - } - if (upperObj.publicText.length > 0) { - publictips.push(upperObj.publicText); - sensitivetips.push(upperObj.sensitiveText); - reasonWhy.push(upperObj.reasonWhy); - //problemText.push(upperObj.problemText); - } - if (digitObj.publicText.length > 0) { - publictips.push(digitObj.publicText); - sensitivetips.push(digitObj.sensitiveText); - reasonWhy.push(digitObj.reasonWhy); - //problemText.push(digitObj.problemText); - } - if (lowerObj.publicText.length > 0) { - publictips.push(lowerObj.publicText); - sensitivetips.push(lowerObj.sensitiveText); - reasonWhy.push(lowerObj.reasonWhy); - //problemText.push(lowerObj.problemText); - } - if (commonsubstringObj.publicText.length > 0 && !this.redundant(commonsubstringObj.problemText, problemText)) { - publictips.push(commonsubstringObj.publicText); - sensitivetips.push(commonsubstringObj.sensitiveText); - reasonWhy.push(commonsubstringObj.reasonWhy); - //problemText.push(commonsubstringObj.problemText); - } - if (structureObj.publicText.length > 0) { - publictips.push(structureObj.publicText); - sensitivetips.push(structureObj.sensitiveText); - reasonWhy.push(structureObj.reasonWhy); - //problemText.push(structureObj.problemText); - } - - // Save the mapping of password to score - this.heuristicMapping[originalPW] = overallScore; - // Save the mapping of password to feedback - this.feedbackMapping[originalPW] = JSON.stringify({ - publictips1: publictips[0], - publictips2: publictips[1], - publictips3: publictips[2], - sensitivetips1: sensitivetips[0], - sensitivetips2: sensitivetips[1], - sensitivetips3: sensitivetips[2], - reasonWhy1: reasonWhy[0], - reasonWhy2: reasonWhy[1], - reasonWhy3: reasonWhy[2], - }); - - // Display the rating if it's the currently shown (primary) password - if (primaryPassword) { - this.displayRating(originalPW); - // also cache modifications to a fixed password - if (digitsPredictableObj.fixedPw.length > 0) { - this.previousCandidate[originalPW] = digitsPredictableObj.fixedPw; - this.deltaHighlighted[digitsPredictableObj.fixedPw] = digitsPredictableObj.deltas; - } else if (symbolsPredictableObj.fixedPw.length > 0) { - this.previousCandidate[originalPW] = symbolsPredictableObj.fixedPw; - this.deltaHighlighted[symbolsPredictableObj.fixedPw] = symbolsPredictableObj.deltas; - } - // Otherwise, we're just scoring a concrete suggestion - } else { - this.synthesizeFixed(originalPW); - } - } - - // set the mapping from the neural network - setNeuralnetMapping(pw: string, value: number): void { - this.neuralnetMapping[pw] = value; - } - - // Update all aspects of the UI (bar and text feedback) to reflect password. - // Note that the password score and feedback was generated + cached in other functions. - displayRating(pw: string): void { - var overallScore = 0; - var numberOfScores = 0; - if (pw.length > 0) { - if (typeof (this.heuristicMapping[pw]) !== "undefined" - && this.heuristicMapping[pw] >= 0) { - overallScore = this.heuristicMapping[pw]; - numberOfScores++; - } - if (typeof (this.neuralnetMapping[pw]) !== "undefined" - && this.neuralnetMapping[pw] >= 0 && isFinite(this.neuralnetMapping[pw])) { - numberOfScores++; - if (overallScore == 0 || (overallScore > 0 - && this.neuralnetMapping[pw] < overallScore)) { - overallScore = this.neuralnetMapping[pw]; - } - } - } - if (overallScore < pw.length / 2) { - overallScore = pw.length / 2; // make people see at least some progess is happening - } - - if (this.verboseMode) { - console.log(pw + " overall from heuristic (" + this.heuristicMapping[pw] + ") and neural nets (" + this.neuralnetMapping[pw] + ")"); - } - - // Avoid errors in case the feedback mapping was somehow screwed up - if (typeof (this.feedbackMapping[pw]) === "undefined") { - this.feedbackMapping[pw] = JSON.stringify({ - publictips1: "", - publictips2: "", - publictips3: "", - sensitivetips1: "", - sensitivetips2: "", - sensitivetips3: "", - reasonWhy1: "", - reasonWhy2: "", - reasonWhy3: "", - }); - } - var feedback = JSON.parse(this.feedbackMapping[pw]); - - var config = PasswordMeter.PasswordMeter.instance.getConfig(); - - var currentUsername = this.$("#usernamebox").val() as string; - var nni = PasswordMeter.PasswordMeter.instance.getNN(); - - var minReqObj = RuleFunctions.RuleFunctions.verifyMinimumRequirements(pw, currentUsername); - // If password complies with password policy, show feedback - if (minReqObj.compliant) { - this.inCompliance = true; - if (pw.length === 0 || !nni.heardFromNn() || numberOfScores === 2) { - this.displayBar(overallScore, true); - } - this.$(".detailedFeedback").show(); - - // For the non-modal display - // Show the button for the password-specific modal - this.$(".portalToGenericAdviceModal").hide(); - // Show (Why?) buttons that bring people to the modal - this.$(".explainWhy").show(); - // Show only 3 tips for improving the password - this.$("#nonmodalRow1").show(); - this.$("#nonmodalRow2").show(); - this.$("#nonmodalRow3").show(); - this.$("#nonmodalRow4").hide(); - this.$("#nonmodalRow5").hide(); - this.$("#nonmodalRow6").hide(); - this.$("#nonmodalRow7").hide(); - this.$("#nonmodalRow8").hide(); - // Also show the confirm password box - this.$("#confirmpw").show(); - - // For the modal display - // First hide all and then show the relevant ones - this.$(".modalRow").hide(); - this.$("#modalRow1").show(); - this.$("#modalRow1a").show(); - this.$("#modalRow2").show(); - this.$("#modalRow2a").show(); - this.$("#modalRow3").show(); - this.$("#modalRow3a").show(); - - // If we have < 3 pieces of feedback, hide relevant rows - if (typeof (feedback.publictips3) === "undefined") { - this.$("#nonmodalRow3").hide(); - this.$("#modalRow3").hide(); - this.$("#modalRow3a").hide(); - } - if (typeof (feedback.publictips2) === "undefined") { - this.$("#nonmodalRow2").hide(); - this.$("#modalRow2").hide(); - this.$("#modalRow2a").hide(); - } - if (typeof (feedback.publictips1) === "undefined") { - this.$("#nonmodalRow1").hide(); - this.$("#modalRow1").hide(); - this.$("#modalRow1a").hide(); - } - - // Display text heading reflecting the score - if (overallScore <= 33) { - var feedbackWeak = "Your password is very easy to guess."; - this.$("#feedbackHeaderText").html(feedbackWeak); - this.$("#feedbackHeaderTextModal").html(feedbackWeak); - } else if (overallScore <= 66) { - var feedbackLowMedium = "Your password could be better."; - this.$("#feedbackHeaderText").html(feedbackLowMedium); - this.$("#feedbackHeaderTextModal").html(feedbackLowMedium); - } else if (overallScore < 100) { - var feedbackHighMedium = "Your password is pretty good."; - if (config.remindAgainstReuse) { - feedbackHighMedium += " Use it only for this account. (Why?)"; - } - feedbackHighMedium += "

 

To make it even better:"; - this.$("#feedbackHeaderText").html(feedbackHighMedium); - this.$("#feedbackHeaderTextModal").html(feedbackHighMedium); - } else { - var feedbackStrong = "Your password appears strong."; - if (config.remindAgainstReuse) { - feedbackStrong += " Make sure you use it only for this account. (Why?)"; - } - this.$("#feedbackHeaderText").html(feedbackStrong); - this.$("#feedbackHeaderTextModal").html(feedbackStrong); - } - - // Show colored boxes taken away when non-compliant with the password policy - this.$(".nonmodalColorCell").show(); - this.$(".modalColorCell").show(); - this.$(".modalColorCellSpacer").show(); - - // Populate table with appropriate feedback - this.$(".recommended").show(); - // If they are showing their password, use sensitive feedback - if (this.$("#showHidePWNonModal").prop("checked") === true) { - this.$(".fixedPWavailablePortal").hide(); - this.$(".concreteSuggestionDiv").show(); - // Non-modal - this.$("#tipText1").html(feedback.sensitivetips1); - this.$("#tipText2").html(feedback.sensitivetips2); - this.$("#tipText3").html(feedback.sensitivetips3); - // Modal - this.$("#suggestion1").html(feedback.sensitivetips1); - this.$("#suggestion2").html(feedback.sensitivetips2); - this.$("#suggestion3").html(feedback.sensitivetips3); - this.$("#sensText1").html(feedback.reasonWhy1); - this.$("#sensText2").html(feedback.reasonWhy2); - this.$("#sensText3").html(feedback.reasonWhy3); - } else { - this.$(".fixedPWavailablePortal").show(); - this.$(".concreteSuggestionDiv").hide(); - // Non-modal - this.$("#tipText1").html(feedback.publictips1); - this.$("#tipText2").html(feedback.publictips2); - this.$("#tipText3").html(feedback.publictips3); - // Modal - this.$("#suggestion1").html(feedback.publictips1); - this.$("#suggestion2").html(feedback.publictips2); - this.$("#suggestion3").html(feedback.publictips3); - this.$("#sensText1").html(feedback.reasonWhy1); - this.$("#sensText2").html(feedback.reasonWhy2); - this.$("#sensText3").html(feedback.reasonWhy3); - } - - // Recommend a concrete suggestion if we have one - if (typeof (this.fixedpwMapping[pw]) !== "undefined") { - // Change colors to highlight what was modified - var coloredFixedPW = ""; - var whereToColor = this.deltaHighlighted[this.fixedpwMapping[pw]]; - var proposedPassword = this.fixedpwMapping[pw]; - for (var j = 0; j < proposedPassword.length; j++) { - if (whereToColor[j] === 1) { - coloredFixedPW += "" + proposedPassword[j].escapeHTML() + ""; - } else { - coloredFixedPW += proposedPassword[j].escapeHTML(); - } - } - this.$(".fixedPW").html(coloredFixedPW); - // If we don't yet have a concrete suggestion - } else { - this.$(".recommended").hide(); - } - - // Hide the feedback if the score is high enough - if (overallScore <= 66) { - this.$("#nonmodalFeedbackTable").show(); - this.$("#modalFeedbackTable").show(); - this.$(".portalToGenericAdviceModal").show(); - } else if (overallScore < 100) { - this.$("#nonmodalFeedbackTable").show(); - this.$("#modalFeedbackTable").show(); - this.$(".portalToGenericAdviceModal").show(); - // If they already took a concrete suggestion, don't show another - if (this.tookSuggestion) { - this.$(".recommended").hide(); - this.$(".portalToGenericAdviceModal").hide(); - } - } else { - this.$("#nonmodalFeedbackTable").hide(); - this.$("#modalFeedbackTable").hide(); - this.$(".recommended").hide(); - // Don't show any modal buttons since score is high - this.$(".portalToGenericAdviceModal").hide(); - } - // However, if the password is not yet compliant with the policy - } else { - this.inCompliance = false; - var nni = PasswordMeter.PasswordMeter.instance.getNN(); - - if (pw.length === 0 || !nni.heardFromNn() || numberOfScores === 2) { - this.displayBar(overallScore, false); - } - // Don't let them confirm a non-compliant password - this.$("#confirmpw").hide(); - this.$(".detailedFeedback").hide(); - // Show the button for the generic modal window - this.$(".portalToGenericAdviceModal").show(); - // Hide (Why?) buttons that bring people to the specific-advice modal - this.$(".explainWhy").hide(); - // Explain what doesn't comply - var requirementsHeader = ""; - var config: Config.Config.Config = PasswordMeter.PasswordMeter.instance.getConfig(); - if (config.remindAgainstReuse) { - requirementsHeader = "Don't reuse a password from another account! (Why?)

 

"; - } - var nonCompliantAdmonition = "Your password must:"; - this.$("#feedbackHeaderText").html(requirementsHeader + nonCompliantAdmonition); - this.$("#feedbackHeaderTextModal").html(requirementsHeader + nonCompliantAdmonition); - this.$("#nonmodalFeedbackTable").show(); - this.$(".recommended").hide(); - - // Give text feedback about how they fail to comply with policy - var policyGripes = []; - var detail = minReqObj.detail; - for (var metric in detail.compliance) { - if (!detail.compliance[metric]) { - policyGripes.push(detail.explanation[metric]); - } - } - - // Hide the color cells - this.$(".nonmodalColorCell").hide(); - this.$(".modalColorCell").hide(); - this.$(".modalColorCellSpacer").hide(); - // Hide all of the rows, and then re-show them as necessary below - this.$(".nonmodalRow").hide(); - this.$(".modalRow").hide(); - - for (var i = 0 ; i < policyGripes.length; i++) { - var nmRow = this.$("#nonmodalRow"+(i+1)); - var tipText = this.$("#tipText"+(i+1)); - var mRow = this.$("#modalRow"+(i+1)); - var suggestion = this.$("#suggestion"+(i+1)); - var gripe = policyGripes[i]; - - nmRow.show(); - tipText.html(gripe); - mRow.show(); - suggestion.html(gripe); - } - - } - - // Start trying to generate a concrete suggestion - var nni = PasswordMeter.PasswordMeter.instance.getNN(); - - if ((pw.length === 0 || !nni.heardFromNn() || numberOfScores === 2) - && minReqObj.compliant && typeof (this.fixedpwMapping[pw]) === "undefined" - && overallScore < 100) { - this.generateCandidateFixed(pw, 0, pw); - } - } - - // This function displays the colored bar. It requires the password's score - // (expected range 0-100) and a boolean metRequirements indicating yes (true) - // to display the bar in color or no (false) to display the bar in grayscale - // until the requirements have been met. - displayBar(score: number, metRequirements: boolean): void { - // Adjust score if outside the range - if (score < 0) { - score = 0; - } - if (score > 100) { - score = 100; - } - - // determine bar color - var scoreProportion = score / 100; - var barcolor = "rgb(160,160,160)"; - // Initially go from RGB 255,0,0 towards 255,140,0 - if (metRequirements && scoreProportion < 0.45) { - barcolor = "rgb(" + Math.round(255) + "," - + Math.round(scoreProportion / 0.45 * 140) + ",0)"; - // Then go from RGB 255,140,0 towards 255,215,0 - } else if (metRequirements && scoreProportion >= 0.45 && scoreProportion < 0.65) { - barcolor = "rgb(" + Math.round(255) + "," - + Math.round((scoreProportion - 0.45) / 0.20 * 75 + 140) + ",0)"; - // Then go from 255,215,0 towards 50,205,50 - } else if (metRequirements) { - barcolor = "rgb(" + Math.round(255 - (scoreProportion - 0.65) / 0.35 * 205) - + "," + Math.round(215 - (scoreProportion - 0.65) / 0.035) + ",0)"; - } - - // Display bar in main window - this.$("#cups-passwordmeter-span").css("width", Math.round(298 * score / 100).toString() + "px"); - this.$("#cups-passwordmeter-span").css("background-color", barcolor); - - // display bar in modal - this.$("#cups-passwordmeter-span-modal").css("width", Math.round(298 * score / 100).toString() + "px"); - this.$("#cups-passwordmeter-span-modal").css("background-color", barcolor); - } - - // css interaction - // potentialTODO this here? - getMaxOfArray(numArray: Array): number { - return Math.max.apply(null, numArray); - } - - expandHelpBut(): void { - this.$('#expandHelpDiv').show(); - this.$('#helpButton').hide(); - } - - modalShowCheck(): void { - //checks whether they've checked the box to show their password - if (this.$("#pwbox").prop("type") == "text") { - this.$('#myModal').show(); - this.storepw(); - // potentialTODO what is rate? mayberate? commenting. - //this.rateModal(); - } else if (this.$('#expandHelpDiv').is(':visible')) { - this.$('#myModal').show(); - this.storepw(); - // potentialTODO what is rate? mayberate? commenting. - //this.rateModal(); - } else { - this.expandHelpBut(); - } - } - - closeDiv(divName: string): void { - this.$(divName).hide(); - } - - // potentialTODO where do the fn params come from? - deselect(e: JQuery): void { - if ((this.$.fn as any).slideFadeToggle == undefined) { - (this.$.fn as any).slideFadeToggle = function (easing: string, callback: Function) { - return this.animate({ - opacity: 'toggle', - height: 'toggle' - }, 'fast', easing, callback); - }; - } - // potentialTODO force cast for our defined function - (this.$('.pop')).slideFadeToggle(function () { - e.removeClass('selected'); - }); - } - - } - - (function () { - var registry = PasswordMeter.PasswordMeter.instance; - var $ = registry.getJquery(); - var verboseMode = false; - var instance = new UIMisc(verboseMode); - registry.setUI(instance); - - $(document).ready(function () { - $("#showpassword").prop('checked', false); - $("#showpassword").click(function () { - document.getElementById("hide-show-label").textContent = "Hide Password"; - $("#cbbutton").css('background-color', '#f5f5f5'); - if ($("#pwbox").prop("type") == "password") { - $("#pwbox").prop("type", "text"); - } else { - $("#pwbox").prop("type", "password"); - document.getElementById("hide-show-label").textContent = "Show Password"; - $("#cbbutton").css('background-color', '#f5f5f5'); - } - // potentialTODO what is rate? mayberate? commenting. - //rate(); - }); - }); - - $(document).ready(function () { - var pw = $("#pwboxModal"); - $("#tip1, #sensText1").mouseover(function () { - pw.addClass("problemColor"); - }); - $("#tip2, #sensText2").mouseover(function () { - pw.addClass("problemColor"); - }); - $("#tip3, #sensText3").mouseover(function () { - pw.addClass("problemColor"); - }); - }); - - $(document).ready(function () { - instance.onReady(); - }); - - }()) + export class UIMisc { + helper: Helper.Helper.Helper; + $: JQueryStatic; + verboseMode: boolean; + + // Global variable to retain the password when the modal was opened, + // so that we later know whether or not to show a 'discard' button + private pwWhenModalOpened: string = ""; + + // Global variable indicating whether they ever clicked the concerete suggestion. + // If so, don't show them another fixed password unless they drop + // below the 2/3rds threshold. + private tookSuggestion: boolean = false; + + // Global variable to store what password's rating is currently shown + private previouslyRated: string = ""; + + // Previously computed information about password scores and feedback + // To avoid scoring things multiple times, store mappings in associative arrays + // -1 means that we already spawned a thread to perform this calculation, so don't duplicate it + // Mapping of passwords to score based on advanced heuristics + private heuristicMapping: { [key: string]: number } = {}; + + // Mapping of passwords to public/sensitive feedback + // potentialTODO that could get expensivex + // potentialTODO structure this + private feedbackMapping: { [key: string]: string } = {}; + + // Previously computed information about concrete suggestions + // Mapping of passwords to a potential concrete suggestion. + // If the suggestion is scored highly enough, then store it in fixedpwMapping. + private recommendedFixes: { [key: string]: string } = {}; + // To avoid excess computation, keep track of how many tries we've made + // trying to generate a strong concerete suggestion. If too many, + // give up rather than potentially cause UI lag. + private recommendedFixesTries: { [key: string]: number } = {}; + // Keep track of the previous candidate we tried for the concrete suggestion. + // If insufficiently strong, we'll want to modify it + private previousCandidate: { [key: string]: string } = {}; + // Final mapping of password to (pre-validated) stronger concrete suggestion + private fixedpwMapping: { [key: string]: string } = {}; + // How the concrete suggestion was modified from the original (for highlights) + private deltaHighlighted: { [key: string]: Array } = {}; + + // Globally keep track of whether the password is in compliance with the + // composition policy. We use this to decide whether to let them continue. + // We store this in a global to avoid double-calling the function each time. + private inCompliance: boolean = false; + + constructor(verboseMode: boolean) { + var registry = PasswordMeter.PasswordMeter.instance; + this.helper = registry.getHelper(); + this.$ = registry.getJquery(); + this.verboseMode = verboseMode; + } + + onReady(): void { + // Make the non-modal (feedback box) appear + this.$(".pop").fadeIn(); + // Reset hide/show checkbox in case they reloaded the page + // and call the function that shows password/******** based on it + this.$("#showHidePWNonModal").prop("checked", false); + this.toggleShowHideNonModal(); + // Rate the password in the box (if any) + this.spawnRating(); + } + + // This function switches between the password being ***** and shown in non-modal + toggleShowHideNonModal(): void { + if (this.$("#showHidePWNonModal").prop("checked")) { + this.$("#pwbox").prop("type", "text"); + this.$("#pwboxModal").prop("type", "text"); + // Make non-modal and modal checkboxes match + this.$("#showHidePWModal").prop("checked", true); + } else { + this.$("#pwbox").prop("type", "password"); + this.$("#pwboxModal").prop("type", "password"); + // Make non-modal and modal checkboxes match + this.$("#showHidePWModal").prop("checked", false); + } + this.spawnRating(); + } + + // This function switches between the password being ***** and shown in modal + toggleShowHideModal(): void { + if (this.$("#showHidePWModal").prop("checked")) { + this.$("#pwbox").prop("type", "text"); + this.$("#pwboxModal").prop("type", "text"); + // Make non-modal and modal checkboxes match + this.$("#showHidePWNonModal").prop("checked", true); + } else { + this.$("#pwbox").prop("type", "password"); + this.$("#pwboxModal").prop("type", "password"); + // Make non-modal and modal checkboxes match + this.$("#showHidePWNonModal").prop("checked", false); + } + this.spawnRating(); + } + + // Function called when the modal window is opened. + // Save what the password is at this point and transfer + // the password from the main window to the modal + storepw(): void { + var pw = this.$("#pwbox").val() as string; + this.pwWhenModalOpened = pw; + this.$("#pwboxModal").val(pw); + } + + // Show the discard button in the modal only if they edited the password field + enableDiscard(): void { + // If they haven't changed the password since opening the modal + if (this.$("#pwboxModal").val() === this.pwWhenModalOpened) { + this.$("#discardButton").hide(); + this.$("#keepButton").html("OK"); + } else { + this.$("#discardButton").show(); + this.$("#keepButton").html("Keep Changes"); + } + } + + // They chose to keep their modal-modified password, + // so transfer it to the main window + keeppw(): void { + this.$("#pwbox").val(this.$("#pwboxModal").val()); + } + + // If they click the concrete suggestion in the non-modal, put it in the password field + fixPWNonModal(): void { + // Note for later that they have taken a suggestion + this.tookSuggestion = true; + var newpw = this.$("#nonmodalFixedPW").text(); + this.$("#pwbox").val(newpw); + // Update the rating + this.spawnRating(); + } + + // If they click the concrete suggestion in the modal, put it in the password field + fixPWModal(): void { + this.tookSuggestion = true; + var pw = this.$("#modalFixedPW").text(); + this.$("#pwboxModal").val(pw); + this.spawnRating(); + this.enableDiscard(); + } + + // Set up the modal when they are initially showing it + showModal(): void { + this.storepw(); + this.$("#discardButton").hide(); + this.$("#keepButton").html("OK"); + this.$("#myModal").show(); + } + + // To save computation, only rate the password if it has changed + mayberate(): void { + if (this.$("#pwbox").val() !== this.previouslyRated) { + this.previouslyRated = this.$("#pwbox").val() as string; + this.spawnRating(); + } + } + + // When they try to submit, decide whether to let them continue + continueCheck(triedToSubmit: boolean): void { + var compliantOverall = true; + // Make sure username is non-empty + if (triedToSubmit) { + var username = this.$("#usernamebox").val() as string; + if (username.length < 1) { + this.$("#usernameTooShort").show(); + compliantOverall = false; + } else { + this.$("#usernameTooShort").hide(); + } + } + + // Check compliance with the password-composition policy + if (!this.inCompliance) { + compliantOverall = false; + // Also hide confirmation error messages + this.$("#confirmDoesNotMatch").hide(); + // Only turn red when they try to submit + if (triedToSubmit) { + this.$("#feedbackHeaderText").css({ + "color": "red", + "font-weight": "bold" + }); + this.$("#passwordNonCompliant").show(); + } + } else { + // It is in compliance, so turn everything back to normal + this.$("#feedbackHeaderText").css({ + "color": "", + "font-weight": "" + }); + this.$("#passwordNonCompliant").hide(); + } + // Check that the confirm box matches the password + if (this.$("#pwbox").val() !== this.$("#confirmbox").val()) { + compliantOverall = false; + // Only show the error when they try to submit a compliant pw + if (triedToSubmit && this.inCompliance) { + this.$("#confirmDoesNotMatch").show(); + } + } else { + this.$("#confirmDoesNotMatch").hide(); + } + // If meets policy, matches confirm, and they hit submit, let them + if (triedToSubmit && compliantOverall) { + alert("this would be submitted"); + } + } + + // translate NN guess number to a percentage-based score (based on stringency configuration). + // this will influence meter fill. + nnNumtoScoreAsPercent(nnNum: number): number { + if (nnNum > 0) { + return nnNum * Constants.Constants.METER_STRINGENCY_SCALE_FACTOR; + } else { + return nnNum; + } + } + + // The main function for starting the password-rating process. + // This function determines whether we've already calculated scores for + // a given password using both heuristics and neural networks. + // If so, call the function to show results. + // If not (undefined mappings), change the mappings temporarily to -1 + // and spawns the ratings. + // When those functions return, display will be called via callbacks. + spawnRating(): void { + var pw = ""; + var nni = PasswordMeter.PasswordMeter.instance.getNN(); + if (this.$("#myModal").data("bs.modal") && this.$("#myModal").data("bs.modal").isShown) { + pw = this.$("#pwboxModal").val() as string; + } else { + pw = this.$("#pwbox").val() as string; + } + var username = this.$("#usernamebox").val() as string; + var ratingsComplete = 0; + var nnNum = nni.getNeuralNetNum(pw); + + if (typeof (nnNum) === "undefined") { + // Signal that we are calculating it to avoid duplicate work + nni.setNeuralNetNum(pw, -1); + // Asynchronously calculate neural network guess number + nni.queryGuessNumber(pw, false); + } else if (nnNum >= 0) { + ratingsComplete++; + } + if (typeof (this.heuristicMapping[pw]) === "undefined") { + this.queryHeuristicGuessNumber(pw, username, true); + } else if (this.heuristicMapping[pw] >= 0) { + ratingsComplete++; + } + // If we have both ratings, or neural nets doesn't seem to work + // on this browser, or the password is empty, display the rating. + if (pw.length === 0 || !nni.heardFromNn() || ratingsComplete === 2) { + this.displayRating(pw); + } + } + + // This function tries to generate a candidate for the conrete suggestion + // following randomly chosen modification strategies. + // It requires the current candidate (pw), the current recursion depth (depth) + // to avoid causing lag, and the original version of the password (originalPW) + generateCandidateFixed(pw: string, depth: number, originalPW: string): number { + // We keep a vector that tracks changes we make to the password for + // future highlighting purposes. + var deltas: Array = []; + // If this is the initial call, initialize that vector + if (typeof (this.deltaHighlighted[pw]) === "undefined") { + for (var i = 0; i < pw.length; i++) { + deltas[i] = 0; + } + } else { + deltas = this.deltaHighlighted[pw]; + } + + // Get the current modification of the password + var modifiedPW = pw; + if (typeof (this.previousCandidate[pw]) !== "undefined") { + // We may have already moved digits or symbols + modifiedPW = this.previousCandidate[pw]; + deltas = this.deltaHighlighted[modifiedPW]; + } + + // Randomly select one of the strategies in a biased way + var selection = Math.floor(8 * Math.random()); + // Strategy A: toggle case + if (selection === 0 || selection === 1) { + var pwLen = modifiedPW.length; + var loc = Math.floor(pwLen * Math.random()); + if (modifiedPW.charCodeAt(loc) >= 65 && modifiedPW.charCodeAt(loc) <= 90) { + modifiedPW = modifiedPW.replaceAt(loc, String.fromCharCode(modifiedPW.charCodeAt(loc) + 32)); + deltas[loc] = 1; + } else if (modifiedPW.charCodeAt(loc) >= 97 && modifiedPW.charCodeAt(loc) <= 122) { + modifiedPW = modifiedPW.replaceAt(loc, String.fromCharCode(modifiedPW.charCodeAt(loc) - 32)); + deltas[loc] = 1; + } + // Strategy B: substitute character + } else if (selection === 2 || selection === 3) { + var char1 = 32 + Math.floor(Math.random() * 95); + var loc1 = Math.floor((modifiedPW.length) * Math.random()); + if (modifiedPW.charCodeAt(loc1) !== char1) { + deltas[loc1] = 1; + } + modifiedPW = modifiedPW.replaceAt(loc1, String.fromCharCode(char1)); + // Strategy C: insert character + } else if (selection >= 4) { + var char1 = 32 + Math.floor(Math.random() * 95); + var loc1 = Math.floor((modifiedPW.length + 1) * Math.random()); + modifiedPW = modifiedPW.slice(0, loc1) + String.fromCharCode(char1) + modifiedPW.slice(loc1); + deltas = deltas.slice(0, loc1).concat(1, deltas.slice(loc1)); + } + + // score the candidate in the background, if needed + var nni = PasswordMeter.PasswordMeter.instance.getNN(); + if (typeof (nni.getNeuralNetNum(modifiedPW)) === "undefined") { + nni.setNeuralNetNum(modifiedPW, -1); // signal that we are calculating it to avoid duplicate work + nni.queryGuessNumber(modifiedPW, true); // asynchronously calculate neural network guess number + } + + // Check the modification's compliance with the password-composition policy + var currentUsername = this.$("#usernamebox").val() as string; + + var verified = RuleFunctions.RuleFunctions.verifyMinimumRequirements(modifiedPW, currentUsername); + if (verified.compliant) { + // If it complies with the policy + this.recommendedFixes[originalPW] = modifiedPW; + this.deltaHighlighted[modifiedPW] = deltas; + if (this.verboseMode) { + console.log("identified " + modifiedPW + " as a potential fix for " + originalPW); + } + if (typeof (this.recommendedFixesTries[originalPW]) === "undefined") { + this.recommendedFixesTries[originalPW] = 1; + } else { + this.recommendedFixesTries[originalPW] = this.recommendedFixesTries[originalPW] + 1; + } + this.spawnFixedRating(modifiedPW); + // If it does not comply, recursively calls itself to try again. + } else { + depth++; + if (depth < 8) { + this.generateCandidateFixed(pw, depth, originalPW); + } + } + return 1; + } + + // A modification of the main function for starting the password-rating process + // that instead works to score a candidate concrete suggestion we've auto-generated. + // This function determines whether we've already calculated scores for + // a given password using both heuristics and neural networks. + // If so, call the function to show results. + // When those functions return, display will be called via callbacks. + spawnFixedRating(pw: string): void { + var nni = PasswordMeter.PasswordMeter.instance.getNN(); + var username = this.$("#usernamebox").val() as string; + if (typeof (this.heuristicMapping[pw]) === "undefined") { + this.queryHeuristicGuessNumber(pw, username, false); + // To avoid duplicating call when the heuristic function returns + } else if (nni.getNeuralNetNum(pw) >= 0 && this.heuristicMapping[pw] >= 0) { + this.synthesizeFixed(pw); + } + } + + // Called when we return new guessing evaluations of a concrete suggestion, + // this function synthesizes the results and (if the concrete suggestion is + // sufficiently strong) updates the array mapping passwords to suggested ones. + // It can only synthesize results, though, if both heuristics and neural + // networks have returned. + synthesizeFixed(fixedpw: string): number { + var nni = PasswordMeter.PasswordMeter.instance.getNN(); + var overallScore: number = 0; + var numberOfScores: number = 0; + var changedAnyMappings: boolean = false; + if (typeof (this.heuristicMapping[fixedpw]) !== "undefined" + && this.heuristicMapping[fixedpw] >= 0) { + numberOfScores++; + overallScore = this.heuristicMapping[fixedpw]; + } + var nnNum = nni.getNeuralNetNum(fixedpw); + var nnScoreAsPercent = this.nnNumtoScoreAsPercent(nnNum); + + if (typeof (nnNum) !== "undefined" + && nnScoreAsPercent >= 0 && isFinite(nnScoreAsPercent)) { + numberOfScores++; + if (overallScore === 0 + || (overallScore > 0 && nnScoreAsPercent < overallScore)) { + overallScore = nnScoreAsPercent; + } + } + if (this.verboseMode) { + console.log("potential fixed " + fixedpw + " from heuristic (" + + this.heuristicMapping[fixedpw] + ") and neural nets (" + + nnScoreAsPercent + ")" + " " + numberOfScores); + } + // When we have a sufficiently strong concrete suggestion, + // find all original passwords that include that as a potential fix + // and set it as the mapping + if (numberOfScores === 2 && overallScore >= 67) { + if (this.verboseMode) { + console.log(fixedpw + " is a plausible fix above the 2/3rds threshold"); + } + for (var j in this.recommendedFixes) { + if (this.recommendedFixes[j] === fixedpw + && typeof (this.fixedpwMapping[j]) === "undefined") { + // Now check to make sure this improves the original password + var originalOverallScore: number = 0; + if (typeof (this.heuristicMapping[j]) !== "undefined" + && this.heuristicMapping[j] >= 0) { + originalOverallScore = this.heuristicMapping[j]; + } + var nnNumFix = nni.getNeuralNetNum(j); + var nnScoreAsPercentFix = this.nnNumtoScoreAsPercent(nnNumFix); + if (typeof (nnNumFix) !== "undefined" + && nnScoreAsPercentFix >= 0 + && isFinite(nnScoreAsPercentFix)) { + if (originalOverallScore === 0 + || (originalOverallScore > 0 + && nnScoreAsPercentFix < originalOverallScore)) { + originalOverallScore = nnScoreAsPercentFix; + } + } + if (overallScore > (originalOverallScore + 15)) { + this.fixedpwMapping[j] = fixedpw; + if (this.verboseMode) { + console.log("mapping " + j + " to " + fixedpw); + } + changedAnyMappings = true; + } else { + if (this.verboseMode) { + console.log("not mapping " + j + " to " + fixedpw + " because it is not enough of an improvement " + originalOverallScore + " --> " + overallScore); + } + } + } + } + // Re-rate things and thus display if we have changed any mappings + if (changedAnyMappings) { + this.spawnRating(); + } + return 1; + } + // Try recursively adding more to the password (to a depth), + // but only if it's still the current password (avoid extra computation) + var currentpw = this.$("#pwbox").val() as string; + // If the modal is open, the current password is actually what's there + if (this.$("#myModal").data("bs.modal") && this.$("#myModal").data("bs.modal").isShown) { + currentpw = this.$("#pwboxModal").val() as string; + } + if (this.recommendedFixes[currentpw] === fixedpw + && numberOfScores === 2 + && typeof (this.fixedpwMapping[currentpw]) === "undefined" + && typeof (this.recommendedFixesTries[currentpw]) !== "undefined" + && this.recommendedFixesTries[currentpw] < 8) { + // Try to generate a better concrete suggestion + if (this.verboseMode) { + console.log("trying again on " + fixedpw + " as current password is " + currentpw); + } + this.generateCandidateFixed(fixedpw, 0, currentpw); + } + return 1; + } + + // A function used to avoid showing redundant text feedback + // generated by different scoring functions. + // Returns true (redundant with previous feedback) or false (not redundant). + redundant(problemText: string, arrayOfProblems: Array): boolean { + // Lowercase since some rule functions lowercase feedback + problemText = problemText.toLowerCase(); + for (var i = 0; i < arrayOfProblems.length; i++) { + arrayOfProblems[i] = arrayOfProblems[i].toLowerCase(); + if (arrayOfProblems[i].length > 0 && problemText.length > 0) { + if ((arrayOfProblems[i].indexOf(problemText) >= 0 + && problemText.length >= 0.7 * arrayOfProblems[i].length) + || (problemText.indexOf(arrayOfProblems[i]) >= 0 + && arrayOfProblems[i].length >= 0.7 * problemText.length)) { + return true; + } + } + } + return false; + } + + // This function calculates the advanced heuristics. + // It requires the password (pw), the username (username), + // and a boolean for which: + // *true indicates this is the primary password, so potentially change + // the bar when done calculating + // *false indicates we are rating a candidate concrete suggestion + queryHeuristicGuessNumber(pw: string, username: string, primaryPassword: boolean): void { + // Used to make 10^{15} fill 2/3rds of the bar + var scalingFactor = 67 / 15; + // We overwrite the password if they use contextual or blacklisted content + // and we need the original to make the correct mappings + var originalPW = pw; + var publictips: Array = []; + var sensitivetips: Array = []; + var reasonWhy: Array = []; + var problemText: Array = []; + + // Return JSON objects from all of the rule functions + var contextualObj = RuleFunctions.RuleFunctions.contextual(pw, [username]); + pw = contextualObj.remaining; + // If their whole password is contextual, we hit a type error + if (typeof (pw) === "undefined") { + pw = ""; + } + var blacklistObj = RuleFunctions.RuleFunctions.blacklist(pw); + pw = blacklistObj.remaining; + // If their whole password is blacklisted, we hit a type error + if (typeof (pw) === "undefined") { + pw = ""; + } + + var lenObj = RuleFunctions.RuleFunctions.pwLength(pw); + var classObj = RuleFunctions.RuleFunctions.characterClasses(pw); + var duplicatedObj = RuleFunctions.RuleFunctions.duplicatedCharacters(pw); + var repeatObj = RuleFunctions.RuleFunctions.repeats(pw); + var patternsObj = RuleFunctions.RuleFunctions.keyboardPatterns(pw); + var sequenceObj = RuleFunctions.RuleFunctions.repeatedSections(pw); + var structureObj = RuleFunctions.RuleFunctions.structurePredictable(pw); + var upperPredictableObj = RuleFunctions.RuleFunctions.uppercasePredictable(pw); + var digitsPredictableObj = RuleFunctions.RuleFunctions.digitsPredictable(pw); + var symbolsPredictableObj = RuleFunctions.RuleFunctions.symbolsPredictable(pw); + var upperObj = RuleFunctions.RuleFunctions.countUC(pw); + var lowerObj = RuleFunctions.RuleFunctions.countLC(pw); + var digitObj = RuleFunctions.RuleFunctions.countDIGS(pw); + var symbolObj = RuleFunctions.RuleFunctions.countSYMS(pw); + var dateObj = RuleFunctions.RuleFunctions.identifyDates(pw); + var minimumObj = RuleFunctions.RuleFunctions.verifyMinimumRequirements(pw, username); + var alphabeticsequenceObj = RuleFunctions.RuleFunctions.alphabeticSequenceCheck(pw); + var commonsubstringObj = RuleFunctions.RuleFunctions.commonSubstringCheck(pw); + var dictionaryCheckObj = RuleFunctions.RuleFunctions.combinedDictCheck(pw); + var substringArrayNoFilter = pw.listSubstringsNoFilter(4); + var commonpwObj = RuleFunctions.RuleFunctions.commonPwCheck(substringArrayNoFilter); + // Take the coefficients from our regression + var coefficients = [1.530, 0.3129, 0.9912, 0.04637, -0.03885, -0.1172, -0.2976, -0.0008581, -0.3008, -0.5566, 0, 0.9108, 0.7369, 0.7578, 0, -0.1213, -0.2402, -0.1364, -0.5534, 1.927, 0.001496, -0.3946]; + var subscores: Array = [1, lenObj.length, classObj.count, duplicatedObj.count, + repeatObj.count, patternsObj.score, sequenceObj.count, structureObj.score, + upperPredictableObj.score, digitsPredictableObj.score, symbolsPredictableObj.score, + upperObj.count, lowerObj.count, digitObj.count, symbolObj.count, dateObj.count, + alphabeticsequenceObj.count, commonsubstringObj.count, dictionaryCheckObj.length, + dictionaryCheckObj.dictionaryTokens, dictionaryCheckObj.substitutionCommonness, + commonpwObj.length]; + // The first value is the intercept + var overallScore = coefficients[0]; + // Take the remaining coefficients and multiply by the rule function score + for (var i = 1; i < coefficients.length; i++) { + overallScore += coefficients[i] * subscores[i]; + } + overallScore = overallScore * scalingFactor; + if (overallScore < (pw.length / 2)) { + overallScore = pw.length / 2; + } else if (overallScore > 100) { + overallScore = 100; + } + + // Save non-empty text feedback from the rule functions + if (contextualObj.publicText.length > 0) { + publictips.push(contextualObj.publicText); + sensitivetips.push(contextualObj.sensitiveText); + reasonWhy.push(contextualObj.reasonWhy); + problemText.push(contextualObj.problemText); + } + if (blacklistObj.publicText.length > 0) { + publictips.push(blacklistObj.publicText); + sensitivetips.push(blacklistObj.sensitiveText); + reasonWhy.push(blacklistObj.reasonWhy); + problemText.push(blacklistObj.problemText); + } + if (dictionaryCheckObj.publicText.length > 0 + && !this.redundant(dictionaryCheckObj.problemText, problemText)) { + publictips.push(dictionaryCheckObj.publicText); + sensitivetips.push(dictionaryCheckObj.sensitiveText); + reasonWhy.push(dictionaryCheckObj.reasonWhy); + problemText.push(dictionaryCheckObj.problemText); + } + if (patternsObj.publicText.length > 0) { + publictips.push(patternsObj.publicText); + sensitivetips.push(patternsObj.sensitiveText); + reasonWhy.push(patternsObj.reasonWhy); + problemText.push(patternsObj.problemText); + } + if (repeatObj.publicText.length > 0) { + publictips.push(repeatObj.publicText); + sensitivetips.push(repeatObj.sensitiveText); + reasonWhy.push(repeatObj.reasonWhy); + problemText.push(repeatObj.problemText); + } + if (dateObj.publicText.length > 0) { + publictips.push(dateObj.publicText); + sensitivetips.push(dateObj.sensitiveText); + reasonWhy.push(dateObj.reasonWhy); + problemText.push(dateObj.problemText); + } + if (sequenceObj.publicText.length > 0) { + publictips.push(sequenceObj.publicText); + sensitivetips.push(sequenceObj.sensitiveText); + reasonWhy.push(sequenceObj.reasonWhy); + problemText.push(sequenceObj.problemText); + } + if (alphabeticsequenceObj.publicText.length > 0) { + publictips.push(alphabeticsequenceObj.publicText); + sensitivetips.push(alphabeticsequenceObj.sensitiveText); + reasonWhy.push(alphabeticsequenceObj.reasonWhy); + problemText.push(alphabeticsequenceObj.problemText); + } + if (commonpwObj.publicText.length > 0 && !this.redundant(commonpwObj.problemText, problemText)) { + publictips.push(commonpwObj.publicText); + sensitivetips.push(commonpwObj.sensitiveText); + reasonWhy.push(commonpwObj.reasonWhy); + problemText.push(commonpwObj.problemText); + } + if (upperPredictableObj.publicText.length > 0) { + publictips.push(upperPredictableObj.publicText); + sensitivetips.push(upperPredictableObj.sensitiveText); + reasonWhy.push(upperPredictableObj.reasonWhy); + problemText.push(upperPredictableObj.problemText); + } + if (digitsPredictableObj.publicText.length > 0) { + publictips.push(digitsPredictableObj.publicText); + sensitivetips.push(digitsPredictableObj.sensitiveText); + reasonWhy.push(digitsPredictableObj.reasonWhy); + problemText.push(digitsPredictableObj.problemText); + } + if (symbolsPredictableObj.publicText.length > 0) { + publictips.push(symbolsPredictableObj.publicText); + sensitivetips.push(symbolsPredictableObj.sensitiveText); + reasonWhy.push(symbolsPredictableObj.reasonWhy); + problemText.push(symbolsPredictableObj.problemText); + } + if (duplicatedObj.publicText.length > 0) { + publictips.push(duplicatedObj.publicText); + sensitivetips.push(duplicatedObj.sensitiveText); + reasonWhy.push(duplicatedObj.reasonWhy); + problemText.push(duplicatedObj.problemText); + } + if (lenObj.publicText.length > 0) { + publictips.push(lenObj.publicText); + sensitivetips.push(lenObj.sensitiveText); + reasonWhy.push(lenObj.reasonWhy); + //problemText.push(lenObj.problemText); + } + if (symbolObj.publicText.length > 0) { + publictips.push(symbolObj.publicText); + sensitivetips.push(symbolObj.sensitiveText); + reasonWhy.push(symbolObj.reasonWhy); + //problemText.push(symbolObj.problemText); + } + if (upperObj.publicText.length > 0) { + publictips.push(upperObj.publicText); + sensitivetips.push(upperObj.sensitiveText); + reasonWhy.push(upperObj.reasonWhy); + //problemText.push(upperObj.problemText); + } + if (digitObj.publicText.length > 0) { + publictips.push(digitObj.publicText); + sensitivetips.push(digitObj.sensitiveText); + reasonWhy.push(digitObj.reasonWhy); + //problemText.push(digitObj.problemText); + } + if (lowerObj.publicText.length > 0) { + publictips.push(lowerObj.publicText); + sensitivetips.push(lowerObj.sensitiveText); + reasonWhy.push(lowerObj.reasonWhy); + //problemText.push(lowerObj.problemText); + } + if (commonsubstringObj.publicText.length > 0 && !this.redundant(commonsubstringObj.problemText, problemText)) { + publictips.push(commonsubstringObj.publicText); + sensitivetips.push(commonsubstringObj.sensitiveText); + reasonWhy.push(commonsubstringObj.reasonWhy); + //problemText.push(commonsubstringObj.problemText); + } + if (structureObj.publicText.length > 0) { + publictips.push(structureObj.publicText); + sensitivetips.push(structureObj.sensitiveText); + reasonWhy.push(structureObj.reasonWhy); + //problemText.push(structureObj.problemText); + } + + // Save the mapping of password to score + this.heuristicMapping[originalPW] = overallScore; + // Save the mapping of password to feedback + this.feedbackMapping[originalPW] = JSON.stringify({ + publictips1: publictips[0], + publictips2: publictips[1], + publictips3: publictips[2], + sensitivetips1: sensitivetips[0], + sensitivetips2: sensitivetips[1], + sensitivetips3: sensitivetips[2], + reasonWhy1: reasonWhy[0], + reasonWhy2: reasonWhy[1], + reasonWhy3: reasonWhy[2], + }); + + // Display the rating if it's the currently shown (primary) password + if (primaryPassword) { + this.displayRating(originalPW); + // also cache modifications to a fixed password + if (digitsPredictableObj.fixedPw.length > 0) { + this.previousCandidate[originalPW] = digitsPredictableObj.fixedPw; + this.deltaHighlighted[digitsPredictableObj.fixedPw] = digitsPredictableObj.deltas; + } else if (symbolsPredictableObj.fixedPw.length > 0) { + this.previousCandidate[originalPW] = symbolsPredictableObj.fixedPw; + this.deltaHighlighted[symbolsPredictableObj.fixedPw] = symbolsPredictableObj.deltas; + } + // Otherwise, we're just scoring a concrete suggestion + } else { + this.synthesizeFixed(originalPW); + } + } + + + + // Update all aspects of the UI (bar and text feedback) to reflect password. + // Note that the password score and feedback was generated + cached in other functions. + displayRating(pw: string): void { + var nni = PasswordMeter.PasswordMeter.instance.getNN(); + var overallScore = 0; + var numberOfScores = 0; + if (pw.length > 0) { + if (typeof (this.heuristicMapping[pw]) !== "undefined" + && this.heuristicMapping[pw] >= 0) { + overallScore = this.heuristicMapping[pw]; + numberOfScores++; + } + var nnNum = nni.getNeuralNetNum(pw); + var nnScoreAsPercent = this.nnNumtoScoreAsPercent(nnNum); + if (typeof (nnNum) !== "undefined" + && nnScoreAsPercent >= 0 && isFinite(nnScoreAsPercent)) { + numberOfScores++; + if (overallScore == 0 || (overallScore > 0 + && nnScoreAsPercent < overallScore)) { + overallScore = nnScoreAsPercent; + } + } + } + if (overallScore < pw.length / 2) { + overallScore = pw.length / 2; // make people see at least some progess is happening + } + + if (this.verboseMode) { + console.log(pw + " overall from heuristic (" + this.heuristicMapping[pw] + ") and neural nets (" + nnScoreAsPercent + ")"); + } + + // Avoid errors in case the feedback mapping was somehow screwed up + if (typeof (this.feedbackMapping[pw]) === "undefined") { + this.feedbackMapping[pw] = JSON.stringify({ + publictips1: "", + publictips2: "", + publictips3: "", + sensitivetips1: "", + sensitivetips2: "", + sensitivetips3: "", + reasonWhy1: "", + reasonWhy2: "", + reasonWhy3: "", + }); + } + var feedback = JSON.parse(this.feedbackMapping[pw]); + + var config = PasswordMeter.PasswordMeter.instance.getConfig(); + + var currentUsername = this.$("#usernamebox").val() as string; + var nni = PasswordMeter.PasswordMeter.instance.getNN(); + + var minReqObj = RuleFunctions.RuleFunctions.verifyMinimumRequirements(pw, currentUsername); + // If password complies with password policy, show feedback + if (minReqObj.compliant) { + this.inCompliance = true; + if (pw.length === 0 || !nni.heardFromNn() || numberOfScores === 2) { + this.displayBar(overallScore, true); + } + this.$(".detailedFeedback").show(); + + // For the non-modal display + // Show the button for the password-specific modal + this.$(".portalToGenericAdviceModal").hide(); + // Show (Why?) buttons that bring people to the modal + this.$(".explainWhy").show(); + // Show only 3 tips for improving the password + this.$("#nonmodalRow1").show(); + this.$("#nonmodalRow2").show(); + this.$("#nonmodalRow3").show(); + this.$("#nonmodalRow4").hide(); + this.$("#nonmodalRow5").hide(); + this.$("#nonmodalRow6").hide(); + this.$("#nonmodalRow7").hide(); + this.$("#nonmodalRow8").hide(); + // Also show the confirm password box + this.$("#confirmpw").show(); + + // For the modal display + // First hide all and then show the relevant ones + this.$(".modalRow").hide(); + this.$("#modalRow1").show(); + this.$("#modalRow1a").show(); + this.$("#modalRow2").show(); + this.$("#modalRow2a").show(); + this.$("#modalRow3").show(); + this.$("#modalRow3a").show(); + + // If we have < 3 pieces of feedback, hide relevant rows + if (typeof (feedback.publictips3) === "undefined") { + this.$("#nonmodalRow3").hide(); + this.$("#modalRow3").hide(); + this.$("#modalRow3a").hide(); + } + if (typeof (feedback.publictips2) === "undefined") { + this.$("#nonmodalRow2").hide(); + this.$("#modalRow2").hide(); + this.$("#modalRow2a").hide(); + } + if (typeof (feedback.publictips1) === "undefined") { + this.$("#nonmodalRow1").hide(); + this.$("#modalRow1").hide(); + this.$("#modalRow1a").hide(); + } + + // Display text heading reflecting the score + if (overallScore <= 33) { + var feedbackWeak = "Your password is very easy to guess."; + this.$("#feedbackHeaderText").html(feedbackWeak); + this.$("#feedbackHeaderTextModal").html(feedbackWeak); + } else if (overallScore <= 66) { + var feedbackLowMedium = "Your password could be better."; + this.$("#feedbackHeaderText").html(feedbackLowMedium); + this.$("#feedbackHeaderTextModal").html(feedbackLowMedium); + } else if (overallScore < 100) { + var feedbackHighMedium = "Your password is pretty good."; + if (config.remindAgainstReuse) { + feedbackHighMedium += " Use it only for this account. (Why?)"; + } + feedbackHighMedium += "

 

To make it even better:"; + this.$("#feedbackHeaderText").html(feedbackHighMedium); + this.$("#feedbackHeaderTextModal").html(feedbackHighMedium); + } else { + var feedbackStrong = "Your password appears strong."; + if (config.remindAgainstReuse) { + feedbackStrong += " Make sure you use it only for this account. (Why?)"; + } + this.$("#feedbackHeaderText").html(feedbackStrong); + this.$("#feedbackHeaderTextModal").html(feedbackStrong); + } + + // Show colored boxes taken away when non-compliant with the password policy + this.$(".nonmodalColorCell").show(); + this.$(".modalColorCell").show(); + this.$(".modalColorCellSpacer").show(); + + // Populate table with appropriate feedback + this.$(".recommended").show(); + // If they are showing their password, use sensitive feedback + if (this.$("#showHidePWNonModal").prop("checked") === true) { + this.$(".fixedPWavailablePortal").hide(); + this.$(".concreteSuggestionDiv").show(); + // Non-modal + this.$("#tipText1").html(feedback.sensitivetips1); + this.$("#tipText2").html(feedback.sensitivetips2); + this.$("#tipText3").html(feedback.sensitivetips3); + // Modal + this.$("#suggestion1").html(feedback.sensitivetips1); + this.$("#suggestion2").html(feedback.sensitivetips2); + this.$("#suggestion3").html(feedback.sensitivetips3); + this.$("#sensText1").html(feedback.reasonWhy1); + this.$("#sensText2").html(feedback.reasonWhy2); + this.$("#sensText3").html(feedback.reasonWhy3); + } else { + this.$(".fixedPWavailablePortal").show(); + this.$(".concreteSuggestionDiv").hide(); + // Non-modal + this.$("#tipText1").html(feedback.publictips1); + this.$("#tipText2").html(feedback.publictips2); + this.$("#tipText3").html(feedback.publictips3); + // Modal + this.$("#suggestion1").html(feedback.publictips1); + this.$("#suggestion2").html(feedback.publictips2); + this.$("#suggestion3").html(feedback.publictips3); + this.$("#sensText1").html(feedback.reasonWhy1); + this.$("#sensText2").html(feedback.reasonWhy2); + this.$("#sensText3").html(feedback.reasonWhy3); + } + + // Recommend a concrete suggestion if we have one + if (typeof (this.fixedpwMapping[pw]) !== "undefined") { + // Change colors to highlight what was modified + var coloredFixedPW = ""; + var whereToColor = this.deltaHighlighted[this.fixedpwMapping[pw]]; + var proposedPassword = this.fixedpwMapping[pw]; + for (var j = 0; j < proposedPassword.length; j++) { + if (whereToColor[j] === 1) { + coloredFixedPW += "" + proposedPassword[j].escapeHTML() + ""; + } else { + coloredFixedPW += proposedPassword[j].escapeHTML(); + } + } + this.$(".fixedPW").html(coloredFixedPW); + // If we don't yet have a concrete suggestion + } else { + this.$(".recommended").hide(); + } + + // Hide the feedback if the score is high enough + if (overallScore <= 66) { + this.$("#nonmodalFeedbackTable").show(); + this.$("#modalFeedbackTable").show(); + this.$(".portalToGenericAdviceModal").show(); + } else if (overallScore < 100) { + this.$("#nonmodalFeedbackTable").show(); + this.$("#modalFeedbackTable").show(); + this.$(".portalToGenericAdviceModal").show(); + // If they already took a concrete suggestion, don't show another + if (this.tookSuggestion) { + this.$(".recommended").hide(); + this.$(".portalToGenericAdviceModal").hide(); + } + } else { + this.$("#nonmodalFeedbackTable").hide(); + this.$("#modalFeedbackTable").hide(); + this.$(".recommended").hide(); + // Don't show any modal buttons since score is high + this.$(".portalToGenericAdviceModal").hide(); + } + // However, if the password is not yet compliant with the policy + } else { + this.inCompliance = false; + if (pw.length === 0 || !nni.heardFromNn() || numberOfScores === 2) { + this.displayBar(overallScore, false); + } + // Don't let them confirm a non-compliant password + this.$("#confirmpw").hide(); + this.$(".detailedFeedback").hide(); + // Show the button for the generic modal window + this.$(".portalToGenericAdviceModal").show(); + // Hide (Why?) buttons that bring people to the specific-advice modal + this.$(".explainWhy").hide(); + // Explain what doesn't comply + var requirementsHeader = ""; + var config: Config.Config.Config = PasswordMeter.PasswordMeter.instance.getConfig(); + if (config.remindAgainstReuse) { + requirementsHeader = "Don't reuse a password from another account! (Why?)

 

"; + } + var nonCompliantAdmonition = "Your password must:"; + this.$("#feedbackHeaderText").html(requirementsHeader + nonCompliantAdmonition); + this.$("#feedbackHeaderTextModal").html(requirementsHeader + nonCompliantAdmonition); + this.$("#nonmodalFeedbackTable").show(); + this.$(".recommended").hide(); + + // Give text feedback about how they fail to comply with policy + var policyGripes = []; + var detail = minReqObj.detail; + for (var metric in detail.compliance) { + if (!detail.compliance[metric]) { + policyGripes.push(detail.explanation[metric]); + } + } + + // Hide the color cells + this.$(".nonmodalColorCell").hide(); + this.$(".modalColorCell").hide(); + this.$(".modalColorCellSpacer").hide(); + // Hide all of the rows, and then re-show them as necessary below + this.$(".nonmodalRow").hide(); + this.$(".modalRow").hide(); + + for (var i = 0; i < policyGripes.length; i++) { + var nmRow = this.$("#nonmodalRow" + (i + 1)); + var tipText = this.$("#tipText" + (i + 1)); + var mRow = this.$("#modalRow" + (i + 1)); + var suggestion = this.$("#suggestion" + (i + 1)); + var gripe = policyGripes[i]; + + nmRow.show(); + tipText.html(gripe); + mRow.show(); + suggestion.html(gripe); + } + + } + + // Start trying to generate a concrete suggestion + if ((pw.length === 0 || !nni.heardFromNn() || numberOfScores === 2) + && minReqObj.compliant && typeof (this.fixedpwMapping[pw]) === "undefined" + && overallScore < 100) { + this.generateCandidateFixed(pw, 0, pw); + } + } + + // This function displays the colored bar. It requires the password's score + // (expected range 0-100) and a boolean metRequirements indicating yes (true) + // to display the bar in color or no (false) to display the bar in grayscale + // until the requirements have been met. + displayBar(score: number, metRequirements: boolean): void { + // Adjust score if outside the range + if (score < 0) { + score = 0; + } + if (score > 100) { + score = 100; + } + + // determine bar color + var scoreProportion = score / 100; + var barcolor = "rgb(160,160,160)"; + // Initially go from RGB 255,0,0 towards 255,140,0 + if (metRequirements && scoreProportion < 0.45) { + barcolor = "rgb(" + Math.round(255) + "," + + Math.round(scoreProportion / 0.45 * 140) + ",0)"; + // Then go from RGB 255,140,0 towards 255,215,0 + } else if (metRequirements && scoreProportion >= 0.45 && scoreProportion < 0.65) { + barcolor = "rgb(" + Math.round(255) + "," + + Math.round((scoreProportion - 0.45) / 0.20 * 75 + 140) + ",0)"; + // Then go from 255,215,0 towards 50,205,50 + } else if (metRequirements) { + barcolor = "rgb(" + Math.round(255 - (scoreProportion - 0.65) / 0.35 * 205) + + "," + Math.round(215 - (scoreProportion - 0.65) / 0.035) + ",0)"; + } + + // Display bar in main window + this.$("#cups-passwordmeter-span").css("width", Math.round(298 * score / 100).toString() + "px"); + this.$("#cups-passwordmeter-span").css("background-color", barcolor); + + // display bar in modal + this.$("#cups-passwordmeter-span-modal").css("width", Math.round(298 * score / 100).toString() + "px"); + this.$("#cups-passwordmeter-span-modal").css("background-color", barcolor); + } + + // css interaction + // potentialTODO this here? + getMaxOfArray(numArray: Array): number { + return Math.max.apply(null, numArray); + } + + expandHelpBut(): void { + this.$('#expandHelpDiv').show(); + this.$('#helpButton').hide(); + } + + modalShowCheck(): void { + //checks whether they've checked the box to show their password + if (this.$("#pwbox").prop("type") == "text") { + this.$('#myModal').show(); + this.storepw(); + // potentialTODO what is rate? mayberate? commenting. + //this.rateModal(); + } else if (this.$('#expandHelpDiv').is(':visible')) { + this.$('#myModal').show(); + this.storepw(); + // potentialTODO what is rate? mayberate? commenting. + //this.rateModal(); + } else { + this.expandHelpBut(); + } + } + + closeDiv(divName: string): void { + this.$(divName).hide(); + } + + // potentialTODO where do the fn params come from? + deselect(e: JQuery): void { + if ((this.$.fn as any).slideFadeToggle == undefined) { + (this.$.fn as any).slideFadeToggle = function(easing: string, callback: Function) { + return this.animate({ + opacity: 'toggle', + height: 'toggle' + }, 'fast', easing, callback); + }; + } + // potentialTODO force cast for our defined function + (this.$('.pop')).slideFadeToggle(function() { + e.removeClass('selected'); + }); + } + + } + + (function() { + var registry = PasswordMeter.PasswordMeter.instance; + var $ = registry.getJquery(); + var verboseMode = false; + var instance = new UIMisc(verboseMode); + registry.setUI(instance); + + $(document).ready(function() { + $("#showpassword").prop('checked', false); + $("#showpassword").click(function() { + document.getElementById("hide-show-label").textContent = "Hide Password"; + $("#cbbutton").css('background-color', '#f5f5f5'); + if ($("#pwbox").prop("type") == "password") { + $("#pwbox").prop("type", "text"); + } else { + $("#pwbox").prop("type", "password"); + document.getElementById("hide-show-label").textContent = "Show Password"; + $("#cbbutton").css('background-color', '#f5f5f5'); + } + // potentialTODO what is rate? mayberate? commenting. + //rate(); + }); + }); + + $(document).ready(function() { + var pw = $("#pwboxModal"); + $("#tip1, #sensText1").mouseover(function() { + pw.addClass("problemColor"); + }); + $("#tip2, #sensText2").mouseover(function() { + pw.addClass("problemColor"); + }); + $("#tip3, #sensText3").mouseover(function() { + pw.addClass("problemColor"); + }); + }); + + $(document).ready(function() { + instance.onReady(); + }); + + }()) } From 5f4283ca5761df73fd11c08386114171edd05d41 Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Wed, 27 Feb 2019 19:04:49 -0500 Subject: [PATCH 05/45] Added blacklist dimension support to password meter, including substring. Turned off no implicit any for typescript compiler since I couldn't get bloom-filter-js working otherwise. --- src/package.json | 15 +- src/ts/bloom-filter-js.js | 167 ++++++++ src/ts/config.ts | 75 +++- src/ts/dict-misc.ts | 60 ++- src/ts/helper.ts | 792 +++++++++++++++++++++----------------- src/ts/rulefunctions.ts | 168 +++++++- 6 files changed, 871 insertions(+), 406 deletions(-) create mode 100644 src/ts/bloom-filter-js.js diff --git a/src/package.json b/src/package.json index 132dc58..4a27e50 100644 --- a/src/package.json +++ b/src/package.json @@ -7,18 +7,21 @@ "@types/core-js": "latest", "@types/jquery": "latest", "@types/lz-string": "latest", - "tsify": "latest", - "typescript": "latest", + "@types/node": "latest", + "babel-cli": "^6.26.0", + "babel-preset-es2015": "^6.24.1", "babelify": "7.3.0", - "uglifyify": "latest", "browserify": "latest", - "@types/node": "latest" + "tsify": "latest", + "typescript": "latest", + "uglifyify": "latest" }, "dependencies": { - "babel-core": "^6.0.0" + "babel-core": "^6.0.0", + "babel-preset-stage-2": "^6.24.1" }, "scripts": { - "do-browserify": "browserify ts/*.ts -p [ tsify --noImplicitAny ] -o PasswordMeter.js" + "do-browserify": "browserify ts/*.ts -p [ tsify ] -o PasswordMeter.js" }, "browserify": { "transform": [ diff --git a/src/ts/bloom-filter-js.js b/src/ts/bloom-filter-js.js new file mode 100644 index 0000000..60bfd3b --- /dev/null +++ b/src/ts/bloom-filter-js.js @@ -0,0 +1,167 @@ +const toCharCodeArray = (str) => str.split('').map(c => c.charCodeAt(0)) + +/** + * Returns a function that generates a Rabin fingerprint hash function + * @param p The prime to use as a base for the Rabin fingerprint algorithm + */ +const simpleHashFn = (p) => (arrayValues, lastHash, lastCharCode) => { + return lastHash + // See the abracadabra example: https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm + ? (lastHash - lastCharCode * Math.pow(p, arrayValues.length - 1)) * p + arrayValues[arrayValues.length - 1] + : arrayValues.reduce((total, x, i) => total + x * Math.pow(p, arrayValues.length - i - 1), 0) +} + +/* + * Sets the specific bit location + */ +const setBit = (buffer, bitLocation) => + buffer[bitLocation / 8 | 0] |= 1 << bitLocation % 8 + +/** + * Returns true if the specified bit location is set + */ +const isBitSet = (buffer, bitLocation) => + !!(buffer[bitLocation / 8 | 0] & 1 << bitLocation % 8) + +class BloomFilter { + /** + * Constructs a new BloomFilter instance. + * If you'd like to initialize with a specific size just call BloomFilter.from(Array.from(Uint8Array(size).values())) + * Note that there is purposely no remove call because adding that would introduce false negatives. + * + * @param bitsPerElement Used along with estimatedNumberOfElements to figure out the size of the BloomFilter + * By using 10 bits per element you'll have roughly 1% chance of false positives. + * @param estimatedNumberOfElements Used along with bitsPerElementto figure out the size of the BloomFilter + * @param hashFns An array of hash functions to use. These can be custom but they should be of the form + * (arrayValues, lastHash, lastCharCode) where the last 2 parameters are optional and are used to make + * a rolling hash to save computation. + */ + constructor (bitsPerElement = 10, estimatedNumberOfElements = 50000, hashFns) { + if (bitsPerElement.constructor === Uint8Array) { + // Re-order params + this.buffer = bitsPerElement + if (estimatedNumberOfElements.constructor === Array) { + hashFns = estimatedNumberOfElements + } + // Calculate new buffer size + this.bufferBitSize = this.buffer.length * 8 + } else if (bitsPerElement.constructor === Array) { + // Re-order params + let arrayLike = bitsPerElement + if (estimatedNumberOfElements.constructor === Array) { + hashFns = estimatedNumberOfElements + } + // Calculate new buffer size + this.bufferBitSize = arrayLike.length * 8 + this.buffer = new Uint8Array(arrayLike) + } else { + // Calculate the needed buffer size in bytes + this.bufferBitSize = bitsPerElement * estimatedNumberOfElements + this.buffer = new Uint8Array(Math.ceil(this.bufferBitSize / 8)) + } + this.hashFns = hashFns || [simpleHashFn(11), simpleHashFn(17), simpleHashFn(23)] + this.setBit = setBit.bind(this, this.buffer) + this.isBitSet = isBitSet.bind(this, this.buffer) + } + + /** + * Construct a Bloom filter from a previous array of data + * Note that the hash functions must be the same! + */ + static from (arrayLike, hashFns) { + return new BloomFilter(arrayLike, hashFns) + } + + /** + * Serializing the current BloomFilter into a JSON friendly format. + * You would typically pass the result into JSON.stringify. + * Note that BloomFilter.from only works if the hash functions are the same. + */ + toJSON () { + return Array.from(this.buffer.values()) + } + + /** + * Print the buffer, mostly used for debugging only + */ + print () { + console.log(this.buffer) + } + + /** + * Given a string gets all the locations to check/set in the buffer + * for that string. + * @param charCodes An array of the char codes to use for the hash + */ + getLocationsForCharCodes (charCodes) { + return this.hashFns.map(h => h(charCodes) % this.bufferBitSize) + } + + /** + * Obtains the hashes for the specified charCodes + * See "Rabin fingerprint" in https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm for more information. + * + * @param charCodes An array of the char codes to use for the hash + * @param lastHashes If specified, it will pass the last hash to the hashing + * function for a faster computation. Must be called with lastCharCode. + * @param lastCharCode if specified, it will pass the last char code + * to the hashing function for a faster computation. Must be called with lastHashes. + */ + getHashesForCharCodes (charCodes, lastHashes, lastCharCode) { + return this.hashFns.map((h, i) => h(charCodes, lastHashes ? lastHashes[i] : undefined, lastCharCode, this.bufferBitSize)) + } + + /** + * Adds he specified string to the set + */ + add (data) { + if (data.constructor !== Array) { + data = toCharCodeArray(data) + } + + this.getLocationsForCharCodes(data).forEach(this.setBit) + } + + /** + * Checks whether an element probably exists in the set, or definitely doesn't. + * @param str Either a string to check for existance or an array of the string's char codes + * The main reason why you'd want to pass in a char code array is because passing a string + * will use JS directly to get the char codes which is very inneficient compared to calling + * into C++ code to get it and then making the call. + * + * Returns true if the element probably exists in the set + * Returns false if the element definitely does not exist in the set + */ + exists (data) { + if (data.constructor !== Array) { + data = toCharCodeArray(data) + } + return this.getLocationsForCharCodes(data).every(this.isBitSet) + } + + /** + * Checks if any substring of length substringLenght probably exists or definitely doesn't + * If false is returned then no substring of the specified string of the specified lengthis in the bloom filter + * @param data The substring or char array to check substrings on. + */ + substringExists (data, substringLength) { + if (data.constructor !== Uint8Array) { + if (data.constructor !== Array) { + data = toCharCodeArray(data) + } + data = new Uint8Array(data) + } + + let lastHashes, lastCharCode + for (let i = 0; i < data.length - substringLength + 1; i++) { + lastHashes = this.getHashesForCharCodes(data.subarray(i, i + substringLength), lastHashes, lastCharCode) + if (lastHashes.map(x => x % this.bufferBitSize).every(this.isBitSet)) { + return true + } + lastCharCode = data[i] + } + return false + } +} + +exports.BloomFilter = BloomFilter; diff --git a/src/ts/config.ts b/src/ts/config.ts index 8a54d51..372309b 100644 --- a/src/ts/config.ts +++ b/src/ts/config.ts @@ -29,10 +29,10 @@ export module Config { symbols: boolean; } - interface ConfigForbidPasswords { - active: boolean; - includeLargerList: boolean; - } + // interface ConfigForbidPasswords { + // active: boolean; + // includeLargerList: boolean; + // } interface ConfigForbidChars { active: boolean; @@ -44,12 +44,30 @@ export module Config { limit: number; } + interface ConfigLimitLengthException { + active: boolean; + limit: number; + lengthException: number; + } + interface ConfigThreshold { active: boolean; threshold: number; rejectionFeedback: string; } + interface ConfigBlacklist { // josh: probably should export this since pass on to dependency + active: boolean; + // if case-insensitive, blacklist file should contain all lowercase entries + // if stripsDigitsSymbol, blacklist file should contain all letters + blacklistFile: string; + caseSensitive: boolean; + stripDigitsSymbolsFromPassword: boolean; + checkSubstrings: boolean; + checkSubstringLength: number; // (minimum) substring length of blacklisted-item that password should be checked against + lengthException: number; + } + export interface ConfigNeuralNetwork { // raise visibility because we pass it on to a dependency intermediate: string; file: string; @@ -61,17 +79,20 @@ export module Config { colors: ConfigColor; symbols: ConfigSymbols; remindAgainstReuse: boolean; - ignoredWords: Array; - forbiddenPasswords: Array; + ignoredWords: Array; // list of words that should count for nothing in the password + // forbiddenPasswords: Array; // list of passwords that should be rejected length: ConfigLength; classCount: ConfigClassCount; classRequire: ConfigClassBoolean; classAllow: ConfigClassBoolean; - forbidPasswords: ConfigForbidPasswords; + // forbidPasswords: ConfigForbidPasswords; forbidChars: ConfigForbidChars; repeatChars: ConfigLimit; + sameChars: ConfigLimitLengthException; usernameDifference: ConfigLimit; minLogNnGuessNum: ConfigThreshold; + prohibitKnownLeaked: boolean; + blacklist: ConfigBlacklist; neuralNetworkConfig: ConfigNeuralNetwork; } @@ -85,15 +106,12 @@ export module Config { noncompliant: "❑ ", // LOWER RIGHT SHADOWED WHITE SQUARE }, remindAgainstReuse: true, // true to emphasize *not* reusing passwords - ignoredWords: // list of words that should count for nothing in the password - ["pittsburgh", - "steelers", "stillers", "penguins", "pens", "pirates", "bucs", "carnegie", "mellon", - "university"], - forbiddenPasswords: // list of passwords that should be rejected - ["123456", "password", "12345", "12345678", "qwerty", "1234567890", "1234", - "baseball", "dragon", "football", "1234567", "monkey", "letmein", "abc123", - "111111", "mustang", "access", "shadow", "master", "michael", "superman", - "696969", "123123", "batman", "trustno1"], + ignoredWords: ["mechanical", "amazon", "mturk", "turk", "survey", "bonus", "qualtrics", "study", "carnegie", "mellon", "university"], + // forbiddenPasswords: + // ["123456", "password", "12345", "12345678", "qwerty", "1234567890", "1234", + // "baseball", "dragon", "football", "1234567", "monkey", "letmein", "abc123", + // "111111", "mustang", "access", "shadow", "master", "michael", "superman", + // "696969", "123123", "batman", "trustno1"], length: { active: true, minLength: 8, @@ -118,11 +136,11 @@ export module Config { digits: true, symbols: true, }, - forbidPasswords: { - active: true, - includeLargerList: true, // setting this to true also blacklists tens of thousands - // of common passwords loaded for the common passwords dictionary check - }, + // forbidPasswords: { + // active: true, + // includeLargerList: true, // setting this to true also blacklists tens of thousands //TODO change this + // // of common passwords loaded for the common passwords dictionary check + // }, forbidChars: { active: false, list: [], @@ -131,6 +149,11 @@ export module Config { active: true, limit: 3, // prohibit a character being repeated N or more times consecutively }, + sameChars: { + active: false, + limit: 3, // prohibit a character being used N or more times (incl. non-consecutively) + lengthException: 20, // constraint does not apply if password is longer than 20 chars + }, usernameDifference: { active: true, limit: 1, // prohibit passwords being N or fewer characters different than username @@ -140,6 +163,16 @@ export module Config { threshold: 7, // prohibit passwords with a NN guess number less than 10^7 rejectionFeedback: "Not be similar to extremely common passwords", }, + prohibitKnownLeaked: false, + blacklist: { + active: false, + blacklistFile: "blacklist-cmu-compressed.txt", + caseSensitive: false, + stripDigitsSymbolsFromPassword: false, + checkSubstrings: false, + checkSubstringLength: 4, + lengthException: 20, + }, neuralNetworkConfig: { intermediate: "basic_3M.info_and_guess_numbers.no_bloomfilter.json", file: "basic_3M.weight_arch.quantized.fixed_point1000.zigzag.nospace.json", diff --git a/src/ts/dict-misc.ts b/src/ts/dict-misc.ts index 71f41ca..f8a45be 100644 --- a/src/ts/dict-misc.ts +++ b/src/ts/dict-misc.ts @@ -1,22 +1,61 @@ import PasswordMeter = require("./PasswordMeter"); -import Helper = require("./helper") +import Helper = require("./helper"); +import * as BloomFilter from "./bloom-filter-js"; +import Config = require("./config"); export module Dictionaries { export type Dictionary = { [key: string]: boolean }; + export type BloomFilter = BloomFilter.BloomFilter; export class Dictionaries { - blacklistDict: Dictionary; + namesDict: Dictionary; phrasesDict: Dictionary; - passwordsDict: Dictionary; + passwordsDict: Dictionary; // josh: keep around; used in rulefunction.ts > commonPwCheck + // load dictionary-passwords-compressed.txt into it englishwordsDict: Dictionary; + blacklistDict: Dictionary; // josh: use this for blacklist rule, not passwordsDict + blacklistBloom: BloomFilter; wikipediaDict: Dictionary; petnames: Dictionary; - constructor() { - var helper:Helper.Helper.Helper = PasswordMeter.PasswordMeter.instance.getHelper(); - this.blacklistDict = helper.compressedFileToDict("dictionary-blacklist1c8-compressed.txt"); - this.namesDict = helper.compressedFileToDict("dictionary-names-compressed.txt"); + + blacklistRejects: (stringToCheck: string) => boolean; + + constructor(config: Config.Config.Config) { + var helper: Helper.Helper.Helper = PasswordMeter.PasswordMeter.instance.getHelper(); + + // if (config.blacklist.checkSubstrings) { + // this.blacklistBloom = helper.compressedFileToBloomFilter(config.blacklist.blacklistFile, + // config.blacklist.checkSubstringLength); + // this.blacklistDict = null; + // this.blacklistRejects = function(stringToCheck) { + // return this.blacklistBloom.substringExists(stringToCheck, + // config.blacklist.checkSubstringLength); + // }; + + // } else { + // this.blacklistBloom = null; + // this.blacklistDict = helper.compressedFileToDict(config.blacklist.blacklistFile); + // this.blacklistRejects = function(stringToCheck) { + // return this.blacklistDict[stringToCheck]; + // }; + // } + + + if (!config.blacklist.checkSubstrings) { + this.blacklistRejects = function(stringToCheck) { + return this.blacklistDict[stringToCheck]; + } + } else { + this.blacklistRejects = function(stringToCheck) { + return this.blacklistBloom.substringExists(stringToCheck, config.blacklist.checkSubstringLength); + } + } + + this.blacklistDict = helper.compressedFileToDict(config.blacklist.blacklistFile); + this.blacklistBloom = helper.compressedFileToBloomFilter(config.blacklist.blacklistFile, config.blacklist.checkSubstringLength); this.passwordsDict = helper.compressedFileToDict("dictionary-passwords-compressed.txt"); + this.namesDict = helper.compressedFileToDict("dictionary-names-compressed.txt"); this.phrasesDict = helper.compressedFileToDict("dictionary-phrases-compressed.txt"); this.englishwordsDict = helper.compressedFileToDict("dictionary-englishwords-compressed.txt"); this.wikipediaDict = helper.compressedFileToDict("dictionary-wikipedia-compressed.txt"); @@ -31,8 +70,11 @@ export module Dictionaries { } } - (function () { - PasswordMeter.PasswordMeter.instance.setDictionaries(new Dictionaries()); + (function() { + var registry = PasswordMeter.PasswordMeter.instance; + var config = registry.getConfig(); + + registry.setDictionaries(new Dictionaries(config)); }()) } diff --git a/src/ts/helper.ts b/src/ts/helper.ts index 5d573f4..84f40ce 100644 --- a/src/ts/helper.ts +++ b/src/ts/helper.ts @@ -2,354 +2,448 @@ import JQuery = require("jquery"); import LZString = require("lz-string"); import PasswordMeter = require("./PasswordMeter"); +import BloomFilter = require("./bloom-filter-js"); +// import * as BloomFilter from "./bloom-filter-js"; + +// export class BloomFilterInterface { +// bloomFilter: BloomFilter.BloomFilter; +// constructor(bitsPerElement: number, +// estimatedNumberOfElements: number) { +// var _BloomFilter: any = BloomFilter; +// this.bloomFilter = new _BloomFilter(bitsPerElement, estimatedNumberOfElements); +// } +// // Array<(hashFns: string) => (arrayValues: Array, lastHash: string, lastCharCode: string)>); +// } + +// declare class NeuralNetworkClient { +// constructor(cb: (n: number, s: string) => void, config: Config.Config.ConfigNeuralNetwork); +// query_guess_number(pw: string): void; +// } + +// export class BloomFilterInterface { +// bloomFilter: NeuralNetworkClient; + +// constructor(nn: NeuralNetworkClient, nnfixed: NeuralNetworkClient) { +// this.nn = nn; +// this.nnfixed = nnfixed; +// } + +// public heardFromNn(): boolean { +// return !neverHeardFromNN; +// } + +// // set the mapping from the neural network +// public setNeuralNetNum(pw: string, value: number): void { +// neuralNetMapping[pw] = value; +// } + +// // set the mapping from the neural network +// public getNeuralNetNum(pw: string): number { +// return neuralNetMapping[pw]; +// } + +// // initiate NN guess number lookup +// public queryGuessNumber(pw: string, isConcreteSuggestionCandidate: boolean): void { +// if (isConcreteSuggestionCandidate) { +// this.nnfixed.query_guess_number(pw); +// } else { +// this.nn.query_guess_number(pw); +// } +// } +// } export module Helper { - interface MatchFoo { - matched: Array; - revisedParts: Array; - score: number; - } - - export interface Alternate { - candidate: string; - offset: number; - // Higher numbers indicate the percentage of substitution that follow a - // particular rule, and I use 100 to indicate no substitution - commonness: number; - } - - interface Replacement { - replacement: string; - commonness: number; - } - - export class Helper { - $: JQueryStatic; - LZString: LZString.LZStringStatic; - verboseMode: boolean; - log: (x: string) => void; - - constructor(jquery: JQueryStatic, lzstring: LZString.LZStringStatic, verboseMode: boolean) { - this.$ = jquery; - this.LZString = lzstring; - this.verboseMode = verboseMode; - this.log = verboseMode && window.console ? console.log : function () { }; - } - - private buildDict(words: Array, dict: { [key: string]: boolean }): number { - for (var i = 0; i < words.length; i++) { - // duplicates? - dict[words[i]] = true; // add to dictionary object for optimized lookup - } - return words.length; - } - - // Function to decompress a .txt file that contains correctly-formatted, - // compressed, dictionary file data - decompressFile(file: string): Array { - var a: Array; - var lzstring = this.LZString; - this.$.get(file, function (s) { - var decompressed = lzstring.decompressFromEncodedURIComponent(s); - a = decompressed.split(","); - }); - return a; - } - - // function for loading dictionaries that we use as wordlists - // REQUIRES: path is a valid path to a txt file - // REQUIRES: file is formatted such that there is one password per line - // ENSURES: creates a javascript object from the given file path - fileToDict(file: string): { [key: string]: boolean } { - var dict: { [key: string]: boolean } = {}; - var fBuildDict = this.buildDict; - this.$.get(file, function (s) { - var words = s.split("\n"); // get as an array - var added = fBuildDict(words, dict); - if (this.verboseMode) { - this.log("Loaded " + added + " words to dictionary.") - } - }); - return dict; - } - - // function for loading dictionaries that we use as wordlists - toDict(s: string): { [key: string]: boolean } { - // get string as array of lines - var words: Array = s.split("\n"); - var dict: { [key: string]: boolean } = {}; - var added: number = this.buildDict(words, dict); - - if (this.verboseMode) { - this.log("Loaded " + added + " words to the dictionary."); - } - return dict; - } - - // function for loading compressed dictionaries that we use as wordlists - compressedFileToDict(path: string): { [key: string]: boolean } { - var dict: { [key: string]: boolean } = {}; - var fLZString = this.LZString; - var fBuildDict = this.buildDict; - this.$.get(path, function (s) { - var decompressed = fLZString.decompressFromEncodedURIComponent(s); - var words: Array = decompressed.split(","); - var added: number = fBuildDict(words, dict); - if (this.verboseMode) { - this.log("Decompressed and loaded " + added + " words to the dictionary."); - } - }); - return dict; - } - - // loads a file (of passwords) to an array - // REQUIRES: path is a valid path to a txt file - // REQUIRES: file is formatted such that there is one password per line - // ENSURES: creates an array from the given file path - fileToArray(path: string): Array { - var a: Array = []; - this.$.get(path, function (s) { - var pws: Array = s.split("\n"); - for (var i = 0; i < pws.length; i++) { - a.push(pws[i]); - } - if (this.verboseMode) { - this.log("Loaded" + pws.length + "passwords to an array."); - } - }); - return a; - } - - // Given a regular expression "rx" and an array of 1+ "passwordParts", returns - // an object whose property "matched" is an array of all 0+ matches it found - // and whose property "score" is the total number of characters matched (summed across all matches) - // and whose property "revisedParts" is "parts" with all matches removed. - // Note that when a match is removed from the middle of a part, it splits that part into 2. - matchHelper(passwordParts: Array, rx: RegExp): MatchFoo { - var matched: Array = []; - var revisedParts: Array = []; - var score = 0; - for (var i = 0; i < passwordParts.length; i++) { - var matchResult = passwordParts[i].match(rx); - if (matchResult) { - for (var j = 0; j < matchResult.length; j++) { - score += matchResult[j].length; - var loc = passwordParts[i].indexOf(matchResult[j]); - // Check for a match at beginning - if (loc === 0) { - passwordParts[i] = passwordParts[i].substring(matchResult[j].length); - } else { // match in middle or end - revisedParts.push(passwordParts[i].substring(0, loc)); - passwordParts[i] = passwordParts[i].substring(loc + matchResult[j].length); - } - } - matched = matched.concat(matchResult); - } - // Check if it didn't match OR there are leftovers after matching - if (passwordParts[i].length > 0) { - revisedParts.push(passwordParts[i]); - } - } - return { - matched: matched, - revisedParts: revisedParts, - score: score - }; - } - - // Given a "candidate" substring from a password, returns an array of objects, each of which - // contains alternate strings with substitutions undone and their commonness - // e.g., Given "m0nkey" this function will return [monkey] - // Only performs substitutions if there is a letter within the preceding 2 or following 2 characters - // Currently, we take the 10 most common substitutions. - // Uncomment relevant parts below for the 20 most common instead. - // leetspeak characters to reverse: 012345akuyz!&@$ - //o → 0 16.2 - //i → 1 7.6 - //20mostCommon l → 1 1.7 - //20mostCommon one → 1 1.2 - //20mostCommon to → 2 1.7 - //20mostCommon too → 2 1.4 - //e → 3 12.4 - //for → 4 6.8 - //a → 4 3.1 - //s → 5 2.0 - //20mostCommon for you → 4u 0.7 - //20mostCommon er → a 1.0 - //20mostCommon c → k 1.2 - //o → u 2.8 - //20mostCommon i → y 0.8 - //s → z 2.5 - //20mostCommon i → ! 1.5 - //20mostCommon and → & 0.9 - //a → @ 7.8 - //s → $ 3.9 - commonSubstitutions(candidate: string): Array { - var NONALPHA = new RegExp("[^A-Za-z]"); - // List alternate strings with substitutions undone - var alternates = new Array(); - // Keep track of offsets (how much longer we made the string). - // If we replace 5 with s, keep the offset the same. - // If we replace 4 with for, add 2 to the offset since it is now - // two characters longer - // Also track the frequency of the *least* common substitution in this string - var original = { - 'candidate': candidate, - 'offset': 0, - 'commonness': 100 - }; - alternates.push(original); - - // Only substitute if there is a letter within 2 characters - // of what we are substituting - for (var i = 0; i < candidate.length; i++) { - if ((i >= 1 && this.isALetter(candidate.charAt(i - 1))) || - (i >= 2 && this.isALetter(candidate.charAt(i - 2))) || - (i < (candidate.length - 1) && this.isALetter(candidate.charAt(i + 1))) || - (i < (candidate.length - 2) && this.isALetter(candidate.charAt(i + 2)))) { - // List possible substitutions - var replacements = new Array(); - if (candidate.charAt(i) === '0') { - replacements.push({ - 'replacement': "o", - 'commonness': 16.2 - }); - } else if (candidate.charAt(i) === '1') { - replacements.push({ - 'replacement': "i", - 'commonness': 7.6 - }); - //replacements.push({'replacement': "l", 'commonness': 1.7}); - //replacements.push({'replacement': "one", 'commonness': 1.2}); - } - //else if(candidate.charAt(i)==='2') { - // replacements.push({'replacement': "to", 'commonness': 1.7}); - // replacements.push({'replacement': "too", 'commonness': 1.4}); - //} - else if (candidate.charAt(i) === '3') { - replacements.push({ - 'replacement': "e", - 'commonness': 12.4 - }); - } else if (candidate.charAt(i) === '4') { - replacements.push({ - 'replacement': "for", - 'commonness': 6.8 - }); - replacements.push({ - 'replacement': "a", - 'commonness': 3.1 - }); - } else if (candidate.charAt(i) === '5') { - replacements.push({ - 'replacement': "s", - 'commonness': 2.0 - }); - } - //else if(candidate.charAt(i)==='u' || candidate.charAt(i)==='U') { - // replacements.push({'replacement': "you", 'commonness': 0.7}); - //} - //else if(candidate.charAt(i)==='a' || candidate.charAt(i)==='A') { - // replacements.push({'replacement': "er", 'commonness': 1.0}); - //} - //else if(candidate.charAt(i)==='k' || candidate.charAt(i)==='K') { - // replacements.push({'replacement': "c", 'commonness': 1.2}); - //} - else if (candidate.charAt(i) === 'u' || candidate.charAt(i) === 'U') { - replacements.push({ - 'replacement': "o", - 'commonness': 2.8 - }); - } - //else if(candidate.charAt(i)==='y' || candidate.charAt(i)==='Y') { - // replacements.push({'replacement': "i", 'commonness': 0.8}); - //} - else if (candidate.charAt(i) === 'z' || candidate.charAt(i) === 'Z') { - replacements.push({ - 'replacement': "s", - 'commonness': 2.5 - }); - } - //else if(candidate.charAt(i)==='!') { - // replacements.push({'replacement': "i", 'commonness': 1.5}); - //} - //else if(candidate.charAt(i)==='&') { - // replacements.push({'replacement': "and", 'commonness': 0.9}); - //} - else if (candidate.charAt(i) === '@') { - replacements.push({ - 'replacement': "a", - 'commonness': 7.8 - }); - } else if (candidate.charAt(i) === '$') { - replacements.push({ - 'replacement': "s", - 'commonness': 3.9 - }); - } - - var existingAlternates = alternates.length; - for (var j = 0; j < existingAlternates; j++) { - for (var k = 0; k < replacements.length; k++) { - var subToMake = replacements[k].replacement; - var newPW = alternates[j].candidate.replaceAt(i + alternates[j].offset, subToMake); - var howCommon = replacements[k].commonness; - if (alternates[j].commonness < howCommon) { - howCommon = alternates[j].commonness; - } - var newOffset = alternates[j].offset + replacements[k].replacement.length - 1; - alternates.push({ - 'candidate': newPW, - 'offset': newOffset, - 'commonness': howCommon - }); - } - } - } - } - for (var z = alternates.length - 1; z >= 0; z--) { - if (alternates[z].candidate.match(NONALPHA)) { - alternates.splice(z, 1); - } - } - return alternates; - } - - // Given two arrays, a and b, each of *strings in decreasing length order*, - // returns the longest string that is in both. - // If there are multiple strings common to both, only returns the first from array a. - // Not case sensitive. - sortedOverlap(a: Array, b: Array): string { - for (var i = 0; i < a.length; i++) { - for (var j = 0; j < b.length; j++) { - if (a[i] == b[j]) { - return a[i]; - } - } - } - return ""; - } - - // Returns true is a character is an uppercase or lowercase letter and false if it is not - // Expects a single character as input. Returns false if not. - isALetter(character: string): boolean { - // Make sure it's a single character - if (character.length != 1) { - return false; - } - var asciiCode = character.charCodeAt(0); - if ((asciiCode >= 65 && asciiCode <= 90) || (asciiCode >= 97 && asciiCode <= 122)) { - return true; - } else { - return false; - } - } - - } - - export function boldAll(foo: Array) { - return foo.map(function(x: string): string { - return ""+x+""; - }); - } -} \ No newline at end of file + interface MatchFoo { + matched: Array; + revisedParts: Array; + score: number; + } + + export interface Alternate { + candidate: string; + offset: number; + // Higher numbers indicate the percentage of substitution that follow a + // particular rule, and I use 100 to indicate no substitution + commonness: number; + } + + interface Replacement { + replacement: string; + commonness: number; + } + + export class Helper { + $: JQueryStatic; + LZString: LZString.LZStringStatic; + verboseMode: boolean; + log: (x: string) => void; + + constructor(jquery: JQueryStatic, lzstring: LZString.LZStringStatic, verboseMode: boolean) { + this.$ = jquery; + this.LZString = lzstring; + this.verboseMode = verboseMode; + this.log = verboseMode && window.console ? console.log : function() { }; + } + + private buildDict(words: Array, dict: { [key: string]: boolean }): number { + for (var i = 0; i < words.length; i++) { + // duplicates? + dict[words[i]] = true; // add to dictionary object for optimized lookup + } + return words.length; + } + + // Function to decompress a .txt file that contains correctly-formatted, + // compressed, dictionary file data + decompressFile(file: string): Array { + var a: Array; + var lzstring = this.LZString; + this.$.get(file, function(s) { + var decompressed = lzstring.decompressFromEncodedURIComponent(s); + a = decompressed.split(","); + }); + return a; + } + + // function for loading dictionaries that we use as wordlists + // REQUIRES: path is a valid path to a txt file + // REQUIRES: file is formatted such that there is one password per line + // ENSURES: creates a javascript object from the given file path + fileToDict(file: string): { [key: string]: boolean } { + var dict: { [key: string]: boolean } = {}; + var fBuildDict = this.buildDict; + this.$.get(file, function(s) { + var words = s.split("\n"); // get as an array + var added = fBuildDict(words, dict); + if (this.verboseMode) { + this.log("Loaded " + added + " words to dictionary.") + } + console.log("Loaded " + added + " words to dictionary.") + }); + return dict; + } + + // function for loading dictionaries that we use as wordlists + toDict(s: string): { [key: string]: boolean } { + // get string as array of lines + var words: Array = s.split("\n"); + var dict: { [key: string]: boolean } = {}; + var added: number = this.buildDict(words, dict); + + if (this.verboseMode) { + this.log("Loaded " + added + " words to the dictionary."); + } + console.log("Loaded " + added + " words to the dictionary."); + return dict; + } + + // function for loading compressed dictionaries that we use as wordlists + compressedFileToDict(path: string): { [key: string]: boolean } { + var dict: { [key: string]: boolean } = {}; + var fLZString = this.LZString; + var fBuildDict = this.buildDict; + this.$.get(path, function(s) { + var decompressed = fLZString.decompressFromEncodedURIComponent(s); + var words: Array = decompressed.split(","); + var added: number = fBuildDict(words, dict); + if (this.verboseMode) { + this.log("Decompressed and loaded " + added + " words to the dictionary."); + } + console.log("Loaded " + added + " words to the dictionary for " + path); + }); + + return dict; + } + + compressedFileToBloomFilter(path: string, blacklistSubstringLength: number) { + + // "The 1% false-positive rate can be reduced by a factor of ten + // by adding only about 4.8 bits per element." + // "By using 10 bits per element youll have roughly 1% chance of false positives." + // so: use 15 bits for ~.1% error or .001 error rate rate + + var bloomBitsPerElement = 15; + var bloomEstimatedNumElements = 425000; + var bloomer = new BloomFilter.BloomFilter(bloomBitsPerElement, bloomEstimatedNumElements); + var wordsAdded = 0; + var startTime = Date.now(); + var substringsAdded = 0; + var fLZString = this.LZString; + + this.$.get(path, function(s) { + + var decompressed = fLZString.decompressFromEncodedURIComponent(s); + var words = decompressed.split(","); + for (var i = 0; i < words.length; i++) { + + var blWord = words[i]; + wordsAdded++; + + // add substrings + if (blWord.length > blacklistSubstringLength) { + var numSubstrings = blWord.length - blacklistSubstringLength + 1; + + for (var j = 0; j < numSubstrings; j++) { + var blSubstring = blWord.substring(j, j + blacklistSubstringLength); + bloomer.add(blSubstring); + substringsAdded++; + } + } + } + var timeTaken = Date.now() - startTime; + console.log("Decompressed and loaded " + substringsAdded + " length-" + blacklistSubstringLength + " substrings (derived from a " + wordsAdded + "-word list) into a Bloom filter" + " [took " + timeTaken + "ms]"); + }); + return bloomer; + } + + // loads a file (of passwords) to an array + // REQUIRES: path is a valid path to a txt file + // REQUIRES: file is formatted such that there is one password per line + // ENSURES: creates an array from the given file path + fileToArray(path: string): Array { + var a: Array = []; + this.$.get(path, function(s) { + var pws: Array = s.split("\n"); + for (var i = 0; i < pws.length; i++) { + a.push(pws[i]); + } + if (this.verboseMode) { + this.log("Loaded" + pws.length + "passwords to an array."); + } + }); + return a; + } + + // Given a regular expression "rx" and an array of 1+ "passwordParts", returns + // an object whose property "matched" is an array of all 0+ matches it found + // and whose property "score" is the total number of characters matched (summed across all matches) + // and whose property "revisedParts" is "parts" with all matches removed. + // Note that when a match is removed from the middle of a part, it splits that part into 2. + matchHelper(passwordParts: Array, rx: RegExp): MatchFoo { + var matched: Array = []; + var revisedParts: Array = []; + var score = 0; + for (var i = 0; i < passwordParts.length; i++) { + var matchResult = passwordParts[i].match(rx); + if (matchResult) { + for (var j = 0; j < matchResult.length; j++) { + score += matchResult[j].length; + var loc = passwordParts[i].indexOf(matchResult[j]); + // Check for a match at beginning + if (loc === 0) { + passwordParts[i] = passwordParts[i].substring(matchResult[j].length); + } else { // match in middle or end + revisedParts.push(passwordParts[i].substring(0, loc)); + passwordParts[i] = passwordParts[i].substring(loc + matchResult[j].length); + } + } + matched = matched.concat(matchResult); + } + // Check if it didn't match OR there are leftovers after matching + if (passwordParts[i].length > 0) { + revisedParts.push(passwordParts[i]); + } + } + return { + matched: matched, + revisedParts: revisedParts, + score: score + }; + } + + // Given a "candidate" substring from a password, returns an array of objects, each of which + // contains alternate strings with substitutions undone and their commonness + // e.g., Given "m0nkey" this function will return [monkey] + // Only performs substitutions if there is a letter within the preceding 2 or following 2 characters + // Currently, we take the 10 most common substitutions. + // Uncomment relevant parts below for the 20 most common instead. + // leetspeak characters to reverse: 012345akuyz!&@$ + //o → 0 16.2 + //i → 1 7.6 + //20mostCommon l → 1 1.7 + //20mostCommon one → 1 1.2 + //20mostCommon to → 2 1.7 + //20mostCommon too → 2 1.4 + //e → 3 12.4 + //for → 4 6.8 + //a → 4 3.1 + //s → 5 2.0 + //20mostCommon for you → 4u 0.7 + //20mostCommon er → a 1.0 + //20mostCommon c → k 1.2 + //o → u 2.8 + //20mostCommon i → y 0.8 + //s → z 2.5 + //20mostCommon i → ! 1.5 + //20mostCommon and → & 0.9 + //a → @ 7.8 + //s → $ 3.9 + commonSubstitutions(candidate: string): Array { + var NONALPHA = new RegExp("[^A-Za-z]"); + // List alternate strings with substitutions undone + var alternates = new Array(); + // Keep track of offsets (how much longer we made the string). + // If we replace 5 with s, keep the offset the same. + // If we replace 4 with for, add 2 to the offset since it is now + // two characters longer + // Also track the frequency of the *least* common substitution in this string + var original = { + 'candidate': candidate, + 'offset': 0, + 'commonness': 100 + }; + alternates.push(original); + + // Only substitute if there is a letter within 2 characters + // of what we are substituting + for (var i = 0; i < candidate.length; i++) { + if ((i >= 1 && this.isALetter(candidate.charAt(i - 1))) || + (i >= 2 && this.isALetter(candidate.charAt(i - 2))) || + (i < (candidate.length - 1) && this.isALetter(candidate.charAt(i + 1))) || + (i < (candidate.length - 2) && this.isALetter(candidate.charAt(i + 2)))) { + // List possible substitutions + var replacements = new Array(); + if (candidate.charAt(i) === '0') { + replacements.push({ + 'replacement': "o", + 'commonness': 16.2 + }); + } else if (candidate.charAt(i) === '1') { + replacements.push({ + 'replacement': "i", + 'commonness': 7.6 + }); + //replacements.push({'replacement': "l", 'commonness': 1.7}); + //replacements.push({'replacement': "one", 'commonness': 1.2}); + } + //else if(candidate.charAt(i)==='2') { + // replacements.push({'replacement': "to", 'commonness': 1.7}); + // replacements.push({'replacement': "too", 'commonness': 1.4}); + //} + else if (candidate.charAt(i) === '3') { + replacements.push({ + 'replacement': "e", + 'commonness': 12.4 + }); + } else if (candidate.charAt(i) === '4') { + replacements.push({ + 'replacement': "for", + 'commonness': 6.8 + }); + replacements.push({ + 'replacement': "a", + 'commonness': 3.1 + }); + } else if (candidate.charAt(i) === '5') { + replacements.push({ + 'replacement': "s", + 'commonness': 2.0 + }); + } + //else if(candidate.charAt(i)==='u' || candidate.charAt(i)==='U') { + // replacements.push({'replacement': "you", 'commonness': 0.7}); + //} + //else if(candidate.charAt(i)==='a' || candidate.charAt(i)==='A') { + // replacements.push({'replacement': "er", 'commonness': 1.0}); + //} + //else if(candidate.charAt(i)==='k' || candidate.charAt(i)==='K') { + // replacements.push({'replacement': "c", 'commonness': 1.2}); + //} + else if (candidate.charAt(i) === 'u' || candidate.charAt(i) === 'U') { + replacements.push({ + 'replacement': "o", + 'commonness': 2.8 + }); + } + //else if(candidate.charAt(i)==='y' || candidate.charAt(i)==='Y') { + // replacements.push({'replacement': "i", 'commonness': 0.8}); + //} + else if (candidate.charAt(i) === 'z' || candidate.charAt(i) === 'Z') { + replacements.push({ + 'replacement': "s", + 'commonness': 2.5 + }); + } + //else if(candidate.charAt(i)==='!') { + // replacements.push({'replacement': "i", 'commonness': 1.5}); + //} + //else if(candidate.charAt(i)==='&') { + // replacements.push({'replacement': "and", 'commonness': 0.9}); + //} + else if (candidate.charAt(i) === '@') { + replacements.push({ + 'replacement': "a", + 'commonness': 7.8 + }); + } else if (candidate.charAt(i) === '$') { + replacements.push({ + 'replacement': "s", + 'commonness': 3.9 + }); + } + + var existingAlternates = alternates.length; + for (var j = 0; j < existingAlternates; j++) { + for (var k = 0; k < replacements.length; k++) { + var subToMake = replacements[k].replacement; + var newPW = alternates[j].candidate.replaceAt(i + alternates[j].offset, subToMake); + var howCommon = replacements[k].commonness; + if (alternates[j].commonness < howCommon) { + howCommon = alternates[j].commonness; + } + var newOffset = alternates[j].offset + replacements[k].replacement.length - 1; + alternates.push({ + 'candidate': newPW, + 'offset': newOffset, + 'commonness': howCommon + }); + } + } + } + } + for (var z = alternates.length - 1; z >= 0; z--) { + if (alternates[z].candidate.match(NONALPHA)) { + alternates.splice(z, 1); + } + } + return alternates; + } + + // Given two arrays, a and b, each of *strings in decreasing length order*, + // returns the longest string that is in both. + // If there are multiple strings common to both, only returns the first from array a. + // Not case sensitive. + sortedOverlap(a: Array, b: Array): string { + for (var i = 0; i < a.length; i++) { + for (var j = 0; j < b.length; j++) { + if (a[i] == b[j]) { + return a[i]; + } + } + } + return ""; + } + + // Returns true is a character is an uppercase or lowercase letter and false if it is not + // Expects a single character as input. Returns false if not. + isALetter(character: string): boolean { + // Make sure it's a single character + if (character.length != 1) { + return false; + } + var asciiCode = character.charCodeAt(0); + if ((asciiCode >= 65 && asciiCode <= 90) || (asciiCode >= 97 && asciiCode <= 122)) { + return true; + } else { + return false; + } + } + + } + + export function boldAll(foo: Array) { + return foo.map(function(x: string): string { + return "" + x + ""; + }); + } +} diff --git a/src/ts/rulefunctions.ts b/src/ts/rulefunctions.ts index e78d905..f2c6f78 100644 --- a/src/ts/rulefunctions.ts +++ b/src/ts/rulefunctions.ts @@ -264,45 +264,133 @@ export module RuleFunctions { compliance["classAllow"] = compliant; } + // // dimension 5: forbidden passwords + // // potentialTODO how much of this is covered by forbidPasswords? + // if (config.forbidPasswords.active) { + // // potentialTODO put this under forbidPasswords? + // var forbiddenPasswords = config.forbiddenPasswords; + // var includelargerlist = config.forbidPasswords.includeLargerList; + // var thisExplanation = ""; + // var compliant = false; + + // // explain + // thisExplanation = "Not be an extremely common password"; + + // // check + // // if it's in our small array from the config file OR, + // // assuming we included the larger list, it's on that list (case-insensitive) + + // // potentialTODO use Array.contains? no strictness. + // if (pw.length === 0 || forbiddenPasswords.indexOf(pw.toLowerCase()) === -1) { + // if (includelargerlist) { + // if (pw.length === 0 || dictionaries.passwordsDict[pw.toLowerCase()] !== true) { + // compliant = true; + // } + // } else { + // compliant = true; + // } + // } + + // // report + // // note that we are only complaining about disallowed passwords if they use one + // if (compliant) { + // } else { + // thisExplanation = "" + noncompliantSymbol + thisExplanation + ""; + + // } + + // if (!compliant) { + // explanation["forbidPasswords"] = thisExplanation; + // } + // compliance["forbidPasswords"] = compliant; + // } + // dimension 5: forbidden passwords - // potentialTODO how much of this is covered by forbidPasswords? - if (config.forbidPasswords.active) { - // potentialTODO put this under forbidPasswords? - var forbiddenPasswords = config.forbiddenPasswords; - var includelargerlist = config.forbidPasswords.includeLargerList; + if (config.blacklist.active) { var thisExplanation = ""; var compliant = false; + var blacklisted = false; // explain thisExplanation = "Not be an extremely common password"; - // check - // if it's in our small array from the config file OR, - // assuming we included the larger list, it's on that list (case-insensitive) - - // potentialTODO use Array.contains? no strictness. - if (pw.length === 0 || forbiddenPasswords.indexOf(pw.toLowerCase()) === -1) { - if (includelargerlist) { - if (pw.length === 0 || dictionaries.passwordsDict[pw.toLowerCase()] !== true) { - compliant = true; - } - } else { - compliant = true; + var isBlacklisted = false; + if (pw.length > 0) { + + var stringToCheck = pw; // default is case-sensitive fullstring + if (config.blacklist.stripDigitsSymbolsFromPassword) { + stringToCheck = stringToCheck.replace(/[^a-zA-Z]/gi, ''); } - } + if (!config.blacklist.caseSensitive) { + stringToCheck = stringToCheck.toLowerCase(); + } + + // switch (blacklistAlgorithm) { + // case "lc_strip_num_sym_fullstring": + // stringToCheck = pw.replace(/[^a-zA-Z]/gi, ''); + // stringToCheck = stringToCheck.toLowerCase(); + // break; + // case "case_ins_fullstring": + // case "case_ins_substring": + // stringToCheck = pw.toLowerCase(); + // break; + // default: // fullstring + // stringToCheck = pw; + // break; + // } + isBlacklisted = dictionaries.blacklistRejects(stringToCheck); + + // if (!config.blacklist.checkSubstrings) { + // // just do fullstring for stringToCheck + // isBlacklisted = dictionaries.passwordsDict[stringToCheck]; + // } else { + // isBlacklisted = blacklistBloom.substringExists(pwdToCheck, blacklistSubstringLength); + + // } + // switch (blacklistAlgorithm) { + // case "case_ins_substring": + // isBlacklisted = substringOfPwdIsBlacklisted(stringToCheck); + // break; + // default: // fullstring-based matching algs + // isBlacklisted = blacklistDict[stringToCheck]; // also load appropriate lettercased blacklist in conditionX.php + // break; + // } + + } + + // // check + // // if it's in our small array from the config file OR, + // // assuming we included the larger list, it's on that list (case-insensitive) + + // // potentialTODO use Array.contains? no strictness. + // if (pw.length === 0 || forbiddenPasswords.indexOf(pw.toLowerCase()) === -1) { + // if (includelargerlist) { + // if (pw.length === 0 || dictionaries.passwordsDict[pw.toLowerCase()] !== true) { + // compliant = true; + // } + // } else { + // compliant = true; + // } + // } + + compliant = !isBlacklisted || + pw.length === 0 || + (config.blacklist.lengthException != -1 && pw.length >= config.blacklist.lengthException) + // report // note that we are only complaining about disallowed passwords if they use one if (compliant) { + //console.log(stringToCheck + " is not on the blacklist [password: " + pw + "]"); } else { thisExplanation = "" + noncompliantSymbol + thisExplanation + ""; - + //console.log(stringToCheck + " IS on the blacklist [password: " + pw + "]"); } if (!compliant) { - explanation["forbidPasswords"] = thisExplanation; + explanation["blacklist"] = thisExplanation; } - compliance["forbidPasswords"] = compliant; + compliance["blacklist"] = compliant; } // dimension 6: forbidden/permitted characters @@ -439,6 +527,28 @@ export module RuleFunctions { compliance["minLogNnGuessNum"] = compliant; } + // dimension 7: same character (repeated in password but not consecutively) + if (config.sameChars.active) { + var sameCharsLimit = config.sameChars.limit; + var thisExplanation = ""; + var compliant = false; + + // explain + if (pw.length >= config.sameChars.lengthException || (satisfiesMaxChar(pw, sameCharsLimit))) { + compliant = true; + } + else { + thisExplanation = "Not contain the same character more than " + sameCharsLimit.toString() + "+ times"; + } + + // report (only explain if violate requirement) + if (!compliant) { + thisExplanation = "" + noncompliantSymbol + thisExplanation + ""; + explanation["sameChars"] = thisExplanation; + } + compliance["sameChars"] = compliant; + } + // potentialTODO reduce operation var overallCompliance: boolean = true; for (const item in compliance) { @@ -457,6 +567,22 @@ export module RuleFunctions { return ret; } + function satisfiesMaxChar(pw: string, maxAllowed: number) { + var pwChars = {}; + for (var i = 0; i < pw.length; i++) { + var pwChar = pw.charAt(i); + if (pwChar in pwChars) { + pwChars[pwChar] = pwChars[pwChar] + 1; + if (pwChars[pwChar] > maxAllowed) { + return false; + } + } else { + pwChars[pwChar] = 1; + } + } + return true; + } + interface PwLengthComment { length: number; reasonWhy: string; From ef84feea0cce9e3a6a1ceaac0498712c68f2b2ea Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Thu, 28 Feb 2019 10:42:21 -0500 Subject: [PATCH 06/45] Moved bloom-filter-js library to js/ dir. --- src/{ts => js}/bloom-filter-js.js | 0 src/ts/dict-misc.ts | 6 +++--- src/ts/helper.ts | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) rename src/{ts => js}/bloom-filter-js.js (100%) diff --git a/src/ts/bloom-filter-js.js b/src/js/bloom-filter-js.js similarity index 100% rename from src/ts/bloom-filter-js.js rename to src/js/bloom-filter-js.js diff --git a/src/ts/dict-misc.ts b/src/ts/dict-misc.ts index f8a45be..b58874e 100644 --- a/src/ts/dict-misc.ts +++ b/src/ts/dict-misc.ts @@ -1,11 +1,11 @@ import PasswordMeter = require("./PasswordMeter"); import Helper = require("./helper"); -import * as BloomFilter from "./bloom-filter-js"; +// import * as BloomFilter from "./bloom-filter-js"; // was also working +import BloomFilter = require("../js/bloom-filter-js"); import Config = require("./config"); export module Dictionaries { export type Dictionary = { [key: string]: boolean }; - export type BloomFilter = BloomFilter.BloomFilter; export class Dictionaries { @@ -15,7 +15,7 @@ export module Dictionaries { // load dictionary-passwords-compressed.txt into it englishwordsDict: Dictionary; blacklistDict: Dictionary; // josh: use this for blacklist rule, not passwordsDict - blacklistBloom: BloomFilter; + blacklistBloom: BloomFilter.BloomFilter; wikipediaDict: Dictionary; petnames: Dictionary; diff --git a/src/ts/helper.ts b/src/ts/helper.ts index 84f40ce..9254b92 100644 --- a/src/ts/helper.ts +++ b/src/ts/helper.ts @@ -2,8 +2,7 @@ import JQuery = require("jquery"); import LZString = require("lz-string"); import PasswordMeter = require("./PasswordMeter"); -import BloomFilter = require("./bloom-filter-js"); -// import * as BloomFilter from "./bloom-filter-js"; +import BloomFilter = require("../js/bloom-filter-js"); // export class BloomFilterInterface { // bloomFilter: BloomFilter.BloomFilter; From 148254bca54a06488a5acefec7ee4451b0273394 Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Thu, 28 Feb 2019 13:44:04 -0500 Subject: [PATCH 07/45] Added HIBP check to password meter. --- src/js/bloom-filter-js.js | 2 + src/js/hibp-js.js | 118 ++++++++++++++++++++++++++++++++++++++ src/ts/config.ts | 14 ++++- src/ts/dict-misc.ts | 32 ++++------- src/ts/helper.ts | 47 --------------- src/ts/rulefunctions.ts | 19 +++++- 6 files changed, 159 insertions(+), 73 deletions(-) create mode 100644 src/js/hibp-js.js diff --git a/src/js/bloom-filter-js.js b/src/js/bloom-filter-js.js index 60bfd3b..dd42803 100644 --- a/src/js/bloom-filter-js.js +++ b/src/js/bloom-filter-js.js @@ -1,3 +1,5 @@ +// https://github.com/bbondy/bloom-filter-js + const toCharCodeArray = (str) => str.split('').map(c => c.charCodeAt(0)) /** diff --git a/src/js/hibp-js.js b/src/js/hibp-js.js new file mode 100644 index 0000000..6b4a88b --- /dev/null +++ b/src/js/hibp-js.js @@ -0,0 +1,118 @@ +/** + * hibp.js + * @version v1 + * @author Mehdi Bounya + * + * Report any bugs here: https://github.com/mehdibo/hibp-js + * + * The MIT License (http://www.opensource.org/licenses/mit-license.php) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +// https://github.com/mehdibo/hibp-js (with additional tweaks for meter) + +class PasswordLeaks { + + constructor() { + this.hibpCache = {}; + this.hibpTimings = {}; + } + + sha1(string){ + var buffer = new TextEncoder("utf-8").encode(string); + return crypto.subtle.digest("SHA-1", buffer).then(function (buffer) { + // Get the hex code + var hexCodes = []; + var view = new DataView(buffer); + for (var i = 0; i < view.byteLength; i += 4) { + // Using getUint32 reduces the number of iterations needed (we process 4 bytes each time) + var value = view.getUint32(i) + // toString(16) will give the hex representation of the number without padding + var stringValue = value.toString(16) + // We use concatenation and slice for padding + var padding = '00000000' + var paddedValue = (padding + stringValue).slice(-padding.length) + hexCodes.push(paddedValue); + } + // Join all the hex strings into one + return hexCodes.join(""); + }); + } + + updateHibpCache(pwd, wasLeaked) { + this.hibpCache[pwd] = wasLeaked === 1 ? 1 : 0; + var timeTaken = Date.now() - this.hibpTimings[pwd]; + this.hibpTimings[pwd] = timeTaken; + console.log((wasLeaked ? "F" : "Not f") + "ound in HIBP database: " + pwd + " [took " + timeTaken + "ms]"); + } + + hibpCheck(pwd){ + // We hash the pwd first + var that = this; + this.sha1(pwd).then(function(hash, self){ + // We send the first 5 chars of the hash to hibp's API + const req = new XMLHttpRequest(); + req.addEventListener("load", function(){ + // When we get back a response from the server + // We create an array of lines and loop through them + const resp = this.responseText.split('\n'); + const hashSub = hash.slice(5).toUpperCase(); + var wasLeakedResult = 0; + + + for (var index = 0; index < resp.length; index++){ + // Check if the line matches the rest of the hash + var hashline = resp[index]; + + if (hashline.substring(0, 35) == hashSub) { + wasLeakedResult = 1; + break; // If found no need to continue the loop + } + } + // Trigger an event with the result + that.updateHibpCache(pwd, wasLeakedResult); + + }); + req.open('GET', 'https://api.pwnedpasswords.com/range/'+hash.substr(0, 5)); + req.send(); + }); + } + + previouslyLeaked(pwd) { + + if (typeof(this.hibpCache[pwd])==="undefined") { + this.hibpCache[pwd] = -1; // signal that we're finding out + this.hibpTimings[pwd] = Date.now(); + this.hibpCheck(pwd); + } + + if (this.hibpCache[pwd] === -1) { + return false; // while figuring these out, say it's okay + } else { + return this.hibpCache[pwd] === 1; + } + + } +} + +exports.PasswordLeaks = PasswordLeaks; diff --git a/src/ts/config.ts b/src/ts/config.ts index 372309b..379a6b6 100644 --- a/src/ts/config.ts +++ b/src/ts/config.ts @@ -44,6 +44,11 @@ export module Config { limit: number; } + interface ConfigSmallestLength { + active: boolean; + smallestLength: number; + } + interface ConfigLimitLengthException { active: boolean; limit: number; @@ -91,7 +96,7 @@ export module Config { sameChars: ConfigLimitLengthException; usernameDifference: ConfigLimit; minLogNnGuessNum: ConfigThreshold; - prohibitKnownLeaked: boolean; + prohibitKnownLeaked: ConfigSmallestLength; blacklist: ConfigBlacklist; neuralNetworkConfig: ConfigNeuralNetwork; } @@ -163,14 +168,17 @@ export module Config { threshold: 7, // prohibit passwords with a NN guess number less than 10^7 rejectionFeedback: "Not be similar to extremely common passwords", }, - prohibitKnownLeaked: false, + prohibitKnownLeaked: { + active: true, + smallestLength: 5, + }, blacklist: { active: false, blacklistFile: "blacklist-cmu-compressed.txt", caseSensitive: false, stripDigitsSymbolsFromPassword: false, checkSubstrings: false, - checkSubstringLength: 4, + checkSubstringLength: 5, lengthException: 20, }, neuralNetworkConfig: { diff --git a/src/ts/dict-misc.ts b/src/ts/dict-misc.ts index b58874e..e7fa059 100644 --- a/src/ts/dict-misc.ts +++ b/src/ts/dict-misc.ts @@ -3,6 +3,7 @@ import Helper = require("./helper"); // import * as BloomFilter from "./bloom-filter-js"; // was also working import BloomFilter = require("../js/bloom-filter-js"); import Config = require("./config"); +import PasswordLeaks = require("../js/hibp-js"); export module Dictionaries { export type Dictionary = { [key: string]: boolean }; @@ -11,37 +12,19 @@ export module Dictionaries { namesDict: Dictionary; phrasesDict: Dictionary; - passwordsDict: Dictionary; // josh: keep around; used in rulefunction.ts > commonPwCheck - // load dictionary-passwords-compressed.txt into it + passwordsDict: Dictionary; // josh: keep around; used in rulefunction.ts commonPwCheck() englishwordsDict: Dictionary; - blacklistDict: Dictionary; // josh: use this for blacklist rule, not passwordsDict - blacklistBloom: BloomFilter.BloomFilter; wikipediaDict: Dictionary; petnames: Dictionary; + blacklistDict: Dictionary; // josh: use this for blacklist rule, not passwordsDict + blacklistBloom: BloomFilter.BloomFilter; + leaks: PasswordLeaks.PasswordLeaks; blacklistRejects: (stringToCheck: string) => boolean; constructor(config: Config.Config.Config) { var helper: Helper.Helper.Helper = PasswordMeter.PasswordMeter.instance.getHelper(); - // if (config.blacklist.checkSubstrings) { - // this.blacklistBloom = helper.compressedFileToBloomFilter(config.blacklist.blacklistFile, - // config.blacklist.checkSubstringLength); - // this.blacklistDict = null; - // this.blacklistRejects = function(stringToCheck) { - // return this.blacklistBloom.substringExists(stringToCheck, - // config.blacklist.checkSubstringLength); - // }; - - // } else { - // this.blacklistBloom = null; - // this.blacklistDict = helper.compressedFileToDict(config.blacklist.blacklistFile); - // this.blacklistRejects = function(stringToCheck) { - // return this.blacklistDict[stringToCheck]; - // }; - // } - - if (!config.blacklist.checkSubstrings) { this.blacklistRejects = function(stringToCheck) { return this.blacklistDict[stringToCheck]; @@ -54,6 +37,7 @@ export module Dictionaries { this.blacklistDict = helper.compressedFileToDict(config.blacklist.blacklistFile); this.blacklistBloom = helper.compressedFileToBloomFilter(config.blacklist.blacklistFile, config.blacklist.checkSubstringLength); + this.leaks = new PasswordLeaks.PasswordLeaks() this.passwordsDict = helper.compressedFileToDict("dictionary-passwords-compressed.txt"); this.namesDict = helper.compressedFileToDict("dictionary-names-compressed.txt"); this.phrasesDict = helper.compressedFileToDict("dictionary-phrases-compressed.txt"); @@ -68,6 +52,10 @@ export module Dictionaries { this.petnames[temppetnames[i]] = true; } } + + previouslyLeaked(pwd: string) { + return this.leaks.previouslyLeaked(pwd); + } } (function() { diff --git a/src/ts/helper.ts b/src/ts/helper.ts index 9254b92..632e581 100644 --- a/src/ts/helper.ts +++ b/src/ts/helper.ts @@ -4,53 +4,6 @@ import LZString = require("lz-string"); import PasswordMeter = require("./PasswordMeter"); import BloomFilter = require("../js/bloom-filter-js"); -// export class BloomFilterInterface { -// bloomFilter: BloomFilter.BloomFilter; -// constructor(bitsPerElement: number, -// estimatedNumberOfElements: number) { -// var _BloomFilter: any = BloomFilter; -// this.bloomFilter = new _BloomFilter(bitsPerElement, estimatedNumberOfElements); -// } -// // Array<(hashFns: string) => (arrayValues: Array, lastHash: string, lastCharCode: string)>); -// } - -// declare class NeuralNetworkClient { -// constructor(cb: (n: number, s: string) => void, config: Config.Config.ConfigNeuralNetwork); -// query_guess_number(pw: string): void; -// } - -// export class BloomFilterInterface { -// bloomFilter: NeuralNetworkClient; - -// constructor(nn: NeuralNetworkClient, nnfixed: NeuralNetworkClient) { -// this.nn = nn; -// this.nnfixed = nnfixed; -// } - -// public heardFromNn(): boolean { -// return !neverHeardFromNN; -// } - -// // set the mapping from the neural network -// public setNeuralNetNum(pw: string, value: number): void { -// neuralNetMapping[pw] = value; -// } - -// // set the mapping from the neural network -// public getNeuralNetNum(pw: string): number { -// return neuralNetMapping[pw]; -// } - -// // initiate NN guess number lookup -// public queryGuessNumber(pw: string, isConcreteSuggestionCandidate: boolean): void { -// if (isConcreteSuggestionCandidate) { -// this.nnfixed.query_guess_number(pw); -// } else { -// this.nn.query_guess_number(pw); -// } -// } -// } - export module Helper { interface MatchFoo { matched: Array; diff --git a/src/ts/rulefunctions.ts b/src/ts/rulefunctions.ts index f2c6f78..fe017e8 100644 --- a/src/ts/rulefunctions.ts +++ b/src/ts/rulefunctions.ts @@ -527,7 +527,7 @@ export module RuleFunctions { compliance["minLogNnGuessNum"] = compliant; } - // dimension 7: same character (repeated in password but not consecutively) + // same character (repeated in password but not consecutively) if (config.sameChars.active) { var sameCharsLimit = config.sameChars.limit; var thisExplanation = ""; @@ -549,6 +549,23 @@ export module RuleFunctions { compliance["sameChars"] = compliant; } + // prohibit perviously-known leaked passwords + if (config.prohibitKnownLeaked.active) { + + var compliant = false; + var thisExplanation = ""; + + if (pw.length < config.prohibitKnownLeaked.smallestLength || !dictionaries.previouslyLeaked(pw)) { + compliant = true; + } else { + compliant = false; + thisExplanation = "" + noncompliantSymbol + "Not use a password found in previous security leaks"; + explanation["prohibitKnownLeaked"] = thisExplanation; + } + + compliance["prohibitKnownLeaked"] = compliant; + } + // potentialTODO reduce operation var overallCompliance: boolean = true; for (const item in compliance) { From 4e6b98c667feb5e425c2203be450e1c1b1a01e1f Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Thu, 28 Feb 2019 13:56:24 -0500 Subject: [PATCH 08/45] Don't ignore transcompiled file. --- .gitignore | 1 - src/PasswordMeter.js | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/PasswordMeter.js diff --git a/.gitignore b/.gitignore index cfe25b2..f7b9fc3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ -src/PasswordMeter.js src/node_modules src/package-lock.json diff --git a/src/PasswordMeter.js b/src/PasswordMeter.js new file mode 100644 index 0000000..6742927 --- /dev/null +++ b/src/PasswordMeter.js @@ -0,0 +1,37 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;it.split("").map(t=>t.charCodeAt(0)),simpleHashFn=t=>(r,e,s)=>e?(e-s*Math.pow(t,r.length-1))*t+r[r.length-1]:r.reduce((e,s,i)=>e+s*Math.pow(t,r.length-i-1),0),setBit=(t,r)=>t[r/8|0]|=1<!!(t[r/8|0]&1<r(t)%this.bufferBitSize)}getHashesForCharCodes(t,r,e){return this.hashFns.map((s,i)=>s(t,r?r[i]:void 0,e,this.bufferBitSize))}add(t){t.constructor!==Array&&(t=toCharCodeArray(t)),this.getLocationsForCharCodes(t).forEach(this.setBit)}exists(t){return t.constructor!==Array&&(t=toCharCodeArray(t)),this.getLocationsForCharCodes(t).every(this.isBitSet)}substringExists(t,r){let e,s;t.constructor!==Uint8Array&&(t.constructor!==Array&&(t=toCharCodeArray(t)),t=new Uint8Array(t));for(let i=0;it%this.bufferBitSize).every(this.isBitSet))return!0;s=t[i]}return!1}}exports.BloomFilter=BloomFilter; + +},{}],2:[function(require,module,exports){ +class PasswordLeaks{constructor(){this.hibpCache={},this.hibpTimings={}}sha1(e){var t=new TextEncoder("utf-8").encode(e);return crypto.subtle.digest("SHA-1",t).then(function(e){for(var t=[],s=new DataView(e),i=0;i=t;e--)for(var s=0;s=e)for(var h=0;h+e<=this[s].length;h++)i.push(this[s].substring(h,h+e));return i}; + +},{}],5:[function(require,module,exports){ +"use strict";var Config;exports.__esModule=!0,function(e){e.passwordMeterDefaultConfig={colors:{compliant:"#006600",noncompliant:"#660000"},symbols:{compliant:"✔ ",noncompliant:"❑ "},remindAgainstReuse:!0,ignoredWords:["mechanical","amazon","mturk","turk","survey","bonus","qualtrics","study","carnegie","mellon","university"],length:{active:!0,minLength:8,maxLength:0},classCount:{active:!1,minCount:1,maxCount:4},classRequire:{active:!1,upperCase:!1,lowerCase:!0,digits:!0,symbols:!1},classAllow:{active:!1,upperCase:!0,lowerCase:!0,digits:!0,symbols:!0},forbidChars:{active:!1,list:[]},repeatChars:{active:!0,limit:3},sameChars:{active:!1,limit:3,lengthException:20},usernameDifference:{active:!0,limit:1},minLogNnGuessNum:{active:!1,threshold:7,rejectionFeedback:"Not be similar to extremely common passwords"},prohibitKnownLeaked:{active:!0,smallestLength:5},blacklist:{active:!1,blacklistFile:"blacklist-cmu-compressed.txt",caseSensitive:!1,stripDigitsSymbolsFromPassword:!1,checkSubstrings:!1,checkSubstringLength:5,lengthException:20},neuralNetworkConfig:{intermediate:"basic_3M.info_and_guess_numbers.no_bloomfilter.json",file:"basic_3M.weight_arch.quantized.fixed_point1000.zigzag.nospace.json",zigzag:!0,scaleFactor:300}}}(Config=exports.Config||(exports.Config={})); + +},{}],6:[function(require,module,exports){ +"use strict";var Constants;exports.__esModule=!0,function(L){L.LOWERCASE_LETTERS=new RegExp("[a-z]"),L.LOWERCASE_LETTERS_GLOBAL=new RegExp("[a-z]","g"),L.UPPERCASE_LETTERS=new RegExp("[A-Z]"),L.UPPERCASE_LETTERS_GLOBAL=new RegExp("[A-Z]","g"),L.NONALPHA=new RegExp("[^A-Za-z]"),L.DIGITS=new RegExp("[0-9]"),L.DIGITS_GLOBAL=new RegExp("[0-9]","g"),L.SYMBOLS=new RegExp("[^A-Za-z0-9]"),L.SYMBOLS_GLOBAL=new RegExp("[^A-Za-z0-9]","g"),L.startASCII=32,L.endASCII=126,L.METER_STRINGENCY_SCALE_FACTOR=67/15,L.commonStructures=["LLLLLL","LLLLLLLL","LLLLLLL","DDDDDDDD","DDDDDD","LLLLL","DDDDDDD","LLLLLLDD","LLLLLLLLL","LLLL","DDDD","LLLLLLLD","LLLLLD","LLLLLLLLLL","LLLLLDD","LLLLDDDD","LLLLLLD","LLLLDD","LLLLLDDD","DDDDD","LLLDDD","LLLDDDD","DDDDDDDDD","LLLLLLLLLLL","DDDDDDL","LLLLLDDDD","LLLLDDD","LLLLLLLDD","DDDDDDDDDD","LLLLLLLLLLLL","LLLLLLDDDD","DDDDDDDDL","UUUUUUUU","LLLLLLDDD","LLDDDD","DDDDDDDDDDD","ULLLLL","LLLLLLLLDD","LLLLLLLLD","ULLLLLLL","UUUUUU","ULLLLLLD","LLLLLLLLLLLLL","ULLLLLL","LLLLLLLDDDD","LLLLLLLDDD","ULLLLLD","DDDDLLLL","LLLLLLLLLLLLLL","LLLLD","LLDDDDDD","DLLLLLLL","UUUUUUU","LLLLLLLLLD","DDLLLLLL","DDDDLL","DDDDDDLL","LDDDDDD","LLLDDDDD","ULLLLLDD","LLLLLLLLDDDD","DDDLLL","LLLLLLLLLDD","DDDDDDDL","LLLLLLLLLLLLLLL","DDDDLLL","DULLLLL","DULLLLLL","LLLDDDDDD","ULLLLD","LLLLLLLLDDD","DLLLLL","DDDDDDLLL","LLLLDLLL","LLLLDDDDDD","ULLLL","LLLDD","LDDDDDDD","LLLDLLLL","LLLLLLLLLLLLLLLL","DDLLLL","LLLDDLLL","DDDDDDDDDDDD","DLLLLLL","DDLLLLL","LLLLLDLL","LLLLLLLLLLDD","LLDDDDD","LLLLLDDDDDD","DDDLLLLL","LDDDDDDDD","DDDDDDLLLL","UUUUU","LLLLLLDL","LDDDDD","ULLLDDDD","ULLLLDDD","ULLLLLLLL","LLLLLLLLLDDD","DDDDDL","LLLLLLDDDDDD","LLLLLLLLLLDDDD","DULLLL","ULLLLDD","LLLLDDDDD","LLLLDL","LDLLLLLL","LLDLLLLL","LLLDLL","LLDLLL","LLLLLLLLLLD","LLLDLLL","LLLLLDDDDD","DDDDLLLLL","LDLDLDLD","DDDDDDDDLL","DDDDDDDDLLL","LLLLLLLLLDDDD","DDDLLLL","DDDDDDDDLLLL","DLLLLLLD","LLDDD","LDLDLD","LLLD","DDDDDDDDDL","DLLLDLLL","LDLLLL","LLLLDDDDDDDD","LLLLDLL","UUUU","ULLLLDDDD","LLLLLDL","ULLLLLLDD","DDLLLLDD","LLLLLLDDDDD","LLDDLL","DDDDLLLLLL","DDDDDLLL","DDDDDDDDDDDL","DDDDDDDDDDL","LLLDDDDDDDD","LDDDDL","LLLLDDLL","ULLL","LLLLLLLLLLLDD","LLLLLLLLLLLLLLLLL","DDDDDDLLLLL","LLLLLLLLLLLLDD","LLLLLLLLLLLD","ULLLLLDDDD","LDDDLL","ULLLLLLLLL","ULLLDD","LLLDDDDDDD","LLDDDDDDD","LLLDLLLD","DDLLLDD","DDDDDDDLL","LLDDDDDDDD","ULLLLLLLD","LLLLLDDL","DLDLDLDL","LLDDDDLL","DDDDDDDLLL","DLDLDL","ULLLLLDDD","LLLLLDDDDDDDD","UUUUUUDD","LLDLLLL","LLLLLLLLLLDDD","LDDDDDDL","DDDDDLL","ULLLD","LLLLDDDDDDD","LLDDLLLL","LLLDDDLL","DDDDDDLLLLLL","DLLLLD","DLLLL","LLLLLLLLLLLLLLLLLL","LLLDDLL","ULLLLLLLDD","LLDDLLDD","UUUUUUUUU","LLLLLLLLLLLDDDD","DULLL","ULLLDDD","DDLLLLLLL","LLL","UUUUDDDD","DDLLDD","DDDLLLLLL","DDDDDDDDLLLLL","LLLDDL","DLLLLLD","DDDDDDDLLLL","LDLLLLL","UUUDDDD","LLLLLLLDDDDDD","DLLLLLLLL","LLLLLLLLLLLDDD","LLLLLLLLLLLLLDD","LLLLLLDDDDDDDD","UUUUUD","UUUUDD","LDDLLLLL","LLLLDLLLL","DDDDLLLLLLL","LLLLLDDDDDDD","DDDDL","UUUDDD","LLLLLLLLLLLLD","UUDDDD","UUUUUUUD","LLLLLLLLLLLLDDDD","LDLDLDLDLD","LDDD","LLDLLD","DDDDDDU","LLLLDDL","LLLDDDDL","UUUUUDD","LLLLLLLDDDDD","DDLLLLLDD","UDDDDDD","LLDD","LDDDD","LLDDDLL","ULLLULLL","DDDDLLLLLLLL","LDLLLDLL","DDDDDLLLL","LDDLLL","LLLLLDLD","ULLLLLLDDD","ULLLLU","DDLLL","LLDDLLL","ULLLLLLDDDD","LDDLDD","LDLLDL","ULLLLLLLLLL","LLDLLLDL","","LLLLDLLD","LLDLLDLL","LLLDL","LLDLLLLD","ULDDDDDD","ULLULL","LLLDDDLLL","UUUUUDDD","LLDLL","UUUUUUD","LLLLDDDL","LLLLLLLLLLLLLD","LLLLLLLLDDDDDD","UUUUUUUUUU","LDLLLLDL","LLLLDLDL","LDLLDLLL","LLLLLLLLLLLLLLLLLLL","DLDLLLLL","DDDLLLDDD","DDDDDLLLLL","LLLDDDL","DLLLLDLL","LLLDLLDL","LLLLLLLLLLLLDDD","LDDDDDDDDD","ULLLLLLLLD","LDLDLLLL","LLLLLLLLLLLLLLDD","DDLLLLLLLL","LLDLDLLL","DLLLLLDL","DDDDDDDDU","DDDDDDDDLLLLLL","LDDDDDDDDDD","LDLLLLLD","DDLLLLLLDD","LLDDDL","LLLDLDLL","DLLL","ULLDDDD","DDLLDLLL","DLLLLLLLLL","DLLDLLLL","DDDLL","LLLLLLDDDDDDD","DDD","LLLLLLLDDDDDDDD","LLLDLD","DDLLLLLD","DLLDLL","LLLLLLDLL","UUDDDDDD","DDDDDDDDDLLL","LLDDDLLL","ULLLLLLLLDD","ULULLL","DDLLDDLL","DLLLLLDD","LDLLL","DDDDDDDLLLLL","DDLDDLDDL","ULULUL","ULLLUL","LDLLLD","UDDDDDDDD","LLLLLDLLL","LDLDLL","ULLLLULL","DDDDDDDDDDDDD","ULLLLLLLDDDD","UUUUDDD","LLLLLLLLLLLLLLLLLLLL","DDDDDDDDDDDDDD","DDDLDDD","DDLDDL","DLLLDL","ULLLUU","DLDLDLDLDL","ULLLLLLLDDD","ULLDDD","LLLLLLDLLL","DDDLLLLLLL","DDDDDDDDDDLL","DDLLLDDDD","UDDDDDDD","ULUULL","ULULLU","ULLLLLLLLLD","ULUULU","DDDDDDDDDLL","LLLLLDLLLL","DDDDDDDDDDDLLLL","ULUUUL","ULUUUU","ULLUUU","ULLULU","ULLUUL","LLDLDL","LLLLLLLDL","LLLLLLLS","LLDL","LLLLLLLLLLLLLLD","LDDDDDDDDL","LDDDLLL","LLLLLLS","ULULUU","LDDDDDDDDDDD","LLLLLLLLLLLLLDDD","LLLLLLLLLDDDDDD","DDDDDDLLLLLLL","DDDDDDDDDDLLL","LLLDDLLD","DDDLLDDD","LDDLDDLDD","LLLDLLLLL","ULLLLLLLLLLL","LLLLDDLLL","DDLLLD","LLLDDDDLLL","DDDDDDDDDDDLLL","LDLDLDL","LLLLLLLLDDDDD","LLLLSLLL","LLLLLLLLDDDDDDDD","DLLLDD","LLLLDLD","DDDDDDDDDDDDDDDD","DLDLLL","UUUUUDDDD","DDDDDDDDDDLLLL","LLLLDLLLLL","DLLLD","DDDDDDDU","DDDDDDUU","DDDLLLDD","LLDDDDL","DLLLLLLLD","LLLSLLL","LDDLLLL","ULLLDDDDDD","LLLLLLLLLLLLLDDDD","DDLLLLD","ULLULLLL","LLLDDLLLL","LLLLDDLLLL","DDDLLLLDDD","LDLL","LDDDDDDDL","LLLDLLLLLL","DDDDDDDDDLLLL","LDDDLLDD","LDDDLLLL","LLDDLLLD","DDDDDDDDDDDLL","LLLDLLDD","DDLL","DDDDUU","DDLDDLDD","DDDDDDLLLLLLLL","DDLDDDD","DDDDLLDD","LLLLLS","ULLDDDDDD","LLDLLDL","LDLDLDLL","LLLLDLDD","LDLLLLLLL","DDDLLLD","LLDLLLDD","ULLDDDDD","ULLLLLLU","ULDDDD","LLLDDLLLDD","UUUUUUUDD","LLLLLLLDDDDDDD","UUUDDDDD","LLDLLLD","UUDDDDD","LDLDL","UUUUUUUUUUU","LDLLLLDD","LLDLLLLLL","LLLDDLDL","DLLLDLL","DLLLLDD","LLLLLSDD","DDDDULLL","DDLLDDDD","LLLLLLLDLL","DLLLLDL","LLLLLLLLDL","LDLLLDL","DLDLDLD","LLDLDD","LLLDDDDDDDDD","ULLLLDDDDDD","LDDDLDDD","DDDDDDDDDDDDDDD","DDDDDDDDDDDDL","ULLULLL","LDLDLDLDLDLD","LLLDLLD","DDDDDDDLLLLLL","LDDDDDL","DDDLLLLLLLLL","LLDDL","LLLLLLDDL","LDLLDLL","LDLLDLDL","LLLLLLLLLLLLLLLDD","UULLLLLL","ULLLLLLLLLDD","LDDDDLL","LDLLDLLD","DDDLDD","DDLLLLLLLDD","LLLLLLLLS","UUUUUUDDDD","LLLLDDLD","UDDDDD","LLDDLDLL","DDDDDDDDLLLLLLL","UUUDDDDDD","DDDDLDDDD","LLDDLD","LLLLLDDLLL","DDLLLDDD","UUUUUUDDD","LLLLLDDLL","LLLLDDDDDDDDDD","DDDLLLLLLLL","LLLLLLLLLDDDDD","LDLLDD","LLLLLLLLLLLLLLLLLLLLL","LLLLLLLLLLLLLLLD","LLLSLLLL","DDDDLD","DDLDDD","DDDDUUUU","DLDLL","LDLLLLD","DLDLLLDL","LLLLSLLLL","LDLDLLDL","DDLDLLLL","DDDDDDDDDDDLLLLL","LLLLLLLLLLDDDDDD","UUUUUUUUUUUU","LLLDLDL","LLLLDDDDDDDDD","DDDDDLLLLLL","DDULLLLL","ULLLULL","LLLLLLLLLLLLLLDDDD","DLLDLLDL","LLLDLDLD","LLLDDDDDDDDDD","DDDDLLLLDDDD","LLLLSL","LDLDLLL","DLLLLLLLLD","LDLLLDLD","DDDDLDD","ULDDDLL","LLDLLLLLLL","LLLLLLSDD","DLDLLLL","ULLLLLLLLDDD","LLDLDLL","DDDDDDS","DDLLLLLLLLL","LDLLLDDL","ULLLLDLL","DDLLLDLL","DDLLDL","LLLLLSLLL","DLLLDDLL","LDLDLDLDL","DLLLDLDL","DLLDLLL","DLLDL","DLDLDLLL","LLDDLLD","DDDLLLLLDDD","DDSDDSDDDD","LLDDLLDL","DLLDLLLD","DLLLDDD","LLDLLDDL","LLLLLU","DLLDLDLL","LDDLDL","LDDLLD","LLDLLDLD","DDLLDDD","DDDDLLLD","DLLDDL","ULLLLLDDDDDD","DDDLDDDL","DDLLD","LLLLLDLLLLL","LLLDDLDD","LLDLDLLD","LDDDDLLL","DLLDDLLL","LLLLDDDDDDDDDDD","DLDLLDLL","LLDDDDDDDDD","DDDDDDUUU","DLDDLLLL","DDDLLD","LDDLLLLD","LDLLLLLLLL","DDDDUUU","LLDLDLDL","DLLLLDLD","DDLLLLDDDD","ULLLLDDDDD","LUULDDL","ULLLDDDDD","LDDLLLDL","ULLLLLLLLDDDD","DDLLLLDL","DLLLLLLLLLL","ULLLLLU","LLLLLSLL","DLLLLDDL","LDLDLLLD","DLDLLLLD","UUUDD","LDLDDLLL","LLLLLLDLLLL","LDLLD","DDDDDDUL","LDLD","DLLLLDDD","LDLLDDLL","UUUUD","LDDLLDLL","LLLLLLLLDDDDDDD","LLLDLDDL","DLLLDLLD","DDDDDDDDDDLLLLL","LLLLLDDDDDDDDD","DDDDDDDDUU","LLLLLDDDDDDDDDD","ULDDDDDDDD","UUULLL","LLLLLSLLLLL","LLLLLSLLLL","DLDLLD","LLLSDDDD","LLDDDDDDLL","DLLLDDDD","DLDLD","ULLLLLLLLLLLL","LLLLLLULLLLL","LLDLDDLL","LLLLLLLLLLLLLLDDD","DDDDLLD","LLLDDDLD","ULLLLULLLL","LDDLL","DDLLLDDL","DDDLLLLD","DDDL","ULDDDDDDD","LLLLLLLU","DDDLLDD","LLLLLLLLLLDDDDD","DDLDD","LLLLLLLLLLLLLLLLLLLLLL","UDLLLLLL","LLLLSDD","LDDLDLLL","DLDDLL","LLLLSLLLLL","LLLLSLLLLLL","LLDDDDDDDDDD","DLDDDD","ULLLDLLL","LLLDDDDLL","DDDDLDDD","DLDLDLDLDLDL","ULLLLLUL","DDLDLL","UUULLLLL","UDDDDDDL","LLLLLLDDDDDDDDD","LLLLLLLLLS","LLSLLL","LLDLD","DDDLDDDD","LLLLLLLLLLLLLLLLDD","LLLDDLD","LLLLLLSD","UUUUUUUUDD","LDLDDD","LLDLLDD","DDDDLLLDDDD","DDLLLLLLLLDD","LLLLDDDDLLLL","DDDDDU","UUUDDDUU","DDDDDDDDLLLLLLLL","LLLLDLLLLD","UUUUUUUUD","LLLLSDDD","LLLLLDDDDDDDDDDD","DDDLLLLLLDDD","DLLDDD","DLLDLD","LLDDLLLLL","UDDDDDDU","LSLLLL","LLLLLLULLLLLL","DDDDDDDDDLLLLL","LLLLLLDDLL","DDDDDDDDS","LLLLLSDDD","LDDLLDDL","ULLULLDD","DLLLLLLDD","ULLLLULLL","LLDLLDDD","UULLLL","ULLLULLLL","LLLLLLSLLL","LLLDDLLLLL","UUDDDDDDDD","LLLLLLU","DDDDDDLLLLLLLLL","ULLLDDDDDDDD","DDLDL","DLLDD","LDLDDL","LDDLDDL","LLLLLLDDDDDDDDDD","LLLLLLSLLLLLL","DDDLD","DDDDDDLD","DDLLLLLDDDD","LDDLDDDD","UUDDDDDDD","DUUUUUUU","LDDL","DDDUUU","ULULLLLL","LDLDLDD","LLLDDDDDDDDDDD","DLLDDLLD","UUUUUUUDDD","LLLDLDD","DDDDLLLDD","LLLLLDDDL","ULLLLLDL","ULULULUL","LLLLLLLDDL","LDDLLLDD","ULLLLLLLLLLD","DDDULLLL","LLLSLL","LLLLLLSL","LLLDDDLLLDDD","LLLDDDLLLL","LLLLDDDLLL","LDLLLDDD","LLLSLLLLL","LLLLDDDDL","LLLLDDDLL","LDDDL","LLLLLLULLLLLLL","DDDDDDDDDDLLLLLL","LLLLLLLSDD","UDDDDU","LLLDLDDD","LLLLLSLLLLLL","LLDDLDD","DLDDL","LDLLLDD","LLLLLLDDLLL","DDLDLLL","DDDDDDDDDDDU","LLDDLDL","DLLDLLD","LDDDDLDDDD","LLLLLLSLLLLL","DDDDDDDDDLLLLLL","UUUUUUUDDDD","ULDDDDD","LLLDLLLDDD","DDLLDDL","ULLLLLDDDDD","LLDDDLLD","UUUULLLL","ULLLLLUU","DDDDDDDLLLLLLL","LLLLDDDLLLL","DLDDLD","DDDDLLDDDD","DDSDDSDD","ULLDLLLL","LDDLDDLD","DDDDDDDDUUU","DLLDDLL","DDDDDDDDDDDDDDDDDD","LLLLLLLLLLLLLLLDDD","ULLLU","LLLLLLDLD","UUDDDDUU","LLLLLDDDDL","LLLLLLLLLLLLLLLDDDD","LLLSDD","LLLLLLSLLLL","LLLLLLLLLDDDDDDD","LSLLLLL","LDDDLD","ULLLLDDDDDDDD","DDDDLLLLLDDDD","DDDDDDDDDU","LLLLSDDDD","LDDLDDLL","ULLLLUDD","LDLLDDDD","ULLULLLD","LLLDDDDDDLLL","LLDDDDDL","ULLDDLLL","DDDLDL","LLLLLSL","LDLLDLD","LDLLDLDD","LDLDLLD","DLDLDD","DDDDLLLLLLLLL","LLLLDDDDLL","LLLDLLLLD","DDLLDLL","DDLLLLLLDDDD","ULLDD","UUUDDDDDDDD","ULULLLL","DDLDDLLL","LDLDLLDD","ULLLULLD","DLLDLLDLL","DDUUUUUU","LDDLLDD","ULULDDDD","LLLLLLLLDLL","LLLLSLL","LLLLDLLLLLL","DDLLLLLLLLLL","LLDLLDLLD","LLLLLSDDDD","LLLLLLLLLDL","DLDLDLDLD","LLLLLSD","LLLLLDDLLLL","DDDDDDDDDDDDLLL","DLDL","LLLLDDLLLLL","LLLLLLLDLLL","LLSLLLLL","DDLLLLLLD","DDLDDDDD","LDDLLLLLL","LLDDDDLLL","DLDDDL","LLLLLDDLLLLL","LLLLLLLLLLLLLLLLLDD","LLLLLLLLLLLDDDDD","LLLLLLLSLLLLLL","LDDLLDL","LLLLLLUU","DULLLLLD","UUUUDDDDDD","DLLD","UUDDD","LLLLLLLDLLLL","LLLLLLLLLDDDDDDDD","LDLLDDL","DDULLLL","ULLLDL","DLLLDLLLDLLL","LLLLDDDDLLL","LDLDLDDD","LLDLDDDD","DLDDD","DDDDDDDDDDU","LLUULL","LLLLLLSDDD","UULLDDDD","LLLLUU","LDLDDLDL","DDDLLLDL","LLLLLLLLSDD","DDDLDLLL","UULLLLL","ULLLLLLLLLLDDDD","DDDDDDDDUL","ULLLDDDLLLL","LLLSDDD","DDLDDLL","DDDSDDD","LLLULL","DDDDUL","DDDDDLLLLLLL","UUUUDUUU","DLDLDLL","LDLDDLDD","LLLLLLLLLLLDDDDDD","DDDDULLLL","ULDLLLLL","DDLDLD","DDDDDDLLLLLLLLLL","DDDDDLDD","DDDLLLLLDD","LDLDLDDL","ULDLDD","LLLLLLDDDL","DLLLLDLLL","LLLUUU","LLLLLDDDLL","DDLLDLLD","DLLLDDDL","DDDDDDDDDDDDLLLL","DLLLDDL","LLDDLDDL","ULLLULLLLL","DLDLLLD","ULLDLL","DLDLLLDD","LSLLLLLL","DLLDDDLL","DLLLLDLLLL","DDDLLDLL","ULLDDDDDDD","LLLLLLLSD","LLLLUL","DLLDLLDD","LLLSLLLLLL","UDLLLL","LLLLLLSLLLLLLL","UUULLLDD","DDLDDLD","LLLLLLLLLLLLLLLLD","DDDDDDDS","LULLLL","LLLLLLSDDDD","DDUUUUU","UDDDDDDDDD","LLSLLLL","DDDDLLLLDD","LLLLLLLSLLLLL","DDDLLLLDD","LDDLLLD","LLLLDLLLD","LLLLULLL","DDULLL","DDSULL","LDDDLLLD","LDDDDLDD","DDDDDDDDDDDDLL","LLLLLLLULLLLL","ULLLLLLLLLDDDD","UUUUUDUU","DDDDDLD","ULLDDDDDDDD","LLLLLLLDDDDDDDDD","ULLLLULLLLL","DDLLLDL","LLLLLSLLLLLLL","UUUDUUUU","DDUUUU","DLLLLLLLLLLL","LDDLD","LLLLLLULLLL","LLDLDLDD","UULLLLDD","ULUL","ULLLLUUU","ULLLDDDDDDD","LDDDLDLL","DLDDLDLL","LDLDDDDD","LLDDDDDDL","ULLLLLUD","DDDDLLLLLLDDDD","UULLLDDD","ULLLLLDDDDDDDD","DLLLDLLLL","LDDLLDLD","DLLLLLLDL","LLDDLLLLLL","DLDDDLLL","LLLLLULL","DDDDDDDUU","DDDLLLDDDLLL","UUDDDUU","LDDLDLDL","LDDDDDLL","DDDDDDDDDDDDDDDDDDDD","UULLUU","LLDDDLDD","UUU","LULULU","UUUDLLLL","UDDDUU","DLLLDDLD","DDLLDLDL","DDDUUUUU","LDLLDDDL","DLDDDDDD","SLLLLL","LLLDLLLLLLL","UDDDDDDDDL","LDLLDDLD","UULLL","LLDDDLDL","LLLLLDLLD","ULLLDLL","DDLDDLDDDDL","LLLLU","UUUUUUDU","ULLLLLULLLL","DDLDDDDL","ULLLLLULLLLL","DLLDDLDL","DLLLLLLLLLD","LLLLLLLSLLLL","UDDDDDDDDDD","ULLLLLULLL","LDDLLDDD","DLLLDLD","DDDDDUU","DDLDDLDDDD","UUUUUUUUUD","DLDLLDL","LLDDDDDDDDLL","LLDLLLLDL","LLLLLLLLLLLLLLLLLLLLLLL","DLLDDLD","DLDDLLL","DLDLDDLL","DDDDULL","LDDDLLDDD","LLDDLDLD","LLLLLLLLLLLLLLLLDDDD","DDLLLLDDD","LDLDDDLL","LLLDDDDLLLL","DLLDLDL","DLDLDLLD","LDLLLLDLL","LLULLLLL","UUUUULLL","UUUUUUUUDDDD","ULLLLDDDDDDD","LDDDDDDDDDL","UDUDUD","DUUUUU","LLLLSLLLLLLL","UDDDD","DLDDLLDL","DDLDLDLL","ULLULULL","DDDLDDL","DLLDLDLD","LLDLDDL","LLULLL","UDLDLDLD","UUULLLL","LLLLLLLULLLLLL","DLDDLLLD","ULLLLDL","LLDDDDDDDDDDD","LLDLDDLD","LLLLLLSLL","DDLDLLDL","DDLLLDLD","DDL","LLDLDLD","LDDDDDDDDDDL","LDDLDLLD","DLLDDDD","DDLDLLLD","ULLDLLL","DLLLDLDD","LDLDD","UDDDDDDDL","LLLLLLDDLLLL","DDDDDUUU","LDDLLLLLLL","UDUDUDUD","DDDLDLL","DLDLLDDL","LLLLLLSLLLLLLLL","DLLDLDDL","ULLULLD","LLLLDLLDD","LDDLDLDD","ULLLLLLLLLLDD","ULLLLLLDDDDDD","ULLLLLLLLLLLLL","ULLSDD","LDDDLDD","UDLLLLL","DLDDDDD","LLLLLLLLLLDDDDDDDD","LUUUUU","DDU","LULULL","LLLLLLLLLLLLLLLLLLLLLLLL","LLLLLLLSLLLLLLL","LDLDDLLD","LLLLLLLSLL","DLDLLDLD","DLDLLLLLL","UUUUUUUUUDD","LDDDLLDL","UUUUUUUUUUUUU","DDUUU","LDLLLLLLD","LDLDDDD","DDDDLLDL","DSDSDDD","DLDDLLD","LLLDDDLLLD","LDDLDDD","LLLLLLLDLD","LLULUL","LLDDLDDD","ULLLLLULL","LLLLDDLLLLDD","LDLDDLL","LLLDDLLDD","DLDLDLDD","LLLLLLLLLSDD","LLDDDDDLL","DDDDDLLD","LLLLLDLDL","LLLLLLDLLLLL","UUDUUUUU","LLLLLLLLSLLLLLL","LLLLLLUUUUUU","SSSSSS","LLLLLLLLLLLLDDDDDD","DDULL","LLLLLLLLLLSLLLLL","DDDDDS","LLDLDDD","DLLLLLDLL","ULLLLUD","DUUUU","LLLLLLLLSL","DLDDLDDL","LLLLLLLLLLLSLLLL","LLLLLDDDLLL","ULDLLL","ULLLLLLULLLL","UUUDDDDDDD","ULLLULLU","UULLLU","ULLLULUL","LDDLDLL","DUUUUUU","DDDDLDDDDL","LLLLLLLLSLLLLL","DDDLLDL","LLLLLLLLLDLL","ULLLLLLDDDDD","LLLLLLLSLLL","LLLLLLLLLSLLL","UDUUUUUU","LDLDLLLLL","DDDDDDUUUU","DULLLULL","DDDDDDULLL","LLDLLLLLLLL","ULLULLUL","LLDDLLLDD","LLLLUD","UUUD","ULLDDULL","ULLLLLLLLLDDD","LLLLLLDDDDL","DDDDDDDLLLLLLLL","UULLLLLD","LDLLDLLLL","LLLULLLL","LLDLLLLDLL","DDLDDLDDLDDL","LLLLLSLLLLLLLL","LDLLDDD","ULULU","LULLUL","LLLULU","LLLLLLLLLLLSLLLLL","DDDDDDLU","UULUUL","LLDDLLDDLLDD","LLLLLLLSL","DDLDDLDL","LLLLLLUD","UUUUUULL","UDDDUDDD","LLLDDDLLLLLL","ULLLUD","ULLLDDLL","LDDDDDDDDDDDD","UDDDDDDDDDDD","ULULL","ULLLLDDL","DDLLDDDL","DDDDLDDL","SLLLLLL","LLLLLLLDDLL","DDDDLLLLLDD","ULULULU","SLLLLLLL","LLLLDLLDL","UUDDUU","DDLLLLLLLLLDD","UUUULU","UUUDDUUU","UUULUU","LLUULU","DLLDLLLLL","LLUUUU","ULLULULU","ULUUUULL","DDLDDDLL","LLDLLLLLD","ULLLDULL","DDDDLLLLLLLLLL","ULLULLLU","LLLLLLLLLLSLLLL","DULLLLLLL","ULLUDDDD","LLLLLDDDDLLLLL","LLLLDDDDDDDDDDDD","DDDDU","DDDULL","DDULLLDD","LLLLLLLLSLLLL","LLDLDDDL","LLLDLDLLL","LLLLLLLSDDDD","LLDDDLD","UUUUDDDDD","DSDSDSDDD","DDDDULLLLL","DDLDDLLD","LLLLLLLULLLLLLL","ULLULLLLL","ULULLLUL","LDLLLLLLLLL","UUUULL","LLLDLLDLL","LDLLLLLDL","ULULULLL","DDDLLLLLLLDDD","DDUUUDD","LLLLLLLLULLLLL","LDDLDDLDDLDD","ULLUULLU","DLLLLLLU","ULULLLLU","LDDLDLD","LLLUDD","UULULL","LLLLLLLLLLLLLLLLDDD","UUUUUDDDDDD","LLDLLLDLL","DDDLDDLL","DDDUUUU","LDDDLLD","LLLLLLULLLLLLLL","DDDDDDULL","LLLLLLLLSLLL","UUUUUUUUDDD","LDLDDLD","ULLLUULL","ULULLULL","LLLLLLLLDLLL","LLLLLLLLLLSLLL","LLLLLLLDDLLL","DDDDDDDDDDS","LLLLLLLLLLLLDDDDD","UDDDDDDDDU","LLLLLLLLLLDL","ULLLLULU","LLUUUL","DUUUUUUD","LUULUU","LLLLLLLLLLLSLLL","ULULUUUL","LLLLLLLLLLLLSLLL","LDDDDDDLL","UUULLLDDD","ULLLULLLLLL","DDLLDDLD","ULULLULU","LLLLLLLSDDD","LLLLLLLLLSLLLL","DDLLDLD","ULLUL","LLLLLLLLLLLLLLLLLLDD","LLLLLLLLLSLLLLLL","DUDLUDUL","DLLLLDDDD","DDLDLLDD","UUULUL","LLLLLLLLDDL","LLLLLLLLLSLLLLL","ULLUUUUU","SSSSS","UULLLULL","DLDLLDDD","ULLULLUU","ULULUULU","LULUUU","LLLLLLLLSLLLLLLL","LLLLLLLSLLLLLLLL","LLLLLUUU","LLLDDLLLLLL","ULLLLUL","DDUUUUDD","DDLDDDL","LDDLDDLDDDD","LLLLUUUU","UULLLLLU","LLLULLL","ULULLLUU","ULLUULLL","DDDDDDDDDDDDDDL","LUULLU","LLLDLLLLLD","LLDDLLDDLL","LDDLDDLDDL","LLDDDLLLL","LLLDLLLDL","LUUULL","LUULLL","DLLDLDD","UULLUUUL","ULULLUUL","LDLDLDLDLDL","DDLDLDDL","ULUUULLL","UULLULLL","ULLLUUUU","DDUU","LLLDDDLLLLL","LLLLLLUUUUUUU","UUUDUUU","LLULUU","LLLLLLLLLLLSDD","ULLLLUUL","ULUULULU","LLLUUL","LLLLLDLLLLLL","LULLLLLL","UUDUUU","DDDDLDLL","LLSLLLLLL","LLLLDDDLLLLDDD","UUUULULL","UUULLUUL","LLLLLLLLLLLLSLLLLL","LULLL","DDDLLLDDDD","DDDDDDDDUUUU","LLLLDLDLL","LSLLL","DLDLDDDL","LDDDLLLLL","LDDDDDDDDDDDL","UULLLLUL","UULUUU","UUULLLLU","UULULU","ULUULULL","UUUUULUU","UUUDU","ULUULUUL","UUULLULL","ULLUUULU","ULULULLU","UULLLLUU","UUDUU","DULULLLL","UULLLUUU","DDDDLDL","ULLLULUU","UUULLLLD","LLLLLLLDLLLLLL","LLLLLLLLDLLLLLL","DDDLDLLD","DDLLLLLLLD","LLLLLLLLSLLLLLLLL","LLDLLDLLL","UUULULLL","LLLLLLDDDLLL","LLLDLLLDD","UUULUULL","ULLUULUL","UULUUULL","UULLULLU","LSLLLLLLL","LLLLSLLLLLLLL","DLLLLLDLLL","LDDDLLDDLLL","LLLSLLLLLLL","LDLLLDLLL","DLLLDLLLLL","LLLLSD","LLLLLDDDDLL","LLDDDLLDDD","LLLLLLDLDL","ULDDLLLL","LLLLDDLLLLLL","LLDLLLLLDL","UDDUDD","DDLLDLDD","LLLLLLDDS","UUUDDLLL","ULUULUUU","DLLDDDDD","DDUUDD","UULLULUU","DDLUL","DDDDDDDDDDDLLLLLL","LUUULU","DULLU","DULUL","LLLLLLLLDLLLL","LLLDDLLLD","DDDDDDDDULLL","DDDULLL","DDDDDDUD","UULULLLL","ULLLLLLLU","ULLULUUL","ULLUUULL","LLLUUD","LLLLLLDLLD","LLLLLLDDDLL","UUUUUUUUUUUUUU","LDDDLDDL","UDDLLLLL","UULLLUUL","DDDLLDDDD","DDUUL","ULULDD","UULULULU","UDUUU","DDLLLLLLLDDDD","ULUUUUUL","DLDDLLDD","LSLLDDDD","DDDDDDDDDDDDDDDDD","LLULL","DULLULLL","LULLLU","LLLLLLLLLLLSLLLLLL","LLLLLLLULLLL","UUUUUL","ULDDLL","DLLLLLLLDD","UULLUULU","UDDDUUDD","LLLLLLLLULLLLLL","DLDDLDL","UUUUUUDDDDDD","DDLLU","DDDLLLLLLLLLL","ULLLLSDD","LLLLLLLLU","LLLLLLLLLLLLLLLLLD","DDDDDDDDDDDS","UUULLULU","LLLLDLLLLLLL","DDDLLDDL","DDDDDDULLLL","LLDLLLDLLL","DLDLDDD","LLLLLLLLSD","UUUUUUUL","DDDDDLDL","LLLUL","UUUUUULU","DULLLLUL","LLLLLUDD","LSLLLLLLLL","DLDLLDD","ULLLLLDDDDDDD","UUULULUL","LLUUL","UULULLUL","LLUUUD","UUUULUUL","ULLDULLL","ULDDDDDDDDD","DDLLDDLLDD","ULLUULUU","ULUULLUL","ULUUULLU","UUULUUUU","UUUUDU","DDDDLLLLD","UULUUUUU","ULULULUU","DLDLDDL","LLLLLLULLLLDD","ULULULDD","DDDLLLLLLLLDDD","DDUULLLL","ULLLULLLDD","LLLLLDLLLLLD","ULLLUUUL","DDLDLDD","ULUULLUU","DLLUL","UUULLLUU","DDDDSDD","DDLLDDDDDD","DDDDDDLLLLDD","LLLLLLLLLLSLLLLLL","UUULLLUL","DDDDDDDUL","UUULULUU","LLLLLDDDDLLL","DLLUU","DLLLLLLLLLLD","ULLLLLSD","LLLLLLLLLLLLSLLLL","UDDDDUDD","LLLLLLLLULLLLLLL","DDLDLLD","DDDDLLLDDD","UUUDUU","ULULUULL","DDDUU","LLLLLLLDLLLLLLL","LUULUL","UULLUUUU","DDDDDDLLLLLDD","DLLULLLL","DDLDLDLD","DDDLDDLD","ULLLULDD","ULDLLLL","DDDDUDDD","LDDLDDDL","DDLDLDL","ULLLLLSDD","UDDDDDU","ULULLUUU","LDLDLDLDLDLDLD","LLLLLLLLLLLLSDD","DLLLDLLLD","DLDDDLDD","ULUUUULU","UUUUDDDDDDDD","UUUUUDDDDD","DUUULLLL","ULLULUUU","LDLLLLDLLL","LLLLLLLLLLLDDDDDDDD","ULLLLULLLLLL","LLULU","DLUULLUL","LLLLLLULLLLLDD","UUUUULUL","ULLLUDDD","LLLLDLDLLL","DDUDDUDD","DULLLULU","DLLLLLDDDD","LLLLLDDDDLLLL","UUULL","DLLDDLDD","UUULUULU","DDDDDDDDDDDDDL","ULLLUULU","UULUULLU","DUULLUUL","ULLLLLLLDDDDDD","ULUULLLU","DLLULULL","LUULL","DLDDDLLD","LLLLLLLLLLSDD","DDLU","DULULUUL","DLDDLDD","UULLULUL","DDLDDDLD","LLLLDDDDUU","DLULU","ULUUUUUU","LLLLLLLLDDLL","LLLLDLLLDL","DDUL","ULULUUUU","ULUULLLL","UDDUDDUDD","LLDDDDLD","LLULLU","UDUUUU","UUUULLUU","LLLLLLDDDDLLLLLL","DDDLDLDL","ULUUULUL","UUULULLU","UUDDUUDD","ULLLLLDDS","DLLDDDL","DDDDDDLLLLLLDD","UULUULLL","UULULULL","DLLLULLU","ULULLLLD","DULLLLLU","LLDLDLLLL","DLDDDDL","ULULUD","UUUULLLU","UUUULLUL","UUULLUUU","DUUULLUL","DUUULULU","UULLUULL","DDDDDDLDD","DDDDUUUUU","DDDLLLLLD","LLLLLLUL","DLLLLLLLDL","LLDLLLLDD","DULULLLU","DDDDLLDDD","UULUUUUL","DULULULU","DDDDLLLLLLLDDDD","LLDLLLLLLD","LLLLLDLDD","UULULLLU","LLLDDDDLLLLLL","LLLLLLDDDDDDDDDDD","DLDLDDDD","LLLLLLLLLLLLLLLLLDDDD","DDDDLDLD","LLDDDDLLLL","LLLLLLLDDDL","DDLD","LLLUU","DDDLDLD","DDULU","DUULLLUL","UUUUULLU","DLLDLDDD","DDLDLDDD","ULLUUUUL","DLLUUULU","ULLU","DUULLLLL","UULUULUL","UULULLUU","LLLLDU","DLLUULUU","DDDDDDDDDLLLLLLL","DLLLLLUU","ULUUULUU","DDDDDDDUUU","ULDDD","LLUUU","DLDLDLDLDLD","DDLLLDDLL","LLDDDDDDDLL","DDDLLDLD","ULLDULLD","DLLLULLL","UULLLULU","DULULULL","UULUULUU","DDLLLLLDDD","DULULLUL","UDDUDDDD","UUUULULU","DDDDLLLLLLDD","DUULU","DLLLLULU","DDULLLLLL","DLLLULUU","DDDUDDDD","LLLLLDLLDL","UUDDDDLL","DLDLLLLLLL","DDLLLDDLLL","LLLLLSLLLLLLLLL","LLLLLLLLLLLLSLLLLLL","ULLLUDD","LLLDULLL","DUUUL","DDDDDDSS","UULULUUL","LLLDDDDDDDDLLL","DUULLLLU","LLDLLDLLLL","DUULLULU","LLLLLUU","DDLDDDDDD","DUUULLUU","DDLUU","LLLLDLLDLL","DLDDDLL","UUUULUUU","LLDLDLLLLL","DLLLU","LLLLLLLDLLLLLLLL","LLLLLDLLLD","LLULLD","LDLLLLDDL","DDDLDLDD","UUULLU","DDDDDDDDDS","DUULULUU","UDDUDDD","ULLLUUU","DLULUUUL","UDDDDL","DUUUULLU","LLLLLLLLLDDL","LLLLLLLLLLSLLLLLLL","LLLUUUDD","LDLLLDLLLL","DLDDDLD","LDDDDLD","DULUUULL","DLLUUULL","DULUULLU","UULUUULU","LLLLLDDS","ULLLLLDDDLLLL","ULLDL","UULLLD","LLLDDDDLLLLL","DULLLUUL","LLLDLLDLLL","DUULULLL","UULLUL","DDDDLLLLLLLLLLL","ULLLLLLDDDDDDDD","ULLLLUU","DLUUULUL","DULUULLL","DDDDDDDLDD","DLLULLLU","ULLLLULD","ULLDLLLD","DULLULUL","DLLDDDDL","LUUUUL","DUULD","DLUUUULL","DUUULLLU","LLLLLLLLLLLLLSLLLLL","LUUUU","UULLLDD","DDULLLLDD","DLLULL","UULLDD","DSULL","DLLLUULL","UULULUUU","ULUUL","DUUUULUU","DLULLULL","UDLLLLLD","DDLDLLLLL","UULUL","ULLLLLLULLL","LLLLLLDS","UDDDDDDDU","LLLLLLLLLDLLL","DLLUULLL","LLLDDDDDDDDDDDD","DLLLLLDDD","DDDDDDDDDDDDDDDL","ULUDDD","DULLUULL","LLLLLUD","ULLLLLLLLLLLLLL","LDDDLDLD","UUUUDUU","UDDDDDUD","DLULLLLU","LLLDLLDDD","LLLLLLLLLLLLLLLLLDDD","ULDDDDLL","DULLUULU","DUUUULUL","LDLLLLLLLD","LLDLLDDDD","DDLLDDLLDDLL","DLULULLL","DULUULUL","DULLLU","DLLLULUL","DUULLLUU","LULLUU","DUULLULL","DLDDDDLL","LLSLLLLLLL","DDDDDDULLLLL","ULLULLLLLL","DULUU","DULLULLU","LDDDDLLD","ULULLLDD","DLLLLLUL","DUDUDUDU","LLLLLLDLLLLLL","ULDDULDD","DULLUUUL","LLLLLDDDLLLL","ULDULL","LLLLLDDDLLLLL","DLLLUUUU","LUDDDDDD","ULDULD","UDLLLLDD","ULLLDLLLL","DUUULUUU","ULLD","UUUDUUUD","ULLLLLLS","DUULULUL","DUULUUUL","UDDUDDUD","DLDDDLDL","UUUUUUUUUDDD","LLDDDDDDLLL","DLDDLDDD","LLLLLLLLLLS","DDULLDD","DULULLUU","DUULULLU","UUDDUUUU","LLLLLLLLLLLDL","DDDDDDLLLLLLLLLLL","ULLLLUUD","DLDLLLLLD","UUUDDDU","DULUULUU","LLLLLLLLLLLLLDDDDDD","ULLLULLLD","DLLUULLU","LULUUL","DUUULUUL","UUUDDUU","LLLDLLLDLL","DUUUUUUL","DUULL","LDDLLLDDL","DDLLLLLLLLLLL","UUUUDDUU","DDDDDDDDLLLLLLLLL","ULLUU","LLLLULLD","UUUDDDDU","LLLLLLLLLSLL","DDSDDSDDDDS","DLLUUUUL","UULUU","DLUUULLL","LLLLLLLLDLLLLLLL","DULULUUU","DLLDDDLD","DLUUULUU","DDDDDDLLD","DULULU","ULL","ULUUU","ULLDDLL","DULUUULU","DUUUUULU","UUUUUDDU","LLLLULL","LLLLDDDDDDLLLL","UUDD","DUULUULL","UUUUL","DLLLDDLLL","LLLLLLLLLLLLLDDDDD","ULULLLD","ULLLLLDLL","DDDDDUDD","LLLLLLDDDDLLL","DLULLLLL","DLUULULL","ULLLLLLLLLLLDD","DULLLUUU","LLLDLDLLLL","LLLLLDLLDD","ULLLLLLDS","DULLLLD","LUUUUUUU","ULLLLLLLLLLDDD","ULLUDD","ULLLLLLLLLLLD","LLLLUULL","DLULUULU","DDDDSDDDD","DDDUUDDD","LLLLLLLLLLLLLSLLLL","DLLLLUUU","DLLULLUU","DUUUULLL","DUULUULU","LLDDDLLLLL","LLLDDDLLLLLLLL","DDDDDDLLLDD","DUUULULL","DLDULU","DLUUULLU","DULLUUUU","DUUDU","LLLLLLLLLLLLSLLLLLLL","LULULULU","LLLLLDDLD","DLUULLLL","DDDDUUDD","LLLLLLLLLLSLL","LULLU","DLLULLUL","DULUUUUL","DDSDDSDDS","ULLLLLULLLLLDDDD","ULULUDDD","ULLLLLUDD","LDLDDDL","DUULUUUU","LLLDDDDDDDLLL","LLLLLLLLLLLLDDDDDDDD","DLDDLDLD","LLLDDDDDLLL","DUULLUUU","UDUDDDDD","LUUUL","LLLLUDDD","DULUUUUU","ULUDDDD","LDLLDLLDL","UUULUUUL","DLDD","LULUULUL","LULUL","DUDUUUUU","DLLLLULL","LLLLLLDDLLLLLL","DDDUDDD","DLLLLLLDLL","LLLLLLLLLLLLDL","LUUULLUU","DDLLLLLLLLLLDD","LLLLLLLLLSLLLLLLL","UDDDDDUU","LLLLDLLDDDD","DULLULUU","LLLLLLSS","DULLLLUU","LLLLDDDLLLLL","DLUULUUU","LLLLLLLLLLLSLLLLLLL","UDLDLD","DUDDDDDD","UUUDDDLL","LDLLDLLLLL","LLLDDDLLLLLLL","LDLDLLLLLL","DLULLLUU","LLLLSS","LLLLLLLLSDDD","UUUUUUUUUUUUUUU","LLLLLLDDLLLLL","UUDUUUU","DLULLUUU","LLLDLLDDDD","SLLLLLS","ULULULUD","LLLLLLDDDDLL","DDDDLLLLDDD","LLLLUUU","UUUDULLL","DULULL","LLLLLLLDLLLLL","LLLUULLL","LLLLLLULLLLLLLLL","LLLLLLLLSLL","UUUUUUUUUUDD","LLLULLLD","LDLDDDDL","LLUUUULL","ULLDDDLL","LDLDLDLLL","LLLLLLLLLDLLLL","ULULDDD","LLLLLDLDLL","LLLLLLLLLLDLLLL","UDDUDDU","DLLUUL","ULLLULLLLLLL","DDDDDULL","LLLLLLLLLLLLLSDD","DLLLLUUL","LUULU","DLUUUUUL","DDDULLLLL","LLLLLLLLDDDL","DUUUUULL","DLUUL","LLLLLLUUUUUUUU","LLDDLLDDD","ULDDDDDDDDDD","LLLLLLDU","DLULUULL","DDDUL","SLLLLLLLL","LLUUUUUU","DLUULLUU","LLLLLLSLLLLLLLLL","LLSLLLLLLLL","UUUDDDLD","LLLSLLLLLLLL","LLLLSLLLLLLLLL","DDUDDDDD","DLLDLLLLLL","LULLLLLLDD","DDLLDDLLL","LDDLLLLDL","LLLLLLLDDDLL","DLLUUUUU","LLLDLLLLDL","ULLLLDLD","DLLLUULU","LLLLDDDU","LLLLLLLLLSD","DLUUUULU","DLLLLDDLL","LULLLLLU","DLLUULUL","UULLU","LLLLLLLLLLLSL","LDLDLDLDLDLDLDLD","DLLLUL","ULUUUD","DLDDDDDL","ULLLDLLD","LLLDLLLDLLLD","DLDLDDLD","LLLDDDDLLLLLLLL","LLLLLDDU","LLLLLLLLSDDDD","LLDDLLLLD","DLULLULU","LLLULLLU","LLLU","ULLLLLDS","LLLLLLLLDLLLLLLLL","UULLLLD","DLDUU","DLULUUUU","UUDDDDDU","LLULUD","LLLLLLULLLDD","LDLLLLLDLL","UUUULLLD","LLLLLLLLLLLLLLLLLLD","DDUDDU","DUUUUD","DLLULUUU","DDUDDDD","LSSL","UULDUU","LLDDDDLLDDDD","UDDDDUU","DDDDDDDDULLLL","UUUUDDDDDDD","LLULLLLU","DLULLUUL","USLLLLLDDDD","LLLLLLLDS","LLLLLLLLDLLLLL","LLLLLLLLLLDLL","ULLLLLLLDDDDD","LLLLLLLLLLSL","LDDDDLDL","UUUULLL","LLLSL","LLLLDDDDDDDDLLLL","ULLLLLS","ULLLLDUL","DDDUDDDU","LLUDLU","UUUDUDD","DDDDLLLLLLLLDDDD","DDLLLLLU","DLLLLLLLLLLLL","LUULLLUU","LLULLLL","UUULU","UUDDUUU","LLLDDDDLLLLLLL","DDDLLLLLLDD","LLLDLLLLDD","DULLD","DLULLL","DUUUDUUU","LLDLLLDDDD","LLLLLLLLLLLLLLLLLLLDD","LLLLLLLDDDDDDDDDD","LDLLLLLDD","LLUULLLL","UUULLLD","UUUUUDDDDDDDD","LDLDLDLDLL","DDDDDDUUUUU","DDDDDDDLD","UDLLL","UUDDLLLL","UUDDDDU","LULLLULL","DDDDDDDLU","DLULLU","LLLLLLLLDDLLL","LLLLULUU","DLULLLUL","LLLDDLLLLD","DLULL","DLDLDLDLL","LLLLLLLLLLLLLLLLLLLLLLLLLL","DULDL","ULLLUDDDD","ULLLDU","DDDLLLLDDDD","DULUUU","DDDUUUDD","ULLLLDDU","SDDDDDDS","LLLUD","DUULLU","DLLULUUL","LDDDDLLLL","LLLLLLLUUUUUU","LLLLLLLLLLDLLL","LDDDDDLD","LDLLLLLLDL","DULLUL","UDULLLLL","DDUDD","DLUULUUL","LLLLDDDDU","DUUUUDUU","LLLLDDDDLLLLL","LLLUUULL","LLLLLLLLULLLL","DUUDUUUU","LDDDLDDDD","LLLLLLLLLLLSLL","ULDLLLLU","DLUULULU","LDDDLDL","ULLLLLDU","LUUUUULL","LLDULL","LLLLULLLL"],L.blacklistedSubstrings=["12345678","password","23456789","11198","land","blue","04199","07199","02199","06199","08199","angel","10199","09199","12199","11199","01197","05197","07197","a199","04197","03197","10197","08197","123123","12197","06197","master","dragon","09197","fish","02197","black","11197","a200","2112","fire","mike","baby","pussy","line","test","mark","cher","wood","mama","bear","cool","ling","anne","fred","illa","a198","anti","alle","marc","monkey","life","man1","dick","ness","good","daniel","sexy","o123","time","assi","gold","shan","shadow","rain","ters","alli","ford","play","mont","anta","mine","qazwsx","ache","stra","erry","michael","dima","green","sher","nick","shar","wolf","ring","killer","suck","tina","robert","01196","even","elin","aris","2211","dark","bird","jordan","paul","1108","scar","ones","lock","123321","0909","arri","mustang","rose","shit","asta","money","121212","0505","arch","03196","football","stro","hill","01019","letmein","dman","chin","10219","04196","05196","amil","pant","baseball","porn","david","james","onic","eron","10419","mini","stal","ison","abc123","lover","ander","alen","30319","t123","erin","ina1","vers","0303","ings","martin","mega","olly","ante","hello","11119","0108","90519","00119","08196","21219","shka","10196","hunter","30119","40419","00319","30219","02196","yboy","666666","10619","1102","vlad","70719","pers","1211","nova","12196","10919","anni","sara","lian","010119","07196","30419","0707","elli","oker","50219","er123","atch","00519","00419","rest","06196","50319","side","na19","60619","1107","50419","1210","00619","50819","80319","11196","90919","1109","tran","arma","anton","30519","50719","andrew","l123","09196","50119","31019","enny","0808","40219","90619","01119","80219","34567890","fuckyou","70219","00719","40519","anch","sweet","30719","80519","51219","40619","80419","soccer","21119","2108","00819","70419","60319","1204","60519","80819","1205","1002","elly","race","00919","7777777","60219","stic","steve","40319","70519","west","41019","90419","30619","thomas","01219","51019","boob","tche","30819","less","assa","60719","allo","ital","poli","light","50919","lion","30919","50619","90319","70319","2109","80119","ment","70919","70119","60419","60119","40719","40819","81219","80719","0404","70819","1208","0112","31219","0107","asti","90119","harley","each","70619","40119","51119","0304","80619","90719","bone","well","41219","0606","80919","71019","10101","1206","phil","0105","brand","1209","61219","1202","90819","1105","696969","71119","lick","ista","11111111","91019","lisa","more","0110","1005","123qwe","91219","1106","alis","60819","0106","60919","1000","41119","stre","arry","1207","llin","1007","charlie","enko","40919","1203","1004","k123","1110","31119","71219","long","61019","buster","apple","1003","wing","91119","ivan","1123","reat","1103","81019","61119","tori","0506","batman","stri","2212","anov","sion","2107","leon","1104","81119","isha","2102","a197","power","summer","superman","anya","qwertyui","sing","3108","pepper","1312","2311","george","ence","nker","lore","2110","tech","alan","3112","87654321","1006","card","2106","1008","part","ryan","ross","123a","liver","amin","gran","1402","cock","aron","william","ssie","gene","2512","2301","01200","elan","ipper","ding","para","rish","maria","nson","dave","frank","sasha","1311","2103","moon","rill","buck","tigger","amel","mara","hand","2105","1812","ollo","2309","roni","kate","1512","happy","2525","2505","0405","1301","21985","redd","2202","arth","terr","iloveyou","hockey","2310","mper","2501","2210","3012","per1","2206","adam","3107","abri","tron","emen","0123","olli","11991","isto","game","cent","1009","3110","2305","achi","arta","emin","21990","1310","ladi","hawk","gfhjkm","moni","21989","gate","ines","ing1","lone","llen","ania","elis","mary","alina","2412","ardo","tall","itte","crea","mani","2204","indi","dogg","1478","shel","0502","0305","tree","ning","ation","peter","real","scott","miss","ucki","sant","slav","liza","erna","3010","olle","2510","oria","enne","meli","asca","0308","0708","chie","access","1510","reds","bass","justin","esse","sche","1305","0508","roll","1412","jxrf","2511","sman","2104","1504","0905","niko","hammer","arre","ender","2303","erto","0507","hall","1410","2207","2410","1502","1501","svet","sama","2203","1303","ingo","bitch","1308","2205","1503","esta","0501","1511","98765432","1404","222222","112233","2503","ress","m123","2504","0212","pres","2304","f123","ming","lucky","lass","fuckme","jessica","1307","1306","lash","1302","0211","an19","tlan","jennifer","1405","link","acker","2306","0306","ener","harr","0301","0503","0302","marl","1235","0509","0809","wild","1612","21984","lori","1411","2411","cola","ger1","andrea","1221","21992","0310","avis","0803","snow","came","3003","1507","illo","mist","sandr","cand","rate","1711","silver","hant","1508","daddy","3001","franc","unny","90219","taylor","1304","2401","ashi","3004","freedom","1704","3105","dead","2208","2509","0607","amanda","0307","joshua","11984","1805","arie","asse","1403","trin","2209","1705","yman","rett","kell","jeff","0609","inst","2502","stas","matthew","lanc","0608","2507","alia","1605","0406","alie","2404","tana","bble","ngle","21991","1801","2307","face","stone","1611","1309","1408","2606","hone","1401","mash","anas","mann","aren","wertyuio","son1","2508","8888888","00219","3006","0504","nicole","1712","1213","1707","poop","1407","asper","3103","dallas","erri","dream","denis","teri","2805","mina","ader","diamond","ride","eral","asshole","0912","ashley","team","cheese","bobb","2506","1406","1710","11983","thunder","ister","hero","roman","er19","2405","chen","3005","21983","n200","ginger","serge","0908","2707","kiss","1811","1604","2406","smoke","0309","lord","maggie","trustno1","2611","1509","mila","wall","2601","s200","pack","1802","arme","trac","1703","2909","0311","44444","orne","2812","1606","arne","i123","dude","2711","cookie","1702","2308","kara","0512","sere","1706","sunshine","holl","tell","1601","2403","101198","1803","ertyuiop","wind","2801","1610","2802","1603","2701","ers1","anny","2612","21982","ound","radi","1506","nman","0407","arro","0408","0510","stat","mail","11992","1804","0807","2808","1602","1810","east","2703","2811","nika","enda","astr","barb","victor","osto","abel","2710","2905","ember","0709","1806","ckle","0711","1409","2901","0312","1808","ker1","2605","rena","arke","olga","n199","colo","0410","ckie","rach","2904","2603","0403","dina","2704","2803","alon","corn","2712","ally","papa","0906","anthony","otte","icks","rona","0704","2804","audi","2810","0702","2602","iner","cart","2604","11982","reak","2702","russ","bron","tain","0605","0910","hbyf","1709","pimp","bond","03200","ristin","1608","0602","devil","2903","shot","phan","08200","etro","2610","05200","1230","lant","2402","house","aran","ana1","enter","mali","slan","2408","2407","01195","erse","ardi","159753","gust","cali","kova","azer","e200","1222","chil","andra","2705","0610","chelsea","princess","0902","1809","ermi","2607","ango","oose","0710","3007","hack","atan","0402","11980","0511","04200","adri","0401","on12","nokia","lady","0805","onde","0601","0412","z123","essa","0603","0810","plan","0411","michelle","maks","inde","2906","blow","nasty","0701","computer","aine","mira","ucks","core","2912","qwerty1","2409","1708","lson","aint","0812","0911","2709","1609","toni","iron","eave","1088","ture","oner","some","0705","tere","onta","skin","vent","3009","fast","merlin","4123","1807","0706","0802","0901","1607","2910","0806","0904","11981","atur","02200","09200","2911","tten","elena","0612","white","manu","zxcvbnm","yankees","0604","blin","ammy","2907","samm","0001","nica","acha","2609","starwars","oleg","1018","2807","0801","alls","water","12200","guitar","boom","tara","0409","0611","0804","mate","2809","nell","rton","boot","ffff","vill","2708","bles","maxim","ster1","3008","eeee","0907","flor","riel","rebe","maha","lton","2468","berg","0712","2806","chicken","tony","jackson","tick","cham","igma","avel","anut","ales","lane","ichi","2608","nche","welcome","0903","2706","ckers","lari","onne","inka","apri","kari","dann","07200","adis","10200","call","pion","london","pink","ddie","0703","erson","sport","eren","peac","1qaz2wsx","11200","1029","03195","beer","lala","sssss","metal","opper","ydog","brown","carol","buff","r200","amor","ennis","cros","brad","2424","init","anes","frog","esto","06200","igor","fant","21993","12011","13579","ncc1701","cast","eddy","rush","n198","rris","stel","05195","kins","11993","enta","0000000","magic","kman","vert","10195","2908","4789","ease","tera","arsenal","0811","them","erre","rter","1100","21980","5150","rome","6123","sham","1194","lman","bigdog","brian","uffy","jake","greg","poll","moto","aser","21981","rando","rash","8963","ooke","sparky","oger","jason","wwww","golfer","jane","arat","eagles","rado","ping","scooter","assword1","medi","lera","poke","nett","arge","sten","high","cont","ddog","user","ambo","anim","phoenix","3344","nity","mars","oren","ashe","octo","orma","work","stud","conn","2369","coll","der1","spider","7896","onte","y200","teen","elvi","sting","hanna","lips","rida","marina","yama","term","tigers","kenn","brit","10203","anad","ooper","08195","atte","bast","vika","billy","ferrari","ishi","kkkk","river","tttt","llar","lakers","rend","04195","11195","able","rita","trip","nice","ilan","barn","seve","usty","bbie","boss","dash","iris","itan","sana","cass","ka19","nina","feli","soni","anil","ussi","aram","ampi","ablo","olla","ton1","toma","gman","rama","02195","spri","isco","rack","mers","admi","lade","olan","333333","inal","tani","1089","1078","lana","temp","lly1","unner","09195","adin","12195","9090","rent","man2","honda","tany","na12","131313","4545","jami","nake","r1234","ples","acki","vova","back","ghbdtn","g123","hema","estr","onald","stia","5252","book","cccc","dale","secret","1515","anis","mana","anal","rell","rion","1415","corvette","emil","madd","tink","icky","h123","103198","tine","surf","ssan","bang","speed","1128","onnie","bubba","23232","best","iant","lter","hhhh","nathan","gent","gina","vera","eart","riss","apol","marine","llis","ager","9999999","spec","renc","q1w2e3r4","lley","llll","07195","arad","mous","iann","rola","iter","aper","fylh","slayer","anet","erpo","trav","carlo","rrrr","orange","lent","herm","spir","cana","1232","kola","adim","01010","alexand","1414","ass1","alic","mish","a196","mily","drum","ter2","smith","11979","tits","asia","acka","21994","dger","r199","moll","ores","egor","ishe","x123","tyle","rangers","osta","alpha","haha","jesus","wer1","herr","nders","020219","clar","buddy","olas","tian","lovem","vfvf","rney","ley1","mans","oopy","rami","orth","lice","ttie","mero","babe","o200","carr","barr","lder","brook","klas","nikita","acer","anic","2334","21978","open","er20","er11","ina2","cowboys","mano","an123","read","anit","bara","rsch","iber","ties","gian","field","obby","q123","outh","ilia","anci","anga","na20","32323","down","ravi","ktor","llan","ine1","bren","112198","amat","21979","beat","3141","ndia","11978","solo","road","alma","amma","steph","internet","nich","bbbbb","nite","vita","arde","form","rans","ndro","austin","enna","mall","bloo","ants","107198","endo","1087","valer","icia","mack","ommy","anana","erbo","simp","dent","arty","1191","mach","asha1","cris","appe","simon","nard","alker","lovel","arga","icker","06195","mela","music","teme","bigg","chik","ler1","bite","rocke","nkin","ver1","lica","domin","geni","105198","aska","izard","coco","banan","tomm","11994","tasha","gang","anka","pook","petr","101199","stya","oone","illie","inner","adma","icho","iman","donn","0100","5123","inky","etta","123654","gand","tewa","9632","slut","maverick","lama","amber","mala","ksan","mona","mino","ddddd","bart","8097","eres","lolo","qazxsw","arks","olina","scha","brie","8098","ugar","richard","here","ntan","hamp","ysta","marg","mmmmm","01020","crazy","oles","soft","wins","drey","ney1","pire","gera","3000","serv","eddi","mercedes","alte","1321","dust","020319","020419","spank","unda","1017","qweasd","erbe","yfcn","magn","shor","horse","aaaaaaa","bern","reme","lett","snoop","artem","egas","guar","plat","bandit","nsta","2580","rdon","s199","108198","dona","horny","asil","ordo","nny1","1472","hear","walk","abbi","otto","baba","8912","ickl","boog","inha","erica","ical","1028","10120","1098","kota","ican","dest","harm","raci","onco","rice","evel","789456","qwas","post","tard","atar","unch","aleks","arah","hers","whatever","amba","guin","ellow","mode","1q2w3e","doug","natas","ffin","8050","tele","winn","1593","202198","burn","a111","steelers","lvin","nada","veta","erti","nna1","madi","ulle","zzzzzz","ena1","duck","4242","indo","oron","matrix","fhby","11995","020819","9119","andal","hoot","eway","abcde","deli","chas","issi","pand","iden","orte","list","rost","laster","punk","nior","heri","polo","nand","kitty","butter","rini","cking","110198","yana","olive","start","linda","1090","pala","051987","21977","1717","chuc","rule","020519","nima","entr","ailey","ador","haro","turn","eder","atti","brea","koff","hans","vero","mati","julia","arce","izza","7891","fucker","011990","orri","erik","leas","mother","natali","thead","arco","rant","erta","b123","020119","gator","heel","ard1","grea","anat","mer1","vfrc","020619","olden","ick1","help","bbit","mera","akot","pool","erst","erni","8951","inch","lame","nchi","death","5555555","1058","kati","011987","aras","lexi","rrie","ierr","mili","dboy","ates","kristi","perf","case","bean","asto","randy","oris","iles","falcon","1516","5050","llio","nati","inni","91989","anki","rame","kevin","207198","a2010","lest","a123456","rega","friend","chevy","aval","andon","red1","verp","lava","omar","kiri","as12","cara","amir","olit","hani","annon","tive","okey","nther","1092","estin","ickey","204198","11977","unit","dance","031988","arba","trai","juan","d1234","rger","11975","1079","020719","dell","rabb","rmin","thor","rlan","jean","jone","scorpio","11976","p123","shal","erlo","nest","hele","5566","en12","want","ayne","est1","erem","issy","208198","ygir","burg","s1234","forever","ions","enka","flower","uren","sass","051990","ashk","theb","isse","scho","2119","camp","031987","201198","tima","0012","ophi","les1","rene","9874","late","oome","205198","chip","hica","ento","loves","2131","pace","21976","inke","ction","little","duke","206198","elic","onat","ancer","sala","doll","onik","eria","cord","eanu","chang","gord","kaka","diab","asdfghj","elia","1237","umpe","dies","alam","gala","fort","nine","11121","1118","rker","2128","071987","avan","soph","oshi","knight","bomb","arra","jimmy","1314","1285","mple","like","imbo","bigt","1324","dodge","rchi","fend","ikol","1129","ocky","r198","1022","lege","inat","llo1","bber","041988","rade","ebel","kass","robi","elec","hari","aldo","otti","stef","ssma","erda","luca","samu","leri","tati","ears","adel","frea","iano","ya19","offe","yell","ochka","geli","esha","15051","dmin","morgan","bella","onna","21995","8910","31991","ameri","annah","isla","truck","asmin","071986","020919","anthe","s198","compa","beth","041986","a777","121987","061986","raider","grac","atash","051988","stle","joke","041987","male","4455","driv","tita","051986","nato","amal","0010","3030","patrick","09876","jjjjj","charle","item","41984","edog","1290","121986","stop","demon","ious","lissa","cheste","5935","4725","chol","warr","atro","entin","umbe","ma19","22011","tata","asan","host","skip","on19","lipp","abra","nish","alib","erro","ench","mpir","1190","1077","10111","10121","dogs","lphin","nnet","ippy","berl","71990","llet","011988","junio","203198","41985","arit","71985","cons","ronc","craft","ongo","ingl","1086","ka12","iking","81990","ooooo","ergi","ritt","hester","10011","031986","cats","brav","011986","7258","2123","k199","lita","81985","011985","0990","johnny","terp","samsung","mang","city","71989","micke","huck","91986","etty","desi","aura","021019","oser","fall","key1","ssin","timo","joseph","viki","orgi","061987","world","anja","iabl","hjcn","mass","hank","5454","anky","comm","21975","051985","91988","81987","arsh","fami","q2w3e4r","051989","obra","twin","011989","gabr","rles","muff","elove","209198","61990","1127","071988","qqqqqq","imbe","erty12","baile","061988","ilip","rico","dward","rova","erde","ghjc","lect","eone","cky1","irina","0019","monster","9357","oster","lish","edwar","3698","shing","inho","idas","1245","01041","shak","1038","ppppp","girls","5656","45612","yste","5000","smar","amie","ners","raven","pean","meric","ulie","laure","look","n1234","210198","101987","2344","idge","ymrf","rpoo","31985","ffer","081988","viper","tton","thing","031990","choo","101986","41990","oodl","right","miller","31989","evan","onto","bian","eigh","manc","lace","lema","ggggg","heather","nnnn","tenn","orin","emar","ssio","hort","loui","camaro","squi","carm","31983","061985","8908","inga","2341","kath","7852","kbyf","stea","view","lldog","pson","ty123","ris1","ert1","1234q","eles","ouch","20011","hman","ova1","arik","dirt","1188","8904","name","ooby","christi","dria","ethe","plea","ra19","1080","boro","dako","pain","earl","rple","ocket","deep","livi","elon","01031","1068","61989","sabe","01021","tyrj","hark","ontr","rink","vfhb","amant","utch","in12","lean","01091","hara","nsto","rocks","e1234","20021","dolphi","asda","iell","anin","fghjk","icki","albert","rato","latin","bulldo","1082","505198","popo","ceman","eras","dog1","23021","mell","71983","mario","ber1","smile","rlos","hane","roke","1016","homer","ntai","xxxxxxx","winte","storm","lova","purpl","kare","41991","coob","091987","nita","count","021988","okin","2342","081989","diana","ione","ntha","pira","pear","dawg","beav","imal","obbi","aroli","71984","2333","081986","tdog","bigbo","rove","erba","blad","bett","usha","ndri"]}(Constants=exports.Constants||(exports.Constants={})); + +},{}],7:[function(require,module,exports){ +"use strict";exports.__esModule=!0;var Dictionaries,PasswordMeter=require("./PasswordMeter"),PasswordLeaks=require("../js/hibp-js");!function(e){var s,i,a=function(){function e(e){var s=PasswordMeter.PasswordMeter.instance.getHelper();e.blacklist.checkSubstrings?this.blacklistRejects=function(s){return this.blacklistBloom.substringExists(s,e.blacklist.checkSubstringLength)}:this.blacklistRejects=function(e){return this.blacklistDict[e]},this.blacklistDict=s.compressedFileToDict(e.blacklist.blacklistFile),this.blacklistBloom=s.compressedFileToBloomFilter(e.blacklist.blacklistFile,e.blacklist.checkSubstringLength),this.leaks=new PasswordLeaks.PasswordLeaks,this.passwordsDict=s.compressedFileToDict("dictionary-passwords-compressed.txt"),this.namesDict=s.compressedFileToDict("dictionary-names-compressed.txt"),this.phrasesDict=s.compressedFileToDict("dictionary-phrases-compressed.txt"),this.englishwordsDict=s.compressedFileToDict("dictionary-englishwords-compressed.txt"),this.wikipediaDict=s.compressedFileToDict("dictionary-wikipedia-compressed.txt"),this.petnames={};for(var i=["abbey","abby","alex","allie","amber","angel","annie","ashley","baby","bailey","bandit","barney","baxter","bear","beau","bella","belle","bentley","blackie","blue","bonnie","boomer","boots","bosco","brady","brandy","bruno","brutus","bubba","buddy","buffy","buster","cali","callie","calvin","casey","casper","cassie","champ","chance","charlie","chase","chelsea","chester","chico","chloe","cleo","cleopatra","clyde","coco","cocoa","cody","cookie","cooper","cosmo","daisy","dakota","dexter","diesel","dixie","duke","duncan","dusty","ella","ellie","elvis","emily","emma","felix","fiona","fluffy","frankie","fred","gabriel","garfield","george","gigi","ginger","gizmo","grace","gracie","guinness","haley","hannah","harley","harry","heidi","henry","holly","honey","hunter","isabella","isis","jack","jackson","jade","jake","jasmine","jasper","jessie","joey","junior","katie","kiki","kitty","kobe","lacey","lady","lexi","lexie","libby","lilly","lily","loki","lola","louie","lucky","lucy","luke","lulu","luna","maddie","madison","maggie","mandy","marley","maximus","maxwell","maya","merlin","mickey","midnight","mikey","millie","milo","mimi","minnie","misskitty","missy","misty","mittens","mocha","molly","moose","morgan","muffin","murphy","nala","nikki","oliver","olivia","oreo","oscar","otis","patches","peaches","peanut","pebbles","penny","pepper","phoebe","piper","precious","prince","princess","pumpkin","rascal","riley","rocco","rocky","romeo","roscoe","rosie","roxie","roxy","ruby","rudy","rufus","rusty","sabrina","sadie","samantha","sammy","sampson","samson","sandy","sarah","sasha","sassy","scooter","scout","sebastian","shadow","sheba","shelby","sierra","simba","simon","smokey","snoopy","snowball","socks","sonny","sophia","sophie","sparky","spencer","spike","stalla","stella","sugar","sunny","sydney","sylvester","tabitha","tasha","teddy","thomas","tiger","tigger","tinkerbell","toby","tommy","trixie","tucker","tyson","willie","willow","winston","xena","yoda","zeus","ziggy","zoey"],a=0;at)for(var h=l.length-t+1,p=0;p0&&r.push(e[s])}return{matched:o,revisedParts:r,score:n}},e.prototype.commonSubstitutions=function(e){var t=new RegExp("[^A-Za-z]"),o=new Array,r={candidate:e,offset:0,commonness:100};o.push(r);for(var n=0;n=1&&this.isALetter(e.charAt(n-1))||n>=2&&this.isALetter(e.charAt(n-2))||n=0;m--)o[m].candidate.match(t)&&o.splice(m,1);return o},e.prototype.sortedOverlap=function(e,t){for(var o=0;o=65&&t<=90||t>=97&&t<=122},e}();e.Helper=t,e.boldAll=function(e){return e.map(function(e){return""+e+""})}}(Helper=exports.Helper||(exports.Helper={})); + +},{"../js/bloom-filter-js":1}],9:[function(require,module,exports){ +"use strict";exports.__esModule=!0;var NeuralNetwork,PasswordMeter=require("./PasswordMeter"),Constants=require("./constants");!function(e){var t=!0,r={};function n(e){return Math.log(e)/Math.LN10}function s(e,r){e*=function(e){var t=1,r=e.substr(1);if(e.charAt(0)===e.charAt(0).toUpperCase()&&e.charAt(0)!==e.charAt(0).toLowerCase()&&r===r.toLowerCase())t=1.5;else if(-1==e.search(/[a-z]/)){var n=e.replace(Constants.Constants.UPPERCASE_LETTERS_GLOBAL,"");e.length>=n.length+3&&(t=2)}else e!==e.toLowerCase()&&(t=10);return t}(r),t=!1;var s=n(e);e<=1&&(s=n(1.1)),r.length>0&&e==Number.POSITIVE_INFINITY&&(s=100),isNaN(e)&&(s=-1),PasswordMeter.PasswordMeter.instance.getNN().setNeuralNetNum(r,s)}function o(e,t){s(e,t),PasswordMeter.PasswordMeter.instance.getUI().displayRating(t)}function a(e,t){s(e,t),PasswordMeter.PasswordMeter.instance.getUI().synthesizeFixed(t)}e.log10=n,e.nnFixedCallback=a;var u,i,N,c,l,w=function(){function e(e,t){this.nn=e,this.nnfixed=t}return e.prototype.heardFromNn=function(){return!t},e.prototype.setNeuralNetNum=function(e,t){r[e]=t},e.prototype.getNeuralNetNum=function(e){return r[e]},e.prototype.queryGuessNumber=function(e,t){t?this.nnfixed.query_guess_number(e):this.nn.query_guess_number(e)},e}();e.NeuralNetworkInterface=w,u=PasswordMeter.PasswordMeter.instance,i=u.getConfig().neuralNetworkConfig,N=new NeuralNetworkClient(a,i),c=new NeuralNetworkClient(o,i),l=new w(c,N),u.setNN(l)}(NeuralNetwork=exports.NeuralNetwork||(exports.NeuralNetwork={})); + +},{"./PasswordMeter":3,"./constants":6}],10:[function(require,module,exports){ +"use strict";exports.__esModule=!0;var RuleFunctions,PasswordMeter=require("./PasswordMeter"),Helper=require("./helper"),Constants=require("./constants"),NeuralNetwork=require("./nn-misc");!function(e){e.verifyMinimumRequirements=function(e,t){var s=PasswordMeter.PasswordMeter.instance,r=s.getConfig(),a=s.getDictionaries(),n=r.colors.compliant,o=r.colors.noncompliant,i=r.symbols.compliant,l=r.symbols.noncompliant,c={},h={};if(r.length.active){var u=r.length.minLength,g=r.length.maxLength,d=!1,p="";p=g>0?"Contain "+u.toString()+"-"+g.toString()+" characters":"Contain "+u.toString()+"+ characters",e.length>=u&&(e.length<=g||0===g)&&(d=!0),p=d?""+i+p:""+l+p,p+="",c.length=p,h.length=d}var m=!1,f=!1,w=!1,b=!1,v=0;if(e.match(Constants.Constants.LOWERCASE_LETTERS_GLOBAL)&&(v++,m=!0),e.match(Constants.Constants.UPPERCASE_LETTERS_GLOBAL)&&(v++,f=!0),e.match(Constants.Constants.DIGITS_GLOBAL)&&(v++,w=!0),e.match(Constants.Constants.SYMBOLS_GLOBAL)&&(v++,b=!0),r.classCount.active){var y=r.classCount.minCount,C=r.classCount.maxCount;p="",d=!1,p=4===C?"Use "+y.toString()+"+ of the following: ":"Use "+y.toString()+"-"+C.toString()+" of the following: ",p+="uppercase letters; lowercase letters; digits; symbols",v>=y&&v<=C&&(d=!0),p=d?""+i+p:""+l+p,p=p+="",c.classCount=p,h.classCount=d}if(r.classRequire.active){var A=r.classRequire.upperCase,x=r.classRequire.lowerCase,M=r.classRequire.digits,T=r.classRequire.symbols;p="",d=!1,x&&(p.length>0?p+=" and a lowercase letter":p="Contain a lowercase letter"),A&&(p.length>0?p+=" and an uppercase letter":p="Contain an uppercase letter"),M&&(p.length>0?p+=" and a digit":p="Contain a digit"),T&&(p.length>0?p+=" and a symbol":p="Contain a symbol"),x&&!m||A&&!f||M&&!w||T&&!b||(d=!0),p=d?""+i+p:""+l+p,p=p+="",c.classRequire=p,h.classRequire=d}if(r.classAllow.active){var k=r.classAllow.upperCase,S=r.classAllow.lowerCase,L=r.classAllow.digits,E=r.classAllow.symbols;if(p="",d=!1,S||(p.length>0?p+=" or lowercase letters":p="Not include lowercase letters"),k||(p.length>0?p+=" or uppercase letters":p="Not include uppercase letters"),L||(p.length>0?p+=" or digits":p="Not include digits"),E||(p.length>0?p+=" or symbols":p="Not include symbols"),!S&&m||!k&&f||!L&&w||!E&&b||(d=!0),d)p=""+i+p;else{var P=[];!S&&m&&(P=P.concat(e.match(Constants.Constants.LOWERCASE_LETTERS))),!k&&f&&(P=P.concat(e.match(Constants.Constants.UPPERCASE_LETTERS))),!L&&w&&(P=P.concat(e.match(Constants.Constants.DIGITS))),!E&&b&&(P=P.concat(e.match(Constants.Constants.SYMBOLS)));var R=(P=P.removeDuplicates()).indexOf(" ");R>-1&&(P[R]="[space]"),p=""+l+(p+=" (You used "+P.join(", ")+")")}p=p+="",c.classAllow=p,h.classAllow=d}if(r.blacklist.active){p="",d=!1,p="Not be an extremely common password";var H=!1;if(e.length>0){var N=e;r.blacklist.stripDigitsSymbolsFromPassword&&(N=N.replace(/[^a-zA-Z]/gi,"")),r.blacklist.caseSensitive||(N=N.toLowerCase()),H=a.blacklistRejects(N)}(d=!H||0===e.length||-1!=r.blacklist.lengthException&&e.length>=r.blacklist.lengthException)||(p=""+l+p+""),d||(c.blacklist=p),h.blacklist=d}if(r.forbidChars.active){var D=r.forbidChars.list;p="",d=!1,p="Not include the following characters: "+W;for(var O=e.removeDuplicateChars(),W="",z=0;zConstants.Constants.endASCII||D.indexOf(O.charAt(z))>=0)&&(W+=O.charAt(z));0===W.length&&(d=!0),d||(p=""+l+p+""),d||(c.forbidChars=p),h.forbidChars=d}if(r.repeatChars.active){var q=r.repeatChars.limit;p="",d=!1,p="Not repeat the same character "+q.toString()+"+ times in a row";for(var I=[],_=q-1;_"+i+p:""+l+(p+=" ("+I.removeDuplicates().join(", ")+")"),p+="",c.repeatChars=p,h.repeatChars=d}if(r.usernameDifference.active){var G=r.usernameDifference.limit;p="",d=!1,p="Not base your password around your username";for(var B=e.toLowerCase(),U=t.toLowerCase();U.length>0&&B.indexOf(U)>-1;)B=B.substr(0,B.indexOf(U))+B.substr(B.indexOf(U)+U.length);(0==U.length||0==e.length||B.length>=G)&&(d=!0),d||(p=""+l+p+""),d||(c.usernameDifference=p),h.usernameDifference=d}if(r.minLogNnGuessNum.active){d=!1,p="";var Z=r.minLogNnGuessNum.threshold,Y=PasswordMeter.PasswordMeter.instance.getNN().getNeuralNetNum(e),$=Y+NeuralNetwork.NeuralNetwork.log10(r.neuralNetworkConfig.scaleFactor);Y<0?console.log("looking up NN guess number: "+e):Y>Z?(d=!0,console.log("high enough NN guess number: "+e+" ("+Y+" > "+Z+") [unconservative NN guess number: "+$+"]")):(console.log("too low NN guess number: "+e+" ("+Y+" < "+Z+") [unconservative NN guess number: "+$+"]"),p=""+l+r.minLogNnGuessNum.rejectionFeedback),d||(c.minLogNnGuessNum=p),h.minLogNnGuessNum=d}if(r.sameChars.active){var F=r.sameChars.limit;p="",d=!1,e.length>=r.sameChars.lengthException||function(e,t){for(var s={},r=0;rt)return!1}else s[a]=1}return!0}(e,F)?d=!0:p="Not contain the same character more than "+F.toString()+"+ times",d||(p=""+l+p+"",c.sameChars=p),h.sameChars=d}r.prohibitKnownLeaked.active&&(d=!1,p="",e.length"+l+"Not use a password found in previous security leaks",c.prohibitKnownLeaked=p),h.prohibitKnownLeaked=d);var K=!0;for(var J in h)if(!(K=K&&h[J]))break;return{compliant:K,detail:{compliance:h,explanation:c}}},e.pwLength=function(e){var t=e.length,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().length.maxLength;return t<16&&(0===n||t=65&&e.charCodeAt(i)<=90&&t++;if(t<.15*e.length&&o){s="Consider using more uppercase letters",r="Consider using ",r+=(t+1).toString()+" or more uppercase letters",a="Uppercase letters are surprisingly uncommon in passwords, which makes them hard to guess";var l=65+Math.floor(26*Math.random()),c=Math.floor(1+Math.random()*(e.length-1));n=e.slice(0,c)+String.fromCharCode(l)+e.slice(c)}return{count:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:n}},e.countLC=function(e){for(var t=0,s="",r="",a="",n="",o=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.lowerCase,i=0;i=97&&e.charCodeAt(i)<=122&&t++;if(t<.15*e.length&&o){a="Having variety in the types of characters you use makes your password harder to guess",s="Consider using more lowercase letters",r="Consider using ",r+=t+1+" or more lowercase letters";var l=97+Math.floor(26*Math.random()),c=Math.floor(1+Math.random()*(e.length-1));n=e.slice(0,c)+String.fromCharCode(l)+e.slice(c)}return{count:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:n}},e.countDIGS=function(e){for(var t=0,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.digits,o=0;o=48&&e.charCodeAt(o)<=57&&t++;return t<.15*e.length&&n&&(s="Consider using more digits",a="Most passwords contain no digits or digits in predictable places; doing otherwise makes your password harder to guess",r="Consider using ",r+=t+1+" or more digits"),{count:t,reasonWhy:a,publicText:s,sensitiveText:r}},e.countSYMS=function(e){var t=e.replace(/[A-Za-z0-9]/g,"").length,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.symbols;return t<.15*e.length&&n&&(s="Consider using more symbols",a="Few passwords contain symbols, which makes passwords with symbols harder to guess",r="Consider using ",r+=t+1+" or more symbols"),{count:t,reasonWhy:a,publicText:s,sensitiveText:r}},e.characterClasses=function(e){var t=0;e.match(Constants.Constants.LOWERCASE_LETTERS)&&t++,e.match(Constants.Constants.UPPERCASE_LETTERS)&&t++,e.match(Constants.Constants.DIGITS)&&t++,e.match(Constants.Constants.SYMBOLS)&&t++;var s=t,r="",a="",n="",o=PasswordMeter.PasswordMeter.instance.getConfig().classAllow;if(e.match(Constants.Constants.UPPERCASE_LETTERS)||e.match(Constants.Constants.DIGITS)||e.match(Constants.Constants.SYMBOLS))if(e.match(Constants.Constants.DIGITS)||e.match(Constants.Constants.SYMBOLS))e.match(Constants.Constants.UPPERCASE_LETTERS)||e.match(Constants.Constants.SYMBOLS)?e.match(Constants.Constants.SYMBOLS)||o.symbols&&(r="Add symbols in unpredictable locations",a="Add symbols in unpredictable locations",n="Because only 1% of passwords use symbols, adding them unpredictably strengthens your password"):(i=[],l="",o.symbols&&i.push("symbols"),o.upperCase&&i.push("uppercase letters"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="42% of passwords contain only lowercase letters and number, making them easy for attackers to guess");else{var i=[],l="";o.symbols&&i.push("symbols"),o.digits&&i.push("digits"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="42% of passwords contain only letters, making them easy for attackers to guess"}else{var i=[],l="";o.symbols&&i.push("symbols"),o.digits&&i.push("digits"),o.upperCase&&i.push("uppercase letters"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="38% of passwords contain only lowercase letters, making them easy for attackers to guess"}return{count:s,reasonWhy:n,publicText:r,sensitiveText:a}},e.uppercasePredictable=function(e){var t=0,s="",r="",a="",n="",o="";if(e.charAt(0)===e.charAt(0).toUpperCase()&&e.charAt(0)!==e.charAt(0).toLowerCase()){var i=e.substr(1);if(i===i.toLowerCase()){t=1,s="Capitalize a letter in the middle",r="Capitalize a letter in the middle, rather than the first character",n=e.charAt(0).escapeHTML(),a="30% of people also capitalize only the first character";for(var l=new Array,c=0;c=97&&e.charCodeAt(c)<=122&&l.push(c);var h=Math.floor(Math.random()*l.length);o=e.substring(0,l[h]),o+=e.charAt(l[h]).toUpperCase(),o+=e.substring(l[h]+1)}}if(-1==e.search(/[a-z]/)){var u=e.replace(/[A-Z]/g,"");if(e.length>=u.length+3){t=1,s="Mix up your capitalization",r="Mix up your capitalization, rather than capitalizing everything",a="21% of passwords also contain only uppercase letters";var g=new Array;for(c=0;c=65&&e.charCodeAt(c)<=90&&g.push(c);var d=Math.floor(Math.random()*g.length);o=e.substring(0,g[d]),o+=e.charAt(g[d]).toLowerCase(),o+=e.substring(g[d]+1)}}return{score:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:o,problemText:n}},e.digitsPredictable=function(e){var t=0,s="",r="",a="",n="",o="",i=[],l=new RegExp("[^0-9]"),c=new RegExp("^[0-9]+[^0-9]+$"),h=new RegExp("^[^0-9]+[0-9]+$");if(e.length>=4&&!e.match(l)){t=1,s="Add more letters and symbols to your password",r="Add characters other than digits to your password",a=e.escapeHTML(),n="35% of people also use only digits";var u=58+Math.floor(68*Math.random()),g=Math.floor(1+Math.random()*(e.length-1));o=e.slice(0,g)+String.fromCharCode(u)+e.slice(g);for(var d=0;d=4&&e.match(c)){t=1,r="Consider inserting digits into the middle, not just at the beginning",s="Consider inserting digits into the middle",n="10% of people also put digits at the beginning of the password";for(var p=1;e.charCodeAt(p)>=48&&e.charCodeAt(p)<=57;)p++;for(a=e.slice(0,p).escapeHTML(),g=Math.floor(p+1+Math.random()*(e.length-p-1)),o=e.slice(p,g)+e.slice(0,p)+e.slice(g),d=0;d=4&&e.match(h)){t=1,r="Consider inserting digits into the middle, not just at the end",s="Consider inserting digits into the middle",n="38% of people also put digits at the end of the password";for(var m=e.length-2;e.charCodeAt(m)>=48&&e.charCodeAt(m)<=57;)m--;for(a=e.slice(m+1).escapeHTML(),g=Math.floor(1+Math.random()*(e.length-m-1)),o=e.slice(0,g)+e.slice(m+1)+e.slice(g,m+1),d=0;d=4&&e.match(l)){t=1,r="Move symbols and digits earlier, rather than just at the end",s="Move symbols and digits elsewhere in your password",a=e.match(h)[0].escapeHTML(),n="14% of people also use letters, followed by symbols, followed by digits";var u=e.search(h);a=e.slice(u).escapeHTML();var g=Math.floor(1+Math.random()*(u-1));o=e.slice(0,g)+e.slice(u)+e.slice(g,u);for(var d=0;d=4&&e.match(c)){for(t=1,r="Move your symbols earlier, rather than just at the end",s="Move symbols and digits elsewhere in your password",n="16% of people also put symbols only at the end of the password",u=e.search(h),a=e.slice(u).escapeHTML(),g=Math.floor(1+Math.random()*(u-1)),o=e.slice(0,g)+e.slice(u)+e.slice(g,u),d=0;d":[3,9],"/":[3,10],"?":[3,10]," ":[4,5]},s="",r=0;rl&&"0,0"!==h&&(i=c,l=r-c),c=r)}var u=l+1,g="",d="",p="",m="";return u>=4&&(g="Avoid using a pattern on your keyboard",d="Avoid using a pattern on your keyboard like "+(p=s.substring(i,i+l+1).escapeHTML())+"",m="Because keyboard patterns are very common in passwords, attackers know to guess them"),u<3&&(u=0),{score:u,reasonWhy:m,publicText:g,sensitiveText:d,problemText:p}},e.duplicatedCharacters=function(e){var t=e.split("").removeDuplicates(),s=e.length-t.length,r="",a="",n="",o="";if(t.length<=.5*e.length&&t.length<=5){o="",r="Have more variety in the characters you choose";var i="";t.length>1&&(i="s"),a="Have more variety than repeating the same "+t.length+" character"+i+" ("+Helper.Helper.boldAll(t.sort()).toHumanString()+")",n="Passwords that use only a few different characters are easy for attackers to guess"}return{count:s,reasonWhy:n,publicText:r,sensitiveText:a,problemText:o}},e.repeatedSections=function(e){for(var t=0,s="",r="",a="",n="",o=!1,i=(e=e.toLowerCase()).length,l=Math.floor(i/2);l>=3;l--){for(var c=0;c<=i-l;c++){for(var h=e.substring(c,c+l),u=h.split("").reverse().join(""),g=0;g+l<=c;g++)e.substring(g,g+l)===h?(t+=l,a=h.escapeHTML()):e.substring(g,g+l)===u&&(t+=l,a=h.escapeHTML(),o=!0);for(g=c+l;g+l<=i;g++)e.substring(g,g+l)===h?(t+=l,a=h.escapeHTML()):e.substring(g,g+l)===u&&(t+=l,a=h.escapeHTML(),o=!0);if(t>=3){t>=4?(s="Avoid repeating sections",r="Avoid repeating sections ("+a+")",n="In their guessing, attackers know to try duplicating parts of the password",o&&(s+=", forwards or backwards",r+=", forwards or backwards")):a="";break}}if(t>0)break}return{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.repeats=function(e){for(var t=e.length,s=1,r=1,a="",n="",o="",i="",l="",c=1;cs&&(s=r,a=e[c]):r=1;var h=s;if(s>=3){n="Don't repeat the same character many times in a row";for(var u=0;u"+(i=i.escapeHTML())+") many times in a row",l="Hitting the same key over and over adds little to your password's strength"}return 1===h&&(h=0),{count:h,reasonWhy:l,publicText:n,sensitiveText:o,problemText:i}},e.contextual=function(e,t){for(var s=0,r="",a="",n="",o="",i=e,l=0;l=5){s=u.length,r="Don't use your account information in your password",a="Don't use your account information ("+(n=u.escapeHTML())+") in your password",o="Attackers know to guess your username and email address as part of your password";var g=e.indexOf(u);g>-1&&(i=e.substr(0,g)+e.substr(g+u.length))}return{count:s,reasonWhy:o,publicText:r,sensitiveText:a,problemText:n,remaining:i}},e.commonSubstringCheck=function(e){var t=0,s="",r="",a="",n="",o=new Array;e=e.toLowerCase();for(var i=Constants.Constants.blacklistedSubstrings,l=0;l0){s="Avoid strings of characters commonly found in passwords",r="Avoid strings of characters commonly found in passwords like "+o.join(" and ")+"",n="Even if they don't make sense, these strings of characters show up in many passwords, which makes them bad to use in yours.",a=o[0].escapeHTML();for(var c=0;c as part of your own password",n=e[r].escapeHTML();return{length:e[r].length,reasonWhy:s,publicText:"Avoid using very common passwords as part of your own password",sensitiveText:a,problemText:n}}return{length:0,reasonWhy:s,publicText:"",sensitiveText:"",problemText:""}},e.blacklist=function(e){for(var t=PasswordMeter.PasswordMeter.instance.getConfig(),s=PasswordMeter.PasswordMeter.instance.getHelper(),r=t.ignoredWords,a="",n="",o="",i="",l=e,c=[],h=new RegExp("[^A-Za-z]"),u=(e=(e=e.toLowerCase()).replace(/[-_ ]/g,"")).split(/[^a-z01345@$]+/),g=(u=u.filter(function(e){return e})).listSubstringsMinMax(1,void 0),d=0;d-1&&(c.push(g[d]),p=g[d])}if(p.length>0){for(0==o.length&&(o=g[d].escapeHTML()),f=0;f-1){u.splice(f,1,u[f].substring(0,b),u[f].substring(b+p.length)),u=u.filter(function(e){return e});break}}g=u.listSubstringsMinMax(1,p.length),p="",d=0}else d++}var v=0;if(c.length>0){for(a="Don't use site-specific terms in your password",d=0;d-1&&(l=l.substr(0,y)+l.substr(y+c[d].length))}n="Don't use site-specific terms ("+Helper.Helper.boldAll(c.removeDuplicates()).toHumanString()+")",i="Attackers target their attacks to words used on a particular service"}return{length:v,reasonWhy:i,publicText:a,sensitiveText:n,problemText:o,remaining:l}},e.combinedDictCheck=function(e){for(var t="",s="",r="",a="",n=100,o=new Array,i=new Array,l=new Array,c=new Array,h=new Array,u=PasswordMeter.PasswordMeter.instance,g=u.getDictionaries(),d=u.getHelper(),p=new Array,m=new Array,f=(e=e.replace(/[-_ ]/g,"")).split(/[^A-Za-z012345!&@$]+/),w=(f=f.filter(function(e){return e})).listSubstringsMinMax(4,void 0),b=0;b0){for(0==r.length&&(r=w[b].escapeHTML()),A=0;A-1){f.splice(A,1,f[A].substring(0,T),f[A].substring(T+v.length)),f=f.filter(function(e){return e});break}}w=f.listSubstringsMinMax(4,v.length),v="",b=0}else b++}var k=new Array,S=new Array,L=0,E=0,P=function(e,t){if(e.length>0){k.push(t);for(var s=0;s0&&(a="Attackers use software that automatically guesses millions of words commonly found in dictionaries, wordlists, or other people's passwords",t="Don't use ",s="Don't use ",n<100&&(a+=", including simple transformations of those words/phrases where they substitute digits and symbols for letters"),t+=k.join(" or "),s+=S.join(" or ")),{length:L,reasonWhy:a,publicText:t,sensitiveText:s,problemText:r,dictionaryTokens:E,substitutionCommonness:n=100-n}},e.identifyDates=function(e){var t=0,s="",r="",a="",n="",o=[],i=PasswordMeter.PasswordMeter.instance.getHelper(),l=[e],c=function(e){var s=i.matchHelper(l,e);s.score>0&&(t+=s.score,o=o.concat(s.matched.toString()),l=s.revisedParts)},h="([ .-/])",u="((0\\d|1[012])|\\d)",g="(january|february|march|april|may|june|july|august|september|october|november|december)",d="([012]\\d|3[01])",p="(\\d\\d)",m="(19\\d\\d|20[01234]\\d)";return c(new RegExp(u+h+d+h+m,"g")),c(new RegExp(d+h+u+h+m,"g")),c(new RegExp(u+h+d+h+p,"g")),c(new RegExp(d+h+u+h+p,"g")),c(new RegExp(u+d+m,"g")),c(new RegExp(d+u+m,"g")),c(new RegExp(g+m,"ig")),c(new RegExp(g+p,"ig")),c(new RegExp(u+h+d,"g")),c(new RegExp(d+h+u,"g")),c(new RegExp(m,"g")),t>0&&(s="Avoid using dates",r="Avoid using dates like "+Helper.Helper.boldAll(o).toHumanString(),n="Dates and years in any format are quite common in passwords",a=o[0].escapeHTML()),{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.alphabeticSequenceCheck=function(e){var t=0,s="",r="",a="",n="",o=[],i=[];o[0]=e.charCodeAt(0);for(var l=1;lh&&0!==g&&(c=u,h=l-u),u=l),1===(t=h)&&(t=0),t>=2&&t++,t>=4){var d=e.substr(c,c+h+1);a=d.escapeHTML();var p=new RegExp("^[0-9]+$");d.match(p)?(s="Avoid numerical patterns",r="Avoid numerical patterns like "+a+""):(s="Avoid patterns from the alphabet",r="Avoid patterns from the alphabet like "+a+""),n="Attackers know to guess sequences following the alphabet, in addition to repeated characters or patterns on your keyboard"}}return{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.structurePredictable=function(e){var t="",s="",r="",a=0,n=(e=(e=(e=(e=e.replace(/[A-Z]/g,"U")).replace(/[a-z]/g,"L")).replace(/[0-9]/g,"D")).replace(/[^A-Za-z0-9]/g,"S"),Constants.Constants.commonStructures.indexOf(e));if(n>=0){a=2124-n,r="One technique attackers use is to try all possible passwords within common structures, or arrangements of character classes (e.g., where lowercase letters and digits are located)",s=(t="The way you structure your password is predictable")+" (";for(var o=!0,i=0;i1&&(s+="s"),i+=l}s+=")"}return{score:a,reasonWhy:r,publicText:t,sensitiveText:s}}}(RuleFunctions=exports.RuleFunctions||(exports.RuleFunctions={})); + +},{"./PasswordMeter":3,"./constants":6,"./helper":8,"./nn-misc":9}],11:[function(require,module,exports){ +String.prototype.replaceAt=function(r,t){return this.substr(0,r)+t+this.substr(r+1)},String.prototype.listSubstringsNoFilter=function(r){for(var t=new Array,e=this.toLowerCase(),n=e.length,i=n;i>=r-1;i--)for(var o=0;i+o/g,">")},String.prototype.listSubstrings=function(r){for(var t,e=new Array,n=(t=(t=this.toLowerCase()).replace(/[^a-z]/g,"")).length,i=n;i>=r-1;i--)for(var o=0;i+o0?e*Constants.Constants.METER_STRINGENCY_SCALE_FACTOR:e},e.prototype.spawnRating=function(){var e="",t=PasswordMeter.PasswordMeter.instance.getNN();e=this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown?this.$("#pwboxModal").val():this.$("#pwbox").val();var s=this.$("#usernamebox").val(),i=0,o=t.getNeuralNetNum(e);void 0===o?(t.setNeuralNetNum(e,-1),t.queryGuessNumber(e,!1)):o>=0&&i++,void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!0):this.heuristicMapping[e]>=0&&i++,0!==e.length&&t.heardFromNn()&&2!==i||this.displayRating(e)},e.prototype.generateCandidateFixed=function(e,t,s){var i=[];if(void 0===this.deltaHighlighted[e])for(var o=0;o=65&&n.charCodeAt(r)<=90?(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)+32)),i[r]=1):n.charCodeAt(r)>=97&&n.charCodeAt(r)<=122&&(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)-32)),i[r]=1)}else if(2===h||3===h){var l=32+Math.floor(95*Math.random()),p=Math.floor(n.length*Math.random());n.charCodeAt(p)!==l&&(i[p]=1),n=n.replaceAt(p,String.fromCharCode(l))}else if(h>=4){l=32+Math.floor(95*Math.random()),p=Math.floor((n.length+1)*Math.random());n=n.slice(0,p)+String.fromCharCode(l)+n.slice(p),i=i.slice(0,p).concat(1,i.slice(p))}var d=PasswordMeter.PasswordMeter.instance.getNN();void 0===d.getNeuralNetNum(n)&&(d.setNeuralNetNum(n,-1),d.queryGuessNumber(n,!0));var u=this.$("#usernamebox").val();return RuleFunctions.RuleFunctions.verifyMinimumRequirements(n,u).compliant?(this.recommendedFixes[s]=n,this.deltaHighlighted[n]=i,this.verboseMode&&console.log("identified "+n+" as a potential fix for "+s),void 0===this.recommendedFixesTries[s]?this.recommendedFixesTries[s]=1:this.recommendedFixesTries[s]=this.recommendedFixesTries[s]+1,this.spawnFixedRating(n)):++t<8&&this.generateCandidateFixed(e,t,s),1},e.prototype.spawnFixedRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=this.$("#usernamebox").val();void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!1):t.getNeuralNetNum(e)>=0&&this.heuristicMapping[e]>=0&&this.synthesizeFixed(e)},e.prototype.synthesizeFixed=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0,o=!1;void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(i++,s=this.heuristicMapping[e]);var n=t.getNeuralNetNum(e),h=this.nnNumtoScoreAsPercent(n);if(void 0!==n&&h>=0&&isFinite(h)&&(i++,(0===s||s>0&&h=67){for(var a in this.verboseMode&&console.log(e+" is a plausible fix above the 2/3rds threshold"),this.recommendedFixes)if(this.recommendedFixes[a]===e&&void 0===this.fixedpwMapping[a]){var r=0;void 0!==this.heuristicMapping[a]&&this.heuristicMapping[a]>=0&&(r=this.heuristicMapping[a]);var l=t.getNeuralNetNum(a),p=this.nnNumtoScoreAsPercent(l);void 0!==l&&p>=0&&isFinite(p)&&(0===r||r>0&&pr+15?(this.fixedpwMapping[a]=e,this.verboseMode&&console.log("mapping "+a+" to "+e),o=!0):this.verboseMode&&console.log("not mapping "+a+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s)}return o&&this.spawnRating(),1}var d=this.$("#pwbox").val();return this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown&&(d=this.$("#pwboxModal").val()),this.recommendedFixes[d]===e&&2===i&&void 0===this.fixedpwMapping[d]&&void 0!==this.recommendedFixesTries[d]&&this.recommendedFixesTries[d]<8&&(this.verboseMode&&console.log("trying again on "+e+" as current password is "+d),this.generateCandidateFixed(e,0,d)),1},e.prototype.redundant=function(e,t){e=e.toLowerCase();for(var s=0;s0&&e.length>0&&(t[s].indexOf(e)>=0&&e.length>=.7*t[s].length||e.indexOf(t[s])>=0&&t[s].length>=.7*e.length))return!0;return!1},e.prototype.queryHeuristicGuessNumber=function(e,t,s){var i=e,o=[],n=[],h=[],a=[],r=RuleFunctions.RuleFunctions.contextual(e,[t]);void 0===(e=r.remaining)&&(e="");var l=RuleFunctions.RuleFunctions.blacklist(e);void 0===(e=l.remaining)&&(e="");for(var p=RuleFunctions.RuleFunctions.pwLength(e),d=RuleFunctions.RuleFunctions.characterClasses(e),u=RuleFunctions.RuleFunctions.duplicatedCharacters(e),c=RuleFunctions.RuleFunctions.repeats(e),m=RuleFunctions.RuleFunctions.keyboardPatterns(e),g=RuleFunctions.RuleFunctions.repeatedSections(e),x=RuleFunctions.RuleFunctions.structurePredictable(e),b=RuleFunctions.RuleFunctions.uppercasePredictable(e),w=RuleFunctions.RuleFunctions.digitsPredictable(e),$=RuleFunctions.RuleFunctions.symbolsPredictable(e),v=RuleFunctions.RuleFunctions.countUC(e),M=RuleFunctions.RuleFunctions.countLC(e),y=RuleFunctions.RuleFunctions.countDIGS(e),f=RuleFunctions.RuleFunctions.countSYMS(e),T=RuleFunctions.RuleFunctions.identifyDates(e),R=(RuleFunctions.RuleFunctions.verifyMinimumRequirements(e,t),RuleFunctions.RuleFunctions.alphabeticSequenceCheck(e)),F=RuleFunctions.RuleFunctions.commonSubstringCheck(e),C=RuleFunctions.RuleFunctions.combinedDictCheck(e),N=e.listSubstringsNoFilter(4),k=RuleFunctions.RuleFunctions.commonPwCheck(N),W=[1.53,.3129,.9912,.04637,-.03885,-.1172,-.2976,-8581e-7,-.3008,-.5566,0,.9108,.7369,.7578,0,-.1213,-.2402,-.1364,-.5534,1.927,.001496,-.3946],P=[1,p.length,d.count,u.count,c.count,m.score,g.count,x.score,b.score,w.score,$.score,v.count,M.count,y.count,f.count,T.count,R.count,F.count,C.length,C.dictionaryTokens,C.substitutionCommonness,k.length],H=W[0],S=1;S100&&(H=100),r.publicText.length>0&&(o.push(r.publicText),n.push(r.sensitiveText),h.push(r.reasonWhy),a.push(r.problemText)),l.publicText.length>0&&(o.push(l.publicText),n.push(l.sensitiveText),h.push(l.reasonWhy),a.push(l.problemText)),C.publicText.length>0&&!this.redundant(C.problemText,a)&&(o.push(C.publicText),n.push(C.sensitiveText),h.push(C.reasonWhy),a.push(C.problemText)),m.publicText.length>0&&(o.push(m.publicText),n.push(m.sensitiveText),h.push(m.reasonWhy),a.push(m.problemText)),c.publicText.length>0&&(o.push(c.publicText),n.push(c.sensitiveText),h.push(c.reasonWhy),a.push(c.problemText)),T.publicText.length>0&&(o.push(T.publicText),n.push(T.sensitiveText),h.push(T.reasonWhy),a.push(T.problemText)),g.publicText.length>0&&(o.push(g.publicText),n.push(g.sensitiveText),h.push(g.reasonWhy),a.push(g.problemText)),R.publicText.length>0&&(o.push(R.publicText),n.push(R.sensitiveText),h.push(R.reasonWhy),a.push(R.problemText)),k.publicText.length>0&&!this.redundant(k.problemText,a)&&(o.push(k.publicText),n.push(k.sensitiveText),h.push(k.reasonWhy),a.push(k.problemText)),b.publicText.length>0&&(o.push(b.publicText),n.push(b.sensitiveText),h.push(b.reasonWhy),a.push(b.problemText)),w.publicText.length>0&&(o.push(w.publicText),n.push(w.sensitiveText),h.push(w.reasonWhy),a.push(w.problemText)),$.publicText.length>0&&(o.push($.publicText),n.push($.sensitiveText),h.push($.reasonWhy),a.push($.problemText)),u.publicText.length>0&&(o.push(u.publicText),n.push(u.sensitiveText),h.push(u.reasonWhy),a.push(u.problemText)),p.publicText.length>0&&(o.push(p.publicText),n.push(p.sensitiveText),h.push(p.reasonWhy)),f.publicText.length>0&&(o.push(f.publicText),n.push(f.sensitiveText),h.push(f.reasonWhy)),v.publicText.length>0&&(o.push(v.publicText),n.push(v.sensitiveText),h.push(v.reasonWhy)),y.publicText.length>0&&(o.push(y.publicText),n.push(y.sensitiveText),h.push(y.reasonWhy)),M.publicText.length>0&&(o.push(M.publicText),n.push(M.sensitiveText),h.push(M.reasonWhy)),F.publicText.length>0&&!this.redundant(F.problemText,a)&&(o.push(F.publicText),n.push(F.sensitiveText),h.push(F.reasonWhy)),x.publicText.length>0&&(o.push(x.publicText),n.push(x.sensitiveText),h.push(x.reasonWhy)),this.heuristicMapping[i]=H,this.feedbackMapping[i]=JSON.stringify({publictips1:o[0],publictips2:o[1],publictips3:o[2],sensitivetips1:n[0],sensitivetips2:n[1],sensitivetips3:n[2],reasonWhy1:h[0],reasonWhy2:h[1],reasonWhy3:h[2]}),s?(this.displayRating(i),w.fixedPw.length>0?(this.previousCandidate[i]=w.fixedPw,this.deltaHighlighted[w.fixedPw]=w.deltas):$.fixedPw.length>0&&(this.previousCandidate[i]=$.fixedPw,this.deltaHighlighted[$.fixedPw]=$.deltas)):this.synthesizeFixed(i)},e.prototype.displayRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0;if(e.length>0){void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(s=this.heuristicMapping[e],i++);var o=t.getNeuralNetNum(e),n=this.nnNumtoScoreAsPercent(o);void 0!==o&&n>=0&&isFinite(n)&&(i++,(0==s||s>0&&n(Why?)"),p+="

 

To make it even better:",this.$("#feedbackHeaderText").html(p),this.$("#feedbackHeaderTextModal").html(p)}else{var d="Your password appears strong.";a.remindAgainstReuse&&(d+=" Make sure you use it only for this account. (Why?)"),this.$("#feedbackHeaderText").html(d),this.$("#feedbackHeaderTextModal").html(d)}if(this.$(".nonmodalColorCell").show(),this.$(".modalColorCell").show(),this.$(".modalColorCellSpacer").show(),this.$(".recommended").show(),!0===this.$("#showHidePWNonModal").prop("checked")?(this.$(".fixedPWavailablePortal").hide(),this.$(".concreteSuggestionDiv").show(),this.$("#tipText1").html(h.sensitivetips1),this.$("#tipText2").html(h.sensitivetips2),this.$("#tipText3").html(h.sensitivetips3),this.$("#suggestion1").html(h.sensitivetips1),this.$("#suggestion2").html(h.sensitivetips2),this.$("#suggestion3").html(h.sensitivetips3),this.$("#sensText1").html(h.reasonWhy1),this.$("#sensText2").html(h.reasonWhy2),this.$("#sensText3").html(h.reasonWhy3)):(this.$(".fixedPWavailablePortal").show(),this.$(".concreteSuggestionDiv").hide(),this.$("#tipText1").html(h.publictips1),this.$("#tipText2").html(h.publictips2),this.$("#tipText3").html(h.publictips3),this.$("#suggestion1").html(h.publictips1),this.$("#suggestion2").html(h.publictips2),this.$("#suggestion3").html(h.publictips3),this.$("#sensText1").html(h.reasonWhy1),this.$("#sensText2").html(h.reasonWhy2),this.$("#sensText3").html(h.reasonWhy3)),void 0!==this.fixedpwMapping[e]){for(var u="",c=this.deltaHighlighted[this.fixedpwMapping[e]],m=this.fixedpwMapping[e],g=0;g"+m[g].escapeHTML()+"
":u+=m[g].escapeHTML();this.$(".fixedPW").html(u)}else this.$(".recommended").hide();s<=66?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show()):s<100?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show(),this.tookSuggestion&&(this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())):(this.$("#nonmodalFeedbackTable").hide(),this.$("#modalFeedbackTable").hide(),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())}else{this.inCompliance=!1,0!==e.length&&t.heardFromNn()&&2!==i||this.displayBar(s,!1),this.$("#confirmpw").hide(),this.$(".detailedFeedback").hide(),this.$(".portalToGenericAdviceModal").show(),this.$(".explainWhy").hide();var x="";(a=PasswordMeter.PasswordMeter.instance.getConfig()).remindAgainstReuse&&(x="Don't reuse a password from another account! (Why?)

 

");var b="Your password must:";this.$("#feedbackHeaderText").html(x+b),this.$("#feedbackHeaderTextModal").html(x+b),this.$("#nonmodalFeedbackTable").show(),this.$(".recommended").hide();var w=[],$=l.detail;for(var v in $.compliance)$.compliance[v]||w.push($.explanation[v]);this.$(".nonmodalColorCell").hide(),this.$(".modalColorCell").hide(),this.$(".modalColorCellSpacer").hide(),this.$(".nonmodalRow").hide(),this.$(".modalRow").hide();for(var M=0;M100&&(e=100);var s=e/100,i="rgb(160,160,160)";t&&s<.45?i="rgb("+Math.round(255)+","+Math.round(s/.45*140)+",0)":t&&s>=.45&&s<.65?i="rgb("+Math.round(255)+","+Math.round((s-.45)/.2*75+140)+",0)":t&&(i="rgb("+Math.round(255-(s-.65)/.35*205)+","+Math.round(215-(s-.65)/.035)+",0)"),this.$("#cups-passwordmeter-span").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span").css("background-color",i),this.$("#cups-passwordmeter-span-modal").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span-modal").css("background-color",i)},e.prototype.getMaxOfArray=function(e){return Math.max.apply(null,e)},e.prototype.expandHelpBut=function(){this.$("#expandHelpDiv").show(),this.$("#helpButton").hide()},e.prototype.modalShowCheck=function(){"text"==this.$("#pwbox").prop("type")?(this.$("#myModal").show(),this.storepw()):this.$("#expandHelpDiv").is(":visible")?(this.$("#myModal").show(),this.storepw()):this.expandHelpBut()},e.prototype.closeDiv=function(e){this.$(e).hide()},e.prototype.deselect=function(e){null==this.$.fn.slideFadeToggle&&(this.$.fn.slideFadeToggle=function(e,t){return this.animate({opacity:"toggle",height:"toggle"},"fast",e,t)}),this.$(".pop").slideFadeToggle(function(){e.removeClass("selected")})},e}();e.UIMisc=o,t=PasswordMeter.PasswordMeter.instance,s=t.getJquery(),i=new o(!1),t.setUI(i),s(document).ready(function(){s("#showpassword").prop("checked",!1),s("#showpassword").click(function(){document.getElementById("hide-show-label").textContent="Hide Password",s("#cbbutton").css("background-color","#f5f5f5"),"password"==s("#pwbox").prop("type")?s("#pwbox").prop("type","text"):(s("#pwbox").prop("type","password"),document.getElementById("hide-show-label").textContent="Show Password",s("#cbbutton").css("background-color","#f5f5f5"))})}),s(document).ready(function(){var e=s("#pwboxModal");s("#tip1, #sensText1").mouseover(function(){e.addClass("problemColor")}),s("#tip2, #sensText2").mouseover(function(){e.addClass("problemColor")}),s("#tip3, #sensText3").mouseover(function(){e.addClass("problemColor")})}),s(document).ready(function(){i.onReady()})}(UIMisc=exports.UIMisc||(exports.UIMisc={})); + +},{"./PasswordMeter":3,"./constants":6,"./rulefunctions":10}]},{},[3,4,5,6,7,8,9,10,11,12]); From 675e92e4f9f337a0bd2141c014793e6c86e3efea Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Thu, 28 Feb 2019 16:22:44 -0500 Subject: [PATCH 09/45] comment tweak --- src/ts/rulefunctions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ts/rulefunctions.ts b/src/ts/rulefunctions.ts index fe017e8..c500004 100644 --- a/src/ts/rulefunctions.ts +++ b/src/ts/rulefunctions.ts @@ -305,7 +305,7 @@ export module RuleFunctions { // compliance["forbidPasswords"] = compliant; // } - // dimension 5: forbidden passwords + // blacklist / forbidden passwords if (config.blacklist.active) { var thisExplanation = ""; var compliant = false; From 961d1a8ff2c794ccdb61bbbe78adf75f52a70854 Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Fri, 1 Mar 2019 11:11:57 -0500 Subject: [PATCH 10/45] Consolidate scaling factor logic for meter stringency. Set to 67/12 everywhere (10^12 = 2/3 meter full) --- src/ts/constants.ts | 2 +- src/ts/ui-misc.ts | 21 ++++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/ts/constants.ts b/src/ts/constants.ts index f8914ff..cee6f98 100644 --- a/src/ts/constants.ts +++ b/src/ts/constants.ts @@ -14,7 +14,7 @@ export module Constants { export const startASCII = 32; export const endASCII = 126; - export const METER_STRINGENCY_SCALE_FACTOR = 67 / 15; // scale so that guess number of 10^15 ~= 67% of meter; 15 dits * 67 percent/15 dits + export const METER_STRINGENCY_SCALE_FACTOR = 67 / 12; // 2/3 (66%) of meter should represent 10^12 export const commonStructures = ["LLLLLL", "LLLLLLLL", "LLLLLLL", "DDDDDDDD", "DDDDDD", "LLLLL", "DDDDDDD", "LLLLLLDD", "LLLLLLLLL", "LLLL", "DDDD", "LLLLLLLD", "LLLLLD", "LLLLLLLLLL", "LLLLLDD", "LLLLDDDD", "LLLLLLD", "LLLLDD", "LLLLLDDD", "DDDDD", "LLLDDD", "LLLDDDD", "DDDDDDDDD", "LLLLLLLLLLL", "DDDDDDL", "LLLLLDDDD", "LLLLDDD", "LLLLLLLDD", "DDDDDDDDDD", "LLLLLLLLLLLL", "LLLLLLDDDD", "DDDDDDDDL", "UUUUUUUU", "LLLLLLDDD", "LLDDDD", "DDDDDDDDDDD", "ULLLLL", "LLLLLLLLDD", "LLLLLLLLD", "ULLLLLLL", "UUUUUU", "ULLLLLLD", "LLLLLLLLLLLLL", "ULLLLLL", "LLLLLLLDDDD", "LLLLLLLDDD", "ULLLLLD", "DDDDLLLL", "LLLLLLLLLLLLLL", "LLLLD", "LLDDDDDD", "DLLLLLLL", "UUUUUUU", "LLLLLLLLLD", "DDLLLLLL", "DDDDLL", "DDDDDDLL", "LDDDDDD", "LLLDDDDD", "ULLLLLDD", "LLLLLLLLDDDD", "DDDLLL", "LLLLLLLLLDD", "DDDDDDDL", "LLLLLLLLLLLLLLL", "DDDDLLL", "DULLLLL", "DULLLLLL", "LLLDDDDDD", "ULLLLD", "LLLLLLLLDDD", "DLLLLL", "DDDDDDLLL", "LLLLDLLL", "LLLLDDDDDD", "ULLLL", "LLLDD", "LDDDDDDD", "LLLDLLLL", "LLLLLLLLLLLLLLLL", "DDLLLL", "LLLDDLLL", "DDDDDDDDDDDD", "DLLLLLL", "DDLLLLL", "LLLLLDLL", "LLLLLLLLLLDD", "LLDDDDD", "LLLLLDDDDDD", "DDDLLLLL", "LDDDDDDDD", "DDDDDDLLLL", "UUUUU", "LLLLLLDL", "LDDDDD", "ULLLDDDD", "ULLLLDDD", "ULLLLLLLL", "LLLLLLLLLDDD", "DDDDDL", "LLLLLLDDDDDD", "LLLLLLLLLLDDDD", "DULLLL", "ULLLLDD", "LLLLDDDDD", "LLLLDL", "LDLLLLLL", "LLDLLLLL", "LLLDLL", "LLDLLL", "LLLLLLLLLLD", "LLLDLLL", "LLLLLDDDDD", "DDDDLLLLL", "LDLDLDLD", "DDDDDDDDLL", "DDDDDDDDLLL", "LLLLLLLLLDDDD", "DDDLLLL", "DDDDDDDDLLLL", "DLLLLLLD", "LLDDD", "LDLDLD", "LLLD", "DDDDDDDDDL", "DLLLDLLL", "LDLLLL", "LLLLDDDDDDDD", "LLLLDLL", "UUUU", "ULLLLDDDD", "LLLLLDL", "ULLLLLLDD", "DDLLLLDD", "LLLLLLDDDDD", "LLDDLL", "DDDDLLLLLL", "DDDDDLLL", "DDDDDDDDDDDL", "DDDDDDDDDDL", "LLLDDDDDDDD", "LDDDDL", "LLLLDDLL", "ULLL", "LLLLLLLLLLLDD", "LLLLLLLLLLLLLLLLL", "DDDDDDLLLLL", "LLLLLLLLLLLLDD", "LLLLLLLLLLLD", "ULLLLLDDDD", "LDDDLL", "ULLLLLLLLL", "ULLLDD", "LLLDDDDDDD", "LLDDDDDDD", "LLLDLLLD", "DDLLLDD", "DDDDDDDLL", "LLDDDDDDDD", "ULLLLLLLD", "LLLLLDDL", "DLDLDLDL", "LLDDDDLL", "DDDDDDDLLL", "DLDLDL", "ULLLLLDDD", "LLLLLDDDDDDDD", "UUUUUUDD", "LLDLLLL", "LLLLLLLLLLDDD", "LDDDDDDL", "DDDDDLL", "ULLLD", "LLLLDDDDDDD", "LLDDLLLL", "LLLDDDLL", "DDDDDDLLLLLL", "DLLLLD", "DLLLL", "LLLLLLLLLLLLLLLLLL", "LLLDDLL", "ULLLLLLLDD", "LLDDLLDD", "UUUUUUUUU", "LLLLLLLLLLLDDDD", "DULLL", "ULLLDDD", "DDLLLLLLL", "LLL", "UUUUDDDD", "DDLLDD", "DDDLLLLLL", "DDDDDDDDLLLLL", "LLLDDL", "DLLLLLD", "DDDDDDDLLLL", "LDLLLLL", "UUUDDDD", "LLLLLLLDDDDDD", "DLLLLLLLL", "LLLLLLLLLLLDDD", "LLLLLLLLLLLLLDD", "LLLLLLDDDDDDDD", "UUUUUD", "UUUUDD", "LDDLLLLL", "LLLLDLLLL", "DDDDLLLLLLL", "LLLLLDDDDDDD", "DDDDL", "UUUDDD", "LLLLLLLLLLLLD", "UUDDDD", "UUUUUUUD", "LLLLLLLLLLLLDDDD", "LDLDLDLDLD", "LDDD", "LLDLLD", "DDDDDDU", "LLLLDDL", "LLLDDDDL", "UUUUUDD", "LLLLLLLDDDDD", "DDLLLLLDD", "UDDDDDD", "LLDD", "LDDDD", "LLDDDLL", "ULLLULLL", "DDDDLLLLLLLL", "LDLLLDLL", "DDDDDLLLL", "LDDLLL", "LLLLLDLD", "ULLLLLLDDD", "ULLLLU", "DDLLL", "LLDDLLL", "ULLLLLLDDDD", "LDDLDD", "LDLLDL", "ULLLLLLLLLL", "LLDLLLDL", "", "LLLLDLLD", "LLDLLDLL", "LLLDL", "LLDLLLLD", "ULDDDDDD", "ULLULL", "LLLDDDLLL", "UUUUUDDD", "LLDLL", "UUUUUUD", "LLLLDDDL", "LLLLLLLLLLLLLD", "LLLLLLLLDDDDDD", "UUUUUUUUUU", "LDLLLLDL", "LLLLDLDL", "LDLLDLLL", "LLLLLLLLLLLLLLLLLLL", "DLDLLLLL", "DDDLLLDDD", "DDDDDLLLLL", "LLLDDDL", "DLLLLDLL", "LLLDLLDL", "LLLLLLLLLLLLDDD", "LDDDDDDDDD", "ULLLLLLLLD", "LDLDLLLL", "LLLLLLLLLLLLLLDD", "DDLLLLLLLL", "LLDLDLLL", "DLLLLLDL", "DDDDDDDDU", "DDDDDDDDLLLLLL", "LDDDDDDDDDD", "LDLLLLLD", "DDLLLLLLDD", "LLDDDL", "LLLDLDLL", "DLLL", "ULLDDDD", "DDLLDLLL", "DLLLLLLLLL", "DLLDLLLL", "DDDLL", "LLLLLLDDDDDDD", "DDD", "LLLLLLLDDDDDDDD", "LLLDLD", "DDLLLLLD", "DLLDLL", "LLLLLLDLL", "UUDDDDDD", "DDDDDDDDDLLL", "LLDDDLLL", "ULLLLLLLLDD", "ULULLL", "DDLLDDLL", "DLLLLLDD", "LDLLL", "DDDDDDDLLLLL", "DDLDDLDDL", "ULULUL", "ULLLUL", "LDLLLD", "UDDDDDDDD", "LLLLLDLLL", "LDLDLL", "ULLLLULL", "DDDDDDDDDDDDD", "ULLLLLLLDDDD", "UUUUDDD", "LLLLLLLLLLLLLLLLLLLL", "DDDDDDDDDDDDDD", "DDDLDDD", "DDLDDL", "DLLLDL", "ULLLUU", "DLDLDLDLDL", "ULLLLLLLDDD", "ULLDDD", "LLLLLLDLLL", "DDDLLLLLLL", "DDDDDDDDDDLL", "DDLLLDDDD", "UDDDDDDD", "ULUULL", "ULULLU", "ULLLLLLLLLD", "ULUULU", "DDDDDDDDDLL", "LLLLLDLLLL", "DDDDDDDDDDDLLLL", "ULUUUL", "ULUUUU", "ULLUUU", "ULLULU", "ULLUUL", "LLDLDL", "LLLLLLLDL", "LLLLLLLS", "LLDL", "LLLLLLLLLLLLLLD", "LDDDDDDDDL", "LDDDLLL", "LLLLLLS", "ULULUU", "LDDDDDDDDDDD", "LLLLLLLLLLLLLDDD", "LLLLLLLLLDDDDDD", "DDDDDDLLLLLLL", "DDDDDDDDDDLLL", "LLLDDLLD", "DDDLLDDD", "LDDLDDLDD", "LLLDLLLLL", "ULLLLLLLLLLL", "LLLLDDLLL", "DDLLLD", "LLLDDDDLLL", "DDDDDDDDDDDLLL", "LDLDLDL", "LLLLLLLLDDDDD", "LLLLSLLL", "LLLLLLLLDDDDDDDD", "DLLLDD", "LLLLDLD", "DDDDDDDDDDDDDDDD", "DLDLLL", "UUUUUDDDD", "DDDDDDDDDDLLLL", "LLLLDLLLLL", "DLLLD", "DDDDDDDU", "DDDDDDUU", "DDDLLLDD", "LLDDDDL", "DLLLLLLLD", "LLLSLLL", "LDDLLLL", "ULLLDDDDDD", "LLLLLLLLLLLLLDDDD", "DDLLLLD", "ULLULLLL", "LLLDDLLLL", "LLLLDDLLLL", "DDDLLLLDDD", "LDLL", "LDDDDDDDL", "LLLDLLLLLL", "DDDDDDDDDLLLL", "LDDDLLDD", "LDDDLLLL", "LLDDLLLD", "DDDDDDDDDDDLL", "LLLDLLDD", "DDLL", "DDDDUU", "DDLDDLDD", "DDDDDDLLLLLLLL", "DDLDDDD", "DDDDLLDD", "LLLLLS", "ULLDDDDDD", "LLDLLDL", "LDLDLDLL", "LLLLDLDD", "LDLLLLLLL", "DDDLLLD", "LLDLLLDD", "ULLDDDDD", "ULLLLLLU", "ULDDDD", "LLLDDLLLDD", "UUUUUUUDD", "LLLLLLLDDDDDDD", "UUUDDDDD", "LLDLLLD", "UUDDDDD", "LDLDL", "UUUUUUUUUUU", "LDLLLLDD", "LLDLLLLLL", "LLLDDLDL", "DLLLDLL", "DLLLLDD", "LLLLLSDD", "DDDDULLL", "DDLLDDDD", "LLLLLLLDLL", "DLLLLDL", "LLLLLLLLDL", "LDLLLDL", "DLDLDLD", "LLDLDD", "LLLDDDDDDDDD", "ULLLLDDDDDD", "LDDDLDDD", "DDDDDDDDDDDDDDD", "DDDDDDDDDDDDL", "ULLULLL", "LDLDLDLDLDLD", "LLLDLLD", "DDDDDDDLLLLLL", "LDDDDDL", "DDDLLLLLLLLL", "LLDDL", "LLLLLLDDL", "LDLLDLL", "LDLLDLDL", "LLLLLLLLLLLLLLLDD", "UULLLLLL", "ULLLLLLLLLDD", "LDDDDLL", "LDLLDLLD", "DDDLDD", "DDLLLLLLLDD", "LLLLLLLLS", "UUUUUUDDDD", "LLLLDDLD", "UDDDDD", "LLDDLDLL", "DDDDDDDDLLLLLLL", "UUUDDDDDD", "DDDDLDDDD", "LLDDLD", "LLLLLDDLLL", "DDLLLDDD", "UUUUUUDDD", "LLLLLDDLL", "LLLLDDDDDDDDDD", "DDDLLLLLLLL", "LLLLLLLLLDDDDD", "LDLLDD", "LLLLLLLLLLLLLLLLLLLLL", "LLLLLLLLLLLLLLLD", "LLLSLLLL", "DDDDLD", "DDLDDD", "DDDDUUUU", "DLDLL", "LDLLLLD", "DLDLLLDL", "LLLLSLLLL", "LDLDLLDL", "DDLDLLLL", "DDDDDDDDDDDLLLLL", "LLLLLLLLLLDDDDDD", "UUUUUUUUUUUU", "LLLDLDL", "LLLLDDDDDDDDD", "DDDDDLLLLLL", "DDULLLLL", "ULLLULL", "LLLLLLLLLLLLLLDDDD", "DLLDLLDL", "LLLDLDLD", "LLLDDDDDDDDDD", "DDDDLLLLDDDD", "LLLLSL", "LDLDLLL", "DLLLLLLLLD", "LDLLLDLD", "DDDDLDD", "ULDDDLL", "LLDLLLLLLL", "LLLLLLSDD", "DLDLLLL", "ULLLLLLLLDDD", "LLDLDLL", "DDDDDDS", "DDLLLLLLLLL", "LDLLLDDL", "ULLLLDLL", "DDLLLDLL", "DDLLDL", "LLLLLSLLL", "DLLLDDLL", "LDLDLDLDL", "DLLLDLDL", "DLLDLLL", "DLLDL", "DLDLDLLL", "LLDDLLD", "DDDLLLLLDDD", "DDSDDSDDDD", "LLDDLLDL", "DLLDLLLD", "DLLLDDD", "LLDLLDDL", "LLLLLU", "DLLDLDLL", "LDDLDL", "LDDLLD", "LLDLLDLD", "DDLLDDD", "DDDDLLLD", "DLLDDL", "ULLLLLDDDDDD", "DDDLDDDL", "DDLLD", "LLLLLDLLLLL", "LLLDDLDD", "LLDLDLLD", "LDDDDLLL", "DLLDDLLL", "LLLLDDDDDDDDDDD", "DLDLLDLL", "LLDDDDDDDDD", "DDDDDDUUU", "DLDDLLLL", "DDDLLD", "LDDLLLLD", "LDLLLLLLLL", "DDDDUUU", "LLDLDLDL", "DLLLLDLD", "DDLLLLDDDD", "ULLLLDDDDD", "LUULDDL", "ULLLDDDDD", "LDDLLLDL", "ULLLLLLLLDDDD", "DDLLLLDL", "DLLLLLLLLLL", "ULLLLLU", "LLLLLSLL", "DLLLLDDL", "LDLDLLLD", "DLDLLLLD", "UUUDD", "LDLDDLLL", "LLLLLLDLLLL", "LDLLD", "DDDDDDUL", "LDLD", "DLLLLDDD", "LDLLDDLL", "UUUUD", "LDDLLDLL", "LLLLLLLLDDDDDDD", "LLLDLDDL", "DLLLDLLD", "DDDDDDDDDDLLLLL", "LLLLLDDDDDDDDD", "DDDDDDDDUU", "LLLLLDDDDDDDDDD", "ULDDDDDDDD", "UUULLL", "LLLLLSLLLLL", "LLLLLSLLLL", "DLDLLD", "LLLSDDDD", "LLDDDDDDLL", "DLLLDDDD", "DLDLD", "ULLLLLLLLLLLL", "LLLLLLULLLLL", "LLDLDDLL", "LLLLLLLLLLLLLLDDD", "DDDDLLD", "LLLDDDLD", "ULLLLULLLL", "LDDLL", "DDLLLDDL", "DDDLLLLD", "DDDL", "ULDDDDDDD", "LLLLLLLU", "DDDLLDD", "LLLLLLLLLLDDDDD", "DDLDD", "LLLLLLLLLLLLLLLLLLLLLL", "UDLLLLLL", "LLLLSDD", "LDDLDLLL", "DLDDLL", "LLLLSLLLLL", "LLLLSLLLLLL", "LLDDDDDDDDDD", "DLDDDD", "ULLLDLLL", "LLLDDDDLL", "DDDDLDDD", "DLDLDLDLDLDL", "ULLLLLUL", "DDLDLL", "UUULLLLL", "UDDDDDDL", "LLLLLLDDDDDDDDD", "LLLLLLLLLS", "LLSLLL", "LLDLD", "DDDLDDDD", "LLLLLLLLLLLLLLLLDD", "LLLDDLD", "LLLLLLSD", "UUUUUUUUDD", "LDLDDD", "LLDLLDD", "DDDDLLLDDDD", "DDLLLLLLLLDD", "LLLLDDDDLLLL", "DDDDDU", "UUUDDDUU", "DDDDDDDDLLLLLLLL", "LLLLDLLLLD", "UUUUUUUUD", "LLLLSDDD", "LLLLLDDDDDDDDDDD", "DDDLLLLLLDDD", "DLLDDD", "DLLDLD", "LLDDLLLLL", "UDDDDDDU", "LSLLLL", "LLLLLLULLLLLL", "DDDDDDDDDLLLLL", "LLLLLLDDLL", "DDDDDDDDS", "LLLLLSDDD", "LDDLLDDL", "ULLULLDD", "DLLLLLLDD", "ULLLLULLL", "LLDLLDDD", "UULLLL", "ULLLULLLL", "LLLLLLSLLL", "LLLDDLLLLL", "UUDDDDDDDD", "LLLLLLU", "DDDDDDLLLLLLLLL", "ULLLDDDDDDDD", "DDLDL", "DLLDD", "LDLDDL", "LDDLDDL", "LLLLLLDDDDDDDDDD", "LLLLLLSLLLLLL", "DDDLD", "DDDDDDLD", "DDLLLLLDDDD", "LDDLDDDD", "UUDDDDDDD", "DUUUUUUU", "LDDL", "DDDUUU", "ULULLLLL", "LDLDLDD", "LLLDDDDDDDDDDD", "DLLDDLLD", "UUUUUUUDDD", "LLLDLDD", "DDDDLLLDD", "LLLLLDDDL", "ULLLLLDL", "ULULULUL", "LLLLLLLDDL", "LDDLLLDD", "ULLLLLLLLLLD", "DDDULLLL", "LLLSLL", "LLLLLLSL", "LLLDDDLLLDDD", "LLLDDDLLLL", "LLLLDDDLLL", "LDLLLDDD", "LLLSLLLLL", "LLLLDDDDL", "LLLLDDDLL", "LDDDL", "LLLLLLULLLLLLL", "DDDDDDDDDDLLLLLL", "LLLLLLLSDD", "UDDDDU", "LLLDLDDD", "LLLLLSLLLLLL", "LLDDLDD", "DLDDL", "LDLLLDD", "LLLLLLDDLLL", "DDLDLLL", "DDDDDDDDDDDU", "LLDDLDL", "DLLDLLD", "LDDDDLDDDD", "LLLLLLSLLLLL", "DDDDDDDDDLLLLLL", "UUUUUUUDDDD", "ULDDDDD", "LLLDLLLDDD", "DDLLDDL", "ULLLLLDDDDD", "LLDDDLLD", "UUUULLLL", "ULLLLLUU", "DDDDDDDLLLLLLL", "LLLLDDDLLLL", "DLDDLD", "DDDDLLDDDD", "DDSDDSDD", "ULLDLLLL", "LDDLDDLD", "DDDDDDDDUUU", "DLLDDLL", "DDDDDDDDDDDDDDDDDD", "LLLLLLLLLLLLLLLDDD", "ULLLU", "LLLLLLDLD", "UUDDDDUU", "LLLLLDDDDL", "LLLLLLLLLLLLLLLDDDD", "LLLSDD", "LLLLLLSLLLL", "LLLLLLLLLDDDDDDD", "LSLLLLL", "LDDDLD", "ULLLLDDDDDDDD", "DDDDLLLLLDDDD", "DDDDDDDDDU", "LLLLSDDDD", "LDDLDDLL", "ULLLLUDD", "LDLLDDDD", "ULLULLLD", "LLLDDDDDDLLL", "LLDDDDDL", "ULLDDLLL", "DDDLDL", "LLLLLSL", "LDLLDLD", "LDLLDLDD", "LDLDLLD", "DLDLDD", "DDDDLLLLLLLLL", "LLLLDDDDLL", "LLLDLLLLD", "DDLLDLL", "DDLLLLLLDDDD", "ULLDD", "UUUDDDDDDDD", "ULULLLL", "DDLDDLLL", "LDLDLLDD", "ULLLULLD", "DLLDLLDLL", "DDUUUUUU", "LDDLLDD", "ULULDDDD", "LLLLLLLLDLL", "LLLLSLL", "LLLLDLLLLLL", "DDLLLLLLLLLL", "LLDLLDLLD", "LLLLLSDDDD", "LLLLLLLLLDL", "DLDLDLDLD", "LLLLLSD", "LLLLLDDLLLL", "DDDDDDDDDDDDLLL", "DLDL", "LLLLDDLLLLL", "LLLLLLLDLLL", "LLSLLLLL", "DDLLLLLLD", "DDLDDDDD", "LDDLLLLLL", "LLDDDDLLL", "DLDDDL", "LLLLLDDLLLLL", "LLLLLLLLLLLLLLLLLDD", "LLLLLLLLLLLDDDDD", "LLLLLLLSLLLLLL", "LDDLLDL", "LLLLLLUU", "DULLLLLD", "UUUUDDDDDD", "DLLD", "UUDDD", "LLLLLLLDLLLL", "LLLLLLLLLDDDDDDDD", "LDLLDDL", "DDULLLL", "ULLLDL", "DLLLDLLLDLLL", "LLLLDDDDLLL", "LDLDLDDD", "LLDLDDDD", "DLDDD", "DDDDDDDDDDU", "LLUULL", "LLLLLLSDDD", "UULLDDDD", "LLLLUU", "LDLDDLDL", "DDDLLLDL", "LLLLLLLLSDD", "DDDLDLLL", "UULLLLL", "ULLLLLLLLLLDDDD", "DDDDDDDDUL", "ULLLDDDLLLL", "LLLSDDD", "DDLDDLL", "DDDSDDD", "LLLULL", "DDDDUL", "DDDDDLLLLLLL", "UUUUDUUU", "DLDLDLL", "LDLDDLDD", "LLLLLLLLLLLDDDDDD", "DDDDULLLL", "ULDLLLLL", "DDLDLD", "DDDDDDLLLLLLLLLL", "DDDDDLDD", "DDDLLLLLDD", "LDLDLDDL", "ULDLDD", "LLLLLLDDDL", "DLLLLDLLL", "LLLUUU", "LLLLLDDDLL", "DDLLDLLD", "DLLLDDDL", "DDDDDDDDDDDDLLLL", "DLLLDDL", "LLDDLDDL", "ULLLULLLLL", "DLDLLLD", "ULLDLL", "DLDLLLDD", "LSLLLLLL", "DLLDDDLL", "DLLLLDLLLL", "DDDLLDLL", "ULLDDDDDDD", "LLLLLLLSD", "LLLLUL", "DLLDLLDD", "LLLSLLLLLL", "UDLLLL", "LLLLLLSLLLLLLL", "UUULLLDD", "DDLDDLD", "LLLLLLLLLLLLLLLLD", "DDDDDDDS", "LULLLL", "LLLLLLSDDDD", "DDUUUUU", "UDDDDDDDDD", "LLSLLLL", "DDDDLLLLDD", "LLLLLLLSLLLLL", "DDDLLLLDD", "LDDLLLD", "LLLLDLLLD", "LLLLULLL", "DDULLL", "DDSULL", "LDDDLLLD", "LDDDDLDD", "DDDDDDDDDDDDLL", "LLLLLLLULLLLL", "ULLLLLLLLLDDDD", "UUUUUDUU", "DDDDDLD", "ULLDDDDDDDD", "LLLLLLLDDDDDDDDD", "ULLLLULLLLL", "DDLLLDL", "LLLLLSLLLLLLL", "UUUDUUUU", "DDUUUU", "DLLLLLLLLLLL", "LDDLD", "LLLLLLULLLL", "LLDLDLDD", "UULLLLDD", "ULUL", "ULLLLUUU", "ULLLDDDDDDD", "LDDDLDLL", "DLDDLDLL", "LDLDDDDD", "LLDDDDDDL", "ULLLLLUD", "DDDDLLLLLLDDDD", "UULLLDDD", "ULLLLLDDDDDDDD", "DLLLDLLLL", "LDDLLDLD", "DLLLLLLDL", "LLDDLLLLLL", "DLDDDLLL", "LLLLLULL", "DDDDDDDUU", "DDDLLLDDDLLL", "UUDDDUU", "LDDLDLDL", "LDDDDDLL", "DDDDDDDDDDDDDDDDDDDD", "UULLUU", "LLDDDLDD", "UUU", "LULULU", "UUUDLLLL", "UDDDUU", "DLLLDDLD", "DDLLDLDL", "DDDUUUUU", "LDLLDDDL", "DLDDDDDD", "SLLLLL", "LLLDLLLLLLL", "UDDDDDDDDL", "LDLLDDLD", "UULLL", "LLDDDLDL", "LLLLLDLLD", "ULLLDLL", "DDLDDLDDDDL", "LLLLU", "UUUUUUDU", "ULLLLLULLLL", "DDLDDDDL", "ULLLLLULLLLL", "DLLDDLDL", "DLLLLLLLLLD", "LLLLLLLSLLLL", "UDDDDDDDDDD", "ULLLLLULLL", "LDDLLDDD", "DLLLDLD", "DDDDDUU", "DDLDDLDDDD", "UUUUUUUUUD", "DLDLLDL", "LLDDDDDDDDLL", "LLDLLLLDL", "LLLLLLLLLLLLLLLLLLLLLLL", "DLLDDLD", "DLDDLLL", "DLDLDDLL", "DDDDULL", "LDDDLLDDD", "LLDDLDLD", "LLLLLLLLLLLLLLLLDDDD", "DDLLLLDDD", "LDLDDDLL", "LLLDDDDLLLL", "DLLDLDL", "DLDLDLLD", "LDLLLLDLL", "LLULLLLL", "UUUUULLL", "UUUUUUUUDDDD", "ULLLLDDDDDDD", "LDDDDDDDDDL", "UDUDUD", "DUUUUU", "LLLLSLLLLLLL", "UDDDD", "DLDDLLDL", "DDLDLDLL", "ULLULULL", "DDDLDDL", "DLLDLDLD", "LLDLDDL", "LLULLL", "UDLDLDLD", "UUULLLL", "LLLLLLLULLLLLL", "DLDDLLLD", "ULLLLDL", "LLDDDDDDDDDDD", "LLDLDDLD", "LLLLLLSLL", "DDLDLLDL", "DDLLLDLD", "DDL", "LLDLDLD", "LDDDDDDDDDDL", "LDDLDLLD", "DLLDDDD", "DDLDLLLD", "ULLDLLL", "DLLLDLDD", "LDLDD", "UDDDDDDDL", "LLLLLLDDLLLL", "DDDDDUUU", "LDDLLLLLLL", "UDUDUDUD", "DDDLDLL", "DLDLLDDL", "LLLLLLSLLLLLLLL", "DLLDLDDL", "ULLULLD", "LLLLDLLDD", "LDDLDLDD", "ULLLLLLLLLLDD", "ULLLLLLDDDDDD", "ULLLLLLLLLLLLL", "ULLSDD", "LDDDLDD", "UDLLLLL", "DLDDDDD", "LLLLLLLLLLDDDDDDDD", "LUUUUU", "DDU", "LULULL", "LLLLLLLLLLLLLLLLLLLLLLLL", "LLLLLLLSLLLLLLL", "LDLDDLLD", "LLLLLLLSLL", "DLDLLDLD", "DLDLLLLLL", "UUUUUUUUUDD", "LDDDLLDL", "UUUUUUUUUUUUU", "DDUUU", "LDLLLLLLD", "LDLDDDD", "DDDDLLDL", "DSDSDDD", "DLDDLLD", "LLLDDDLLLD", "LDDLDDD", "LLLLLLLDLD", "LLULUL", "LLDDLDDD", "ULLLLLULL", "LLLLDDLLLLDD", "LDLDDLL", "LLLDDLLDD", "DLDLDLDD", "LLLLLLLLLSDD", "LLDDDDDLL", "DDDDDLLD", "LLLLLDLDL", "LLLLLLDLLLLL", "UUDUUUUU", "LLLLLLLLSLLLLLL", "LLLLLLUUUUUU", "SSSSSS", "LLLLLLLLLLLLDDDDDD", "DDULL", "LLLLLLLLLLSLLLLL", "DDDDDS", "LLDLDDD", "DLLLLLDLL", "ULLLLUD", "DUUUU", "LLLLLLLLSL", "DLDDLDDL", "LLLLLLLLLLLSLLLL", "LLLLLDDDLLL", "ULDLLL", "ULLLLLLULLLL", "UUUDDDDDDD", "ULLLULLU", "UULLLU", "ULLLULUL", "LDDLDLL", "DUUUUUU", "DDDDLDDDDL", "LLLLLLLLSLLLLL", "DDDLLDL", "LLLLLLLLLDLL", "ULLLLLLDDDDD", "LLLLLLLSLLL", "LLLLLLLLLSLLL", "UDUUUUUU", "LDLDLLLLL", "DDDDDDUUUU", "DULLLULL", "DDDDDDULLL", "LLDLLLLLLLL", "ULLULLUL", "LLDDLLLDD", "LLLLUD", "UUUD", "ULLDDULL", "ULLLLLLLLLDDD", "LLLLLLDDDDL", "DDDDDDDLLLLLLLL", "UULLLLLD", "LDLLDLLLL", "LLLULLLL", "LLDLLLLDLL", "DDLDDLDDLDDL", "LLLLLSLLLLLLLL", "LDLLDDD", "ULULU", "LULLUL", "LLLULU", "LLLLLLLLLLLSLLLLL", "DDDDDDLU", "UULUUL", "LLDDLLDDLLDD", "LLLLLLLSL", "DDLDDLDL", "LLLLLLUD", "UUUUUULL", "UDDDUDDD", "LLLDDDLLLLLL", "ULLLUD", "ULLLDDLL", "LDDDDDDDDDDDD", "UDDDDDDDDDDD", "ULULL", "ULLLLDDL", "DDLLDDDL", "DDDDLDDL", "SLLLLLL", "LLLLLLLDDLL", "DDDDLLLLLDD", "ULULULU", "SLLLLLLL", "LLLLDLLDL", "UUDDUU", "DDLLLLLLLLLDD", "UUUULU", "UUUDDUUU", "UUULUU", "LLUULU", "DLLDLLLLL", "LLUUUU", "ULLULULU", "ULUUUULL", "DDLDDDLL", "LLDLLLLLD", "ULLLDULL", "DDDDLLLLLLLLLL", "ULLULLLU", "LLLLLLLLLLSLLLL", "DULLLLLLL", "ULLUDDDD", "LLLLLDDDDLLLLL", "LLLLDDDDDDDDDDDD", "DDDDU", "DDDULL", "DDULLLDD", "LLLLLLLLSLLLL", "LLDLDDDL", "LLLDLDLLL", "LLLLLLLSDDDD", "LLDDDLD", "UUUUDDDDD", "DSDSDSDDD", "DDDDULLLLL", "DDLDDLLD", "LLLLLLLULLLLLLL", "ULLULLLLL", "ULULLLUL", "LDLLLLLLLLL", "UUUULL", "LLLDLLDLL", "LDLLLLLDL", "ULULULLL", "DDDLLLLLLLDDD", "DDUUUDD", "LLLLLLLLULLLLL", "LDDLDDLDDLDD", "ULLUULLU", "DLLLLLLU", "ULULLLLU", "LDDLDLD", "LLLUDD", "UULULL", "LLLLLLLLLLLLLLLLDDD", "UUUUUDDDDDD", "LLDLLLDLL", "DDDLDDLL", "DDDUUUU", "LDDDLLD", "LLLLLLULLLLLLLL", "DDDDDDULL", "LLLLLLLLSLLL", "UUUUUUUUDDD", "LDLDDLD", "ULLLUULL", "ULULLULL", "LLLLLLLLDLLL", "LLLLLLLLLLSLLL", "LLLLLLLDDLLL", "DDDDDDDDDDS", "LLLLLLLLLLLLDDDDD", "UDDDDDDDDU", "LLLLLLLLLLDL", "ULLLLULU", "LLUUUL", "DUUUUUUD", "LUULUU", "LLLLLLLLLLLSLLL", "ULULUUUL", "LLLLLLLLLLLLSLLL", "LDDDDDDLL", "UUULLLDDD", "ULLLULLLLLL", "DDLLDDLD", "ULULLULU", "LLLLLLLSDDD", "LLLLLLLLLSLLLL", "DDLLDLD", "ULLUL", "LLLLLLLLLLLLLLLLLLDD", "LLLLLLLLLSLLLLLL", "DUDLUDUL", "DLLLLDDDD", "DDLDLLDD", "UUULUL", "LLLLLLLLDDL", "LLLLLLLLLSLLLLL", "ULLUUUUU", "SSSSS", "UULLLULL", "DLDLLDDD", "ULLULLUU", "ULULUULU", "LULUUU", "LLLLLLLLSLLLLLLL", "LLLLLLLSLLLLLLLL", "LLLLLUUU", "LLLDDLLLLLL", "ULLLLUL", "DDUUUUDD", "DDLDDDL", "LDDLDDLDDDD", "LLLLUUUU", "UULLLLLU", "LLLULLL", "ULULLLUU", "ULLUULLL", "DDDDDDDDDDDDDDL", "LUULLU", "LLLDLLLLLD", "LLDDLLDDLL", "LDDLDDLDDL", "LLDDDLLLL", "LLLDLLLDL", "LUUULL", "LUULLL", "DLLDLDD", "UULLUUUL", "ULULLUUL", "LDLDLDLDLDL", "DDLDLDDL", "ULUUULLL", "UULLULLL", "ULLLUUUU", "DDUU", "LLLDDDLLLLL", "LLLLLLUUUUUUU", "UUUDUUU", "LLULUU", "LLLLLLLLLLLSDD", "ULLLLUUL", "ULUULULU", "LLLUUL", "LLLLLDLLLLLL", "LULLLLLL", "UUDUUU", "DDDDLDLL", "LLSLLLLLL", "LLLLDDDLLLLDDD", "UUUULULL", "UUULLUUL", "LLLLLLLLLLLLSLLLLL", "LULLL", "DDDLLLDDDD", "DDDDDDDDUUUU", "LLLLDLDLL", "LSLLL", "DLDLDDDL", "LDDDLLLLL", "LDDDDDDDDDDDL", "UULLLLUL", "UULUUU", "UUULLLLU", "UULULU", "ULUULULL", "UUUUULUU", "UUUDU", "ULUULUUL", "UUULLULL", "ULLUUULU", "ULULULLU", "UULLLLUU", "UUDUU", "DULULLLL", "UULLLUUU", "DDDDLDL", "ULLLULUU", "UUULLLLD", "LLLLLLLDLLLLLL", "LLLLLLLLDLLLLLL", "DDDLDLLD", "DDLLLLLLLD", "LLLLLLLLSLLLLLLLL", "LLDLLDLLL", "UUULULLL", "LLLLLLDDDLLL", "LLLDLLLDD", "UUULUULL", "ULLUULUL", "UULUUULL", "UULLULLU", "LSLLLLLLL", "LLLLSLLLLLLLL", "DLLLLLDLLL", "LDDDLLDDLLL", "LLLSLLLLLLL", "LDLLLDLLL", "DLLLDLLLLL", "LLLLSD", "LLLLLDDDDLL", "LLDDDLLDDD", "LLLLLLDLDL", "ULDDLLLL", "LLLLDDLLLLLL", "LLDLLLLLDL", "UDDUDD", "DDLLDLDD", "LLLLLLDDS", "UUUDDLLL", "ULUULUUU", "DLLDDDDD", "DDUUDD", "UULLULUU", "DDLUL", "DDDDDDDDDDDLLLLLL", "LUUULU", "DULLU", "DULUL", "LLLLLLLLDLLLL", "LLLDDLLLD", "DDDDDDDDULLL", "DDDULLL", "DDDDDDUD", "UULULLLL", "ULLLLLLLU", "ULLULUUL", "ULLUUULL", "LLLUUD", "LLLLLLDLLD", "LLLLLLDDDLL", "UUUUUUUUUUUUUU", "LDDDLDDL", "UDDLLLLL", "UULLLUUL", "DDDLLDDDD", "DDUUL", "ULULDD", "UULULULU", "UDUUU", "DDLLLLLLLDDDD", "ULUUUUUL", "DLDDLLDD", "LSLLDDDD", "DDDDDDDDDDDDDDDDD", "LLULL", "DULLULLL", "LULLLU", "LLLLLLLLLLLSLLLLLL", "LLLLLLLULLLL", "UUUUUL", "ULDDLL", "DLLLLLLLDD", "UULLUULU", "UDDDUUDD", "LLLLLLLLULLLLLL", "DLDDLDL", "UUUUUUDDDDDD", "DDLLU", "DDDLLLLLLLLLL", "ULLLLSDD", "LLLLLLLLU", "LLLLLLLLLLLLLLLLLD", "DDDDDDDDDDDS", "UUULLULU", "LLLLDLLLLLLL", "DDDLLDDL", "DDDDDDULLLL", "LLDLLLDLLL", "DLDLDDD", "LLLLLLLLSD", "UUUUUUUL", "DDDDDLDL", "LLLUL", "UUUUUULU", "DULLLLUL", "LLLLLUDD", "LSLLLLLLLL", "DLDLLDD", "ULLLLLDDDDDDD", "UUULULUL", "LLUUL", "UULULLUL", "LLUUUD", "UUUULUUL", "ULLDULLL", "ULDDDDDDDDD", "DDLLDDLLDD", "ULLUULUU", "ULUULLUL", "ULUUULLU", "UUULUUUU", "UUUUDU", "DDDDLLLLD", "UULUUUUU", "ULULULUU", "DLDLDDL", "LLLLLLULLLLDD", "ULULULDD", "DDDLLLLLLLLDDD", "DDUULLLL", "ULLLULLLDD", "LLLLLDLLLLLD", "ULLLUUUL", "DDLDLDD", "ULUULLUU", "DLLUL", "UUULLLUU", "DDDDSDD", "DDLLDDDDDD", "DDDDDDLLLLDD", "LLLLLLLLLLSLLLLLL", "UUULLLUL", "DDDDDDDUL", "UUULULUU", "LLLLLDDDDLLL", "DLLUU", "DLLLLLLLLLLD", "ULLLLLSD", "LLLLLLLLLLLLSLLLL", "UDDDDUDD", "LLLLLLLLULLLLLLL", "DDLDLLD", "DDDDLLLDDD", "UUUDUU", "ULULUULL", "DDDUU", "LLLLLLLDLLLLLLL", "LUULUL", "UULLUUUU", "DDDDDDLLLLLDD", "DLLULLLL", "DDLDLDLD", "DDDLDDLD", "ULLLULDD", "ULDLLLL", "DDDDUDDD", "LDDLDDDL", "DDLDLDL", "ULLLLLSDD", "UDDDDDU", "ULULLUUU", "LDLDLDLDLDLDLD", "LLLLLLLLLLLLSDD", "DLLLDLLLD", "DLDDDLDD", "ULUUUULU", "UUUUDDDDDDDD", "UUUUUDDDDD", "DUUULLLL", "ULLULUUU", "LDLLLLDLLL", "LLLLLLLLLLLDDDDDDDD", "ULLLLULLLLLL", "LLULU", "DLUULLUL", "LLLLLLULLLLLDD", "UUUUULUL", "ULLLUDDD", "LLLLDLDLLL", "DDUDDUDD", "DULLLULU", "DLLLLLDDDD", "LLLLLDDDDLLLL", "UUULL", "DLLDDLDD", "UUULUULU", "DDDDDDDDDDDDDL", "ULLLUULU", "UULUULLU", "DUULLUUL", "ULLLLLLLDDDDDD", "ULUULLLU", "DLLULULL", "LUULL", "DLDDDLLD", "LLLLLLLLLLSDD", "DDLU", "DULULUUL", "DLDDLDD", "UULLULUL", "DDLDDDLD", "LLLLDDDDUU", "DLULU", "ULUUUUUU", "LLLLLLLLDDLL", "LLLLDLLLDL", "DDUL", "ULULUUUU", "ULUULLLL", "UDDUDDUDD", "LLDDDDLD", "LLULLU", "UDUUUU", "UUUULLUU", "LLLLLLDDDDLLLLLL", "DDDLDLDL", "ULUUULUL", "UUULULLU", "UUDDUUDD", "ULLLLLDDS", "DLLDDDL", "DDDDDDLLLLLLDD", "UULUULLL", "UULULULL", "DLLLULLU", "ULULLLLD", "DULLLLLU", "LLDLDLLLL", "DLDDDDL", "ULULUD", "UUUULLLU", "UUUULLUL", "UUULLUUU", "DUUULLUL", "DUUULULU", "UULLUULL", "DDDDDDLDD", "DDDDUUUUU", "DDDLLLLLD", "LLLLLLUL", "DLLLLLLLDL", "LLDLLLLDD", "DULULLLU", "DDDDLLDDD", "UULUUUUL", "DULULULU", "DDDDLLLLLLLDDDD", "LLDLLLLLLD", "LLLLLDLDD", "UULULLLU", "LLLDDDDLLLLLL", "LLLLLLDDDDDDDDDDD", "DLDLDDDD", "LLLLLLLLLLLLLLLLLDDDD", "DDDDLDLD", "LLDDDDLLLL", "LLLLLLLDDDL", "DDLD", "LLLUU", "DDDLDLD", "DDULU", "DUULLLUL", "UUUUULLU", "DLLDLDDD", "DDLDLDDD", "ULLUUUUL", "DLLUUULU", "ULLU", "DUULLLLL", "UULUULUL", "UULULLUU", "LLLLDU", "DLLUULUU", "DDDDDDDDDLLLLLLL", "DLLLLLUU", "ULUUULUU", "DDDDDDDUUU", "ULDDD", "LLUUU", "DLDLDLDLDLD", "DDLLLDDLL", "LLDDDDDDDLL", "DDDLLDLD", "ULLDULLD", "DLLLULLL", "UULLLULU", "DULULULL", "UULUULUU", "DDLLLLLDDD", "DULULLUL", "UDDUDDDD", "UUUULULU", "DDDDLLLLLLDD", "DUULU", "DLLLLULU", "DDULLLLLL", "DLLLULUU", "DDDUDDDD", "LLLLLDLLDL", "UUDDDDLL", "DLDLLLLLLL", "DDLLLDDLLL", "LLLLLSLLLLLLLLL", "LLLLLLLLLLLLSLLLLLL", "ULLLUDD", "LLLDULLL", "DUUUL", "DDDDDDSS", "UULULUUL", "LLLDDDDDDDDLLL", "DUULLLLU", "LLDLLDLLLL", "DUULLULU", "LLLLLUU", "DDLDDDDDD", "DUUULLUU", "DDLUU", "LLLLDLLDLL", "DLDDDLL", "UUUULUUU", "LLDLDLLLLL", "DLLLU", "LLLLLLLDLLLLLLLL", "LLLLLDLLLD", "LLULLD", "LDLLLLDDL", "DDDLDLDD", "UUULLU", "DDDDDDDDDS", "DUULULUU", "UDDUDDD", "ULLLUUU", "DLULUUUL", "UDDDDL", "DUUUULLU", "LLLLLLLLLDDL", "LLLLLLLLLLSLLLLLLL", "LLLUUUDD", "LDLLLDLLLL", "DLDDDLD", "LDDDDLD", "DULUUULL", "DLLUUULL", "DULUULLU", "UULUUULU", "LLLLLDDS", "ULLLLLDDDLLLL", "ULLDL", "UULLLD", "LLLDDDDLLLLL", "DULLLUUL", "LLLDLLDLLL", "DUULULLL", "UULLUL", "DDDDLLLLLLLLLLL", "ULLLLLLDDDDDDDD", "ULLLLUU", "DLUUULUL", "DULUULLL", "DDDDDDDLDD", "DLLULLLU", "ULLLLULD", "ULLDLLLD", "DULLULUL", "DLLDDDDL", "LUUUUL", "DUULD", "DLUUUULL", "DUUULLLU", "LLLLLLLLLLLLLSLLLLL", "LUUUU", "UULLLDD", "DDULLLLDD", "DLLULL", "UULLDD", "DSULL", "DLLLUULL", "UULULUUU", "ULUUL", "DUUUULUU", "DLULLULL", "UDLLLLLD", "DDLDLLLLL", "UULUL", "ULLLLLLULLL", "LLLLLLDS", "UDDDDDDDU", "LLLLLLLLLDLLL", "DLLUULLL", "LLLDDDDDDDDDDDD", "DLLLLLDDD", "DDDDDDDDDDDDDDDL", "ULUDDD", "DULLUULL", "LLLLLUD", "ULLLLLLLLLLLLLL", "LDDDLDLD", "UUUUDUU", "UDDDDDUD", "DLULLLLU", "LLLDLLDDD", "LLLLLLLLLLLLLLLLLDDD", "ULDDDDLL", "DULLUULU", "DUUUULUL", "LDLLLLLLLD", "LLDLLDDDD", "DDLLDDLLDDLL", "DLULULLL", "DULUULUL", "DULLLU", "DLLLULUL", "DUULLLUU", "LULLUU", "DUULLULL", "DLDDDDLL", "LLSLLLLLLL", "DDDDDDULLLLL", "ULLULLLLLL", "DULUU", "DULLULLU", "LDDDDLLD", "ULULLLDD", "DLLLLLUL", "DUDUDUDU", "LLLLLLDLLLLLL", "ULDDULDD", "DULLUUUL", "LLLLLDDDLLLL", "ULDULL", "LLLLLDDDLLLLL", "DLLLUUUU", "LUDDDDDD", "ULDULD", "UDLLLLDD", "ULLLDLLLL", "DUUULUUU", "ULLD", "UUUDUUUD", "ULLLLLLS", "DUULULUL", "DUULUUUL", "UDDUDDUD", "DLDDDLDL", "UUUUUUUUUDDD", "LLDDDDDDLLL", "DLDDLDDD", "LLLLLLLLLLS", "DDULLDD", "DULULLUU", "DUULULLU", "UUDDUUUU", "LLLLLLLLLLLDL", "DDDDDDLLLLLLLLLLL", "ULLLLUUD", "DLDLLLLLD", "UUUDDDU", "DULUULUU", "LLLLLLLLLLLLLDDDDDD", "ULLLULLLD", "DLLUULLU", "LULUUL", "DUUULUUL", "UUUDDUU", "LLLDLLLDLL", "DUUUUUUL", "DUULL", "LDDLLLDDL", "DDLLLLLLLLLLL", "UUUUDDUU", "DDDDDDDDLLLLLLLLL", "ULLUU", "LLLLULLD", "UUUDDDDU", "LLLLLLLLLSLL", "DDSDDSDDDDS", "DLLUUUUL", "UULUU", "DLUUULLL", "LLLLLLLLDLLLLLLL", "DULULUUU", "DLLDDDLD", "DLUUULUU", "DDDDDDLLD", "DULULU", "ULL", "ULUUU", "ULLDDLL", "DULUUULU", "DUUUUULU", "UUUUUDDU", "LLLLULL", "LLLLDDDDDDLLLL", "UUDD", "DUULUULL", "UUUUL", "DLLLDDLLL", "LLLLLLLLLLLLLDDDDD", "ULULLLD", "ULLLLLDLL", "DDDDDUDD", "LLLLLLDDDDLLL", "DLULLLLL", "DLUULULL", "ULLLLLLLLLLLDD", "DULLLUUU", "LLLDLDLLLL", "LLLLLDLLDD", "ULLLLLLDS", "DULLLLD", "LUUUUUUU", "ULLLLLLLLLLDDD", "ULLUDD", "ULLLLLLLLLLLD", "LLLLUULL", "DLULUULU", "DDDDSDDDD", "DDDUUDDD", "LLLLLLLLLLLLLSLLLL", "DLLLLUUU", "DLLULLUU", "DUUUULLL", "DUULUULU", "LLDDDLLLLL", "LLLDDDLLLLLLLL", "DDDDDDLLLDD", "DUUULULL", "DLDULU", "DLUUULLU", "DULLUUUU", "DUUDU", "LLLLLLLLLLLLSLLLLLLL", "LULULULU", "LLLLLDDLD", "DLUULLLL", "DDDDUUDD", "LLLLLLLLLLSLL", "LULLU", "DLLULLUL", "DULUUUUL", "DDSDDSDDS", "ULLLLLULLLLLDDDD", "ULULUDDD", "ULLLLLUDD", "LDLDDDL", "DUULUUUU", "LLLDDDDDDDLLL", "LLLLLLLLLLLLDDDDDDDD", "DLDDLDLD", "LLLDDDDDLLL", "DUULLUUU", "UDUDDDDD", "LUUUL", "LLLLUDDD", "DULUUUUU", "ULUDDDD", "LDLLDLLDL", "UUULUUUL", "DLDD", "LULUULUL", "LULUL", "DUDUUUUU", "DLLLLULL", "LLLLLLDDLLLLLL", "DDDUDDD", "DLLLLLLDLL", "LLLLLLLLLLLLDL", "LUUULLUU", "DDLLLLLLLLLLDD", "LLLLLLLLLSLLLLLLL", "UDDDDDUU", "LLLLDLLDDDD", "DULLULUU", "LLLLLLSS", "DULLLLUU", "LLLLDDDLLLLL", "DLUULUUU", "LLLLLLLLLLLSLLLLLLL", "UDLDLD", "DUDDDDDD", "UUUDDDLL", "LDLLDLLLLL", "LLLDDDLLLLLLL", "LDLDLLLLLL", "DLULLLUU", "LLLLSS", "LLLLLLLLSDDD", "UUUUUUUUUUUUUUU", "LLLLLLDDLLLLL", "UUDUUUU", "DLULLUUU", "LLLDLLDDDD", "SLLLLLS", "ULULULUD", "LLLLLLDDDDLL", "DDDDLLLLDDD", "LLLLUUU", "UUUDULLL", "DULULL", "LLLLLLLDLLLLL", "LLLUULLL", "LLLLLLULLLLLLLLL", "LLLLLLLLSLL", "UUUUUUUUUUDD", "LLLULLLD", "LDLDDDDL", "LLUUUULL", "ULLDDDLL", "LDLDLDLLL", "LLLLLLLLLDLLLL", "ULULDDD", "LLLLLDLDLL", "LLLLLLLLLLDLLLL", "UDDUDDU", "DLLUUL", "ULLLULLLLLLL", "DDDDDULL", "LLLLLLLLLLLLLSDD", "DLLLLUUL", "LUULU", "DLUUUUUL", "DDDULLLLL", "LLLLLLLLDDDL", "DUUUUULL", "DLUUL", "LLLLLLUUUUUUUU", "LLDDLLDDD", "ULDDDDDDDDDD", "LLLLLLDU", "DLULUULL", "DDDUL", "SLLLLLLLL", "LLUUUUUU", "DLUULLUU", "LLLLLLSLLLLLLLLL", "LLSLLLLLLLL", "UUUDDDLD", "LLLSLLLLLLLL", "LLLLSLLLLLLLLL", "DDUDDDDD", "DLLDLLLLLL", "LULLLLLLDD", "DDLLDDLLL", "LDDLLLLDL", "LLLLLLLDDDLL", "DLLUUUUU", "LLLDLLLLDL", "ULLLLDLD", "DLLLUULU", "LLLLDDDU", "LLLLLLLLLSD", "DLUUUULU", "DLLLLDDLL", "LULLLLLU", "DLLUULUL", "UULLU", "LLLLLLLLLLLSL", "LDLDLDLDLDLDLDLD", "DLLLUL", "ULUUUD", "DLDDDDDL", "ULLLDLLD", "LLLDLLLDLLLD", "DLDLDDLD", "LLLDDDDLLLLLLLL", "LLLLLDDU", "LLLLLLLLSDDDD", "LLDDLLLLD", "DLULLULU", "LLLULLLU", "LLLU", "ULLLLLDS", "LLLLLLLLDLLLLLLLL", "UULLLLD", "DLDUU", "DLULUUUU", "UUDDDDDU", "LLULUD", "LLLLLLULLLDD", "LDLLLLLDLL", "UUUULLLD", "LLLLLLLLLLLLLLLLLLD", "DDUDDU", "DUUUUD", "DLLULUUU", "DDUDDDD", "LSSL", "UULDUU", "LLDDDDLLDDDD", "UDDDDUU", "DDDDDDDDULLLL", "UUUUDDDDDDD", "LLULLLLU", "DLULLUUL", "USLLLLLDDDD", "LLLLLLLDS", "LLLLLLLLDLLLLL", "LLLLLLLLLLDLL", "ULLLLLLLDDDDD", "LLLLLLLLLLSL", "LDDDDLDL", "UUUULLL", "LLLSL", "LLLLDDDDDDDDLLLL", "ULLLLLS", "ULLLLDUL", "DDDUDDDU", "LLUDLU", "UUUDUDD", "DDDDLLLLLLLLDDDD", "DDLLLLLU", "DLLLLLLLLLLLL", "LUULLLUU", "LLULLLL", "UUULU", "UUDDUUU", "LLLDDDDLLLLLLL", "DDDLLLLLLDD", "LLLDLLLLDD", "DULLD", "DLULLL", "DUUUDUUU", "LLDLLLDDDD", "LLLLLLLLLLLLLLLLLLLDD", "LLLLLLLDDDDDDDDDD", "LDLLLLLDD", "LLUULLLL", "UUULLLD", "UUUUUDDDDDDDD", "LDLDLDLDLL", "DDDDDDUUUUU", "DDDDDDDLD", "UDLLL", "UUDDLLLL", "UUDDDDU", "LULLLULL", "DDDDDDDLU", "DLULLU", "LLLLLLLLDDLLL", "LLLLULUU", "DLULLLUL", "LLLDDLLLLD", "DLULL", "DLDLDLDLL", "LLLLLLLLLLLLLLLLLLLLLLLLLL", "DULDL", "ULLLUDDDD", "ULLLDU", "DDDLLLLDDDD", "DULUUU", "DDDUUUDD", "ULLLLDDU", "SDDDDDDS", "LLLUD", "DUULLU", "DLLULUUL", "LDDDDLLLL", "LLLLLLLUUUUUU", "LLLLLLLLLLDLLL", "LDDDDDLD", "LDLLLLLLDL", "DULLUL", "UDULLLLL", "DDUDD", "DLUULUUL", "LLLLDDDDU", "DUUUUDUU", "LLLLDDDDLLLLL", "LLLUUULL", "LLLLLLLLULLLL", "DUUDUUUU", "LDDDLDDDD", "LLLLLLLLLLLSLL", "ULDLLLLU", "DLUULULU", "LDDDLDL", "ULLLLLDU", "LUUUUULL", "LLDULL", "LLLLULLLL"]; diff --git a/src/ts/ui-misc.ts b/src/ts/ui-misc.ts index a477710..2557377 100644 --- a/src/ts/ui-misc.ts +++ b/src/ts/ui-misc.ts @@ -221,13 +221,13 @@ export module UIMisc { } } - // translate NN guess number to a percentage-based score (based on stringency configuration). + // translate NN/heuristic guess number to a percentage-based score (based on stringency configuration). // this will influence meter fill. - nnNumtoScoreAsPercent(nnNum: number): number { - if (nnNum > 0) { - return nnNum * Constants.Constants.METER_STRINGENCY_SCALE_FACTOR; + scaleGuessNumByMeterStringencyFactor(guessNum: number): number { + if (guessNum > 0) { + return guessNum * Constants.Constants.METER_STRINGENCY_SCALE_FACTOR; } else { - return nnNum; + return guessNum; } } @@ -391,7 +391,7 @@ export module UIMisc { overallScore = this.heuristicMapping[fixedpw]; } var nnNum = nni.getNeuralNetNum(fixedpw); - var nnScoreAsPercent = this.nnNumtoScoreAsPercent(nnNum); + var nnScoreAsPercent = this.scaleGuessNumByMeterStringencyFactor(nnNum); if (typeof (nnNum) !== "undefined" && nnScoreAsPercent >= 0 && isFinite(nnScoreAsPercent)) { @@ -423,7 +423,7 @@ export module UIMisc { originalOverallScore = this.heuristicMapping[j]; } var nnNumFix = nni.getNeuralNetNum(j); - var nnScoreAsPercentFix = this.nnNumtoScoreAsPercent(nnNumFix); + var nnScoreAsPercentFix = this.scaleGuessNumByMeterStringencyFactor(nnNumFix); if (typeof (nnNumFix) !== "undefined" && nnScoreAsPercentFix >= 0 && isFinite(nnScoreAsPercentFix)) { @@ -500,8 +500,6 @@ export module UIMisc { // the bar when done calculating // *false indicates we are rating a candidate concrete suggestion queryHeuristicGuessNumber(pw: string, username: string, primaryPassword: boolean): void { - // Used to make 10^{15} fill 2/3rds of the bar - var scalingFactor = 67 / 15; // We overwrite the password if they use contextual or blacklisted content // and we need the original to make the correct mappings var originalPW = pw; @@ -560,7 +558,8 @@ export module UIMisc { for (var i = 1; i < coefficients.length; i++) { overallScore += coefficients[i] * subscores[i]; } - overallScore = overallScore * scalingFactor; + overallScore = this.scaleGuessNumByMeterStringencyFactor(overallScore); + if (overallScore < (pw.length / 2)) { overallScore = pw.length / 2; } else if (overallScore > 100) { @@ -737,7 +736,7 @@ export module UIMisc { numberOfScores++; } var nnNum = nni.getNeuralNetNum(pw); - var nnScoreAsPercent = this.nnNumtoScoreAsPercent(nnNum); + var nnScoreAsPercent = this.scaleGuessNumByMeterStringencyFactor(nnNum); if (typeof (nnNum) !== "undefined" && nnScoreAsPercent >= 0 && isFinite(nnScoreAsPercent)) { numberOfScores++; From 7bba1b9a81cbd3abead0e67fbb3e97ddffed7dad Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Fri, 1 Mar 2019 12:28:59 -0500 Subject: [PATCH 11/45] Fixed bug where interface would become unusable after clicking specific-password modal (clicking 'Why?' for specific recommendations). Also fixed bug related to lack of discardpw() function in ui module (this did not seem to affect functionality, but gets rid of javascript error) --- src/PasswordMeter.js | 4 ++-- src/package.json | 1 + src/ts/ui-misc.ts | 8 +++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/PasswordMeter.js b/src/PasswordMeter.js index 6742927..533b84c 100644 --- a/src/PasswordMeter.js +++ b/src/PasswordMeter.js @@ -14,7 +14,7 @@ Array.prototype.toHumanString=function(){var t=this.length;if(0==t)return"(empty "use strict";var Config;exports.__esModule=!0,function(e){e.passwordMeterDefaultConfig={colors:{compliant:"#006600",noncompliant:"#660000"},symbols:{compliant:"✔ ",noncompliant:"❑ "},remindAgainstReuse:!0,ignoredWords:["mechanical","amazon","mturk","turk","survey","bonus","qualtrics","study","carnegie","mellon","university"],length:{active:!0,minLength:8,maxLength:0},classCount:{active:!1,minCount:1,maxCount:4},classRequire:{active:!1,upperCase:!1,lowerCase:!0,digits:!0,symbols:!1},classAllow:{active:!1,upperCase:!0,lowerCase:!0,digits:!0,symbols:!0},forbidChars:{active:!1,list:[]},repeatChars:{active:!0,limit:3},sameChars:{active:!1,limit:3,lengthException:20},usernameDifference:{active:!0,limit:1},minLogNnGuessNum:{active:!1,threshold:7,rejectionFeedback:"Not be similar to extremely common passwords"},prohibitKnownLeaked:{active:!0,smallestLength:5},blacklist:{active:!1,blacklistFile:"blacklist-cmu-compressed.txt",caseSensitive:!1,stripDigitsSymbolsFromPassword:!1,checkSubstrings:!1,checkSubstringLength:5,lengthException:20},neuralNetworkConfig:{intermediate:"basic_3M.info_and_guess_numbers.no_bloomfilter.json",file:"basic_3M.weight_arch.quantized.fixed_point1000.zigzag.nospace.json",zigzag:!0,scaleFactor:300}}}(Config=exports.Config||(exports.Config={})); },{}],6:[function(require,module,exports){ -"use strict";var Constants;exports.__esModule=!0,function(L){L.LOWERCASE_LETTERS=new RegExp("[a-z]"),L.LOWERCASE_LETTERS_GLOBAL=new RegExp("[a-z]","g"),L.UPPERCASE_LETTERS=new RegExp("[A-Z]"),L.UPPERCASE_LETTERS_GLOBAL=new RegExp("[A-Z]","g"),L.NONALPHA=new RegExp("[^A-Za-z]"),L.DIGITS=new RegExp("[0-9]"),L.DIGITS_GLOBAL=new RegExp("[0-9]","g"),L.SYMBOLS=new RegExp("[^A-Za-z0-9]"),L.SYMBOLS_GLOBAL=new RegExp("[^A-Za-z0-9]","g"),L.startASCII=32,L.endASCII=126,L.METER_STRINGENCY_SCALE_FACTOR=67/15,L.commonStructures=["LLLLLL","LLLLLLLL","LLLLLLL","DDDDDDDD","DDDDDD","LLLLL","DDDDDDD","LLLLLLDD","LLLLLLLLL","LLLL","DDDD","LLLLLLLD","LLLLLD","LLLLLLLLLL","LLLLLDD","LLLLDDDD","LLLLLLD","LLLLDD","LLLLLDDD","DDDDD","LLLDDD","LLLDDDD","DDDDDDDDD","LLLLLLLLLLL","DDDDDDL","LLLLLDDDD","LLLLDDD","LLLLLLLDD","DDDDDDDDDD","LLLLLLLLLLLL","LLLLLLDDDD","DDDDDDDDL","UUUUUUUU","LLLLLLDDD","LLDDDD","DDDDDDDDDDD","ULLLLL","LLLLLLLLDD","LLLLLLLLD","ULLLLLLL","UUUUUU","ULLLLLLD","LLLLLLLLLLLLL","ULLLLLL","LLLLLLLDDDD","LLLLLLLDDD","ULLLLLD","DDDDLLLL","LLLLLLLLLLLLLL","LLLLD","LLDDDDDD","DLLLLLLL","UUUUUUU","LLLLLLLLLD","DDLLLLLL","DDDDLL","DDDDDDLL","LDDDDDD","LLLDDDDD","ULLLLLDD","LLLLLLLLDDDD","DDDLLL","LLLLLLLLLDD","DDDDDDDL","LLLLLLLLLLLLLLL","DDDDLLL","DULLLLL","DULLLLLL","LLLDDDDDD","ULLLLD","LLLLLLLLDDD","DLLLLL","DDDDDDLLL","LLLLDLLL","LLLLDDDDDD","ULLLL","LLLDD","LDDDDDDD","LLLDLLLL","LLLLLLLLLLLLLLLL","DDLLLL","LLLDDLLL","DDDDDDDDDDDD","DLLLLLL","DDLLLLL","LLLLLDLL","LLLLLLLLLLDD","LLDDDDD","LLLLLDDDDDD","DDDLLLLL","LDDDDDDDD","DDDDDDLLLL","UUUUU","LLLLLLDL","LDDDDD","ULLLDDDD","ULLLLDDD","ULLLLLLLL","LLLLLLLLLDDD","DDDDDL","LLLLLLDDDDDD","LLLLLLLLLLDDDD","DULLLL","ULLLLDD","LLLLDDDDD","LLLLDL","LDLLLLLL","LLDLLLLL","LLLDLL","LLDLLL","LLLLLLLLLLD","LLLDLLL","LLLLLDDDDD","DDDDLLLLL","LDLDLDLD","DDDDDDDDLL","DDDDDDDDLLL","LLLLLLLLLDDDD","DDDLLLL","DDDDDDDDLLLL","DLLLLLLD","LLDDD","LDLDLD","LLLD","DDDDDDDDDL","DLLLDLLL","LDLLLL","LLLLDDDDDDDD","LLLLDLL","UUUU","ULLLLDDDD","LLLLLDL","ULLLLLLDD","DDLLLLDD","LLLLLLDDDDD","LLDDLL","DDDDLLLLLL","DDDDDLLL","DDDDDDDDDDDL","DDDDDDDDDDL","LLLDDDDDDDD","LDDDDL","LLLLDDLL","ULLL","LLLLLLLLLLLDD","LLLLLLLLLLLLLLLLL","DDDDDDLLLLL","LLLLLLLLLLLLDD","LLLLLLLLLLLD","ULLLLLDDDD","LDDDLL","ULLLLLLLLL","ULLLDD","LLLDDDDDDD","LLDDDDDDD","LLLDLLLD","DDLLLDD","DDDDDDDLL","LLDDDDDDDD","ULLLLLLLD","LLLLLDDL","DLDLDLDL","LLDDDDLL","DDDDDDDLLL","DLDLDL","ULLLLLDDD","LLLLLDDDDDDDD","UUUUUUDD","LLDLLLL","LLLLLLLLLLDDD","LDDDDDDL","DDDDDLL","ULLLD","LLLLDDDDDDD","LLDDLLLL","LLLDDDLL","DDDDDDLLLLLL","DLLLLD","DLLLL","LLLLLLLLLLLLLLLLLL","LLLDDLL","ULLLLLLLDD","LLDDLLDD","UUUUUUUUU","LLLLLLLLLLLDDDD","DULLL","ULLLDDD","DDLLLLLLL","LLL","UUUUDDDD","DDLLDD","DDDLLLLLL","DDDDDDDDLLLLL","LLLDDL","DLLLLLD","DDDDDDDLLLL","LDLLLLL","UUUDDDD","LLLLLLLDDDDDD","DLLLLLLLL","LLLLLLLLLLLDDD","LLLLLLLLLLLLLDD","LLLLLLDDDDDDDD","UUUUUD","UUUUDD","LDDLLLLL","LLLLDLLLL","DDDDLLLLLLL","LLLLLDDDDDDD","DDDDL","UUUDDD","LLLLLLLLLLLLD","UUDDDD","UUUUUUUD","LLLLLLLLLLLLDDDD","LDLDLDLDLD","LDDD","LLDLLD","DDDDDDU","LLLLDDL","LLLDDDDL","UUUUUDD","LLLLLLLDDDDD","DDLLLLLDD","UDDDDDD","LLDD","LDDDD","LLDDDLL","ULLLULLL","DDDDLLLLLLLL","LDLLLDLL","DDDDDLLLL","LDDLLL","LLLLLDLD","ULLLLLLDDD","ULLLLU","DDLLL","LLDDLLL","ULLLLLLDDDD","LDDLDD","LDLLDL","ULLLLLLLLLL","LLDLLLDL","","LLLLDLLD","LLDLLDLL","LLLDL","LLDLLLLD","ULDDDDDD","ULLULL","LLLDDDLLL","UUUUUDDD","LLDLL","UUUUUUD","LLLLDDDL","LLLLLLLLLLLLLD","LLLLLLLLDDDDDD","UUUUUUUUUU","LDLLLLDL","LLLLDLDL","LDLLDLLL","LLLLLLLLLLLLLLLLLLL","DLDLLLLL","DDDLLLDDD","DDDDDLLLLL","LLLDDDL","DLLLLDLL","LLLDLLDL","LLLLLLLLLLLLDDD","LDDDDDDDDD","ULLLLLLLLD","LDLDLLLL","LLLLLLLLLLLLLLDD","DDLLLLLLLL","LLDLDLLL","DLLLLLDL","DDDDDDDDU","DDDDDDDDLLLLLL","LDDDDDDDDDD","LDLLLLLD","DDLLLLLLDD","LLDDDL","LLLDLDLL","DLLL","ULLDDDD","DDLLDLLL","DLLLLLLLLL","DLLDLLLL","DDDLL","LLLLLLDDDDDDD","DDD","LLLLLLLDDDDDDDD","LLLDLD","DDLLLLLD","DLLDLL","LLLLLLDLL","UUDDDDDD","DDDDDDDDDLLL","LLDDDLLL","ULLLLLLLLDD","ULULLL","DDLLDDLL","DLLLLLDD","LDLLL","DDDDDDDLLLLL","DDLDDLDDL","ULULUL","ULLLUL","LDLLLD","UDDDDDDDD","LLLLLDLLL","LDLDLL","ULLLLULL","DDDDDDDDDDDDD","ULLLLLLLDDDD","UUUUDDD","LLLLLLLLLLLLLLLLLLLL","DDDDDDDDDDDDDD","DDDLDDD","DDLDDL","DLLLDL","ULLLUU","DLDLDLDLDL","ULLLLLLLDDD","ULLDDD","LLLLLLDLLL","DDDLLLLLLL","DDDDDDDDDDLL","DDLLLDDDD","UDDDDDDD","ULUULL","ULULLU","ULLLLLLLLLD","ULUULU","DDDDDDDDDLL","LLLLLDLLLL","DDDDDDDDDDDLLLL","ULUUUL","ULUUUU","ULLUUU","ULLULU","ULLUUL","LLDLDL","LLLLLLLDL","LLLLLLLS","LLDL","LLLLLLLLLLLLLLD","LDDDDDDDDL","LDDDLLL","LLLLLLS","ULULUU","LDDDDDDDDDDD","LLLLLLLLLLLLLDDD","LLLLLLLLLDDDDDD","DDDDDDLLLLLLL","DDDDDDDDDDLLL","LLLDDLLD","DDDLLDDD","LDDLDDLDD","LLLDLLLLL","ULLLLLLLLLLL","LLLLDDLLL","DDLLLD","LLLDDDDLLL","DDDDDDDDDDDLLL","LDLDLDL","LLLLLLLLDDDDD","LLLLSLLL","LLLLLLLLDDDDDDDD","DLLLDD","LLLLDLD","DDDDDDDDDDDDDDDD","DLDLLL","UUUUUDDDD","DDDDDDDDDDLLLL","LLLLDLLLLL","DLLLD","DDDDDDDU","DDDDDDUU","DDDLLLDD","LLDDDDL","DLLLLLLLD","LLLSLLL","LDDLLLL","ULLLDDDDDD","LLLLLLLLLLLLLDDDD","DDLLLLD","ULLULLLL","LLLDDLLLL","LLLLDDLLLL","DDDLLLLDDD","LDLL","LDDDDDDDL","LLLDLLLLLL","DDDDDDDDDLLLL","LDDDLLDD","LDDDLLLL","LLDDLLLD","DDDDDDDDDDDLL","LLLDLLDD","DDLL","DDDDUU","DDLDDLDD","DDDDDDLLLLLLLL","DDLDDDD","DDDDLLDD","LLLLLS","ULLDDDDDD","LLDLLDL","LDLDLDLL","LLLLDLDD","LDLLLLLLL","DDDLLLD","LLDLLLDD","ULLDDDDD","ULLLLLLU","ULDDDD","LLLDDLLLDD","UUUUUUUDD","LLLLLLLDDDDDDD","UUUDDDDD","LLDLLLD","UUDDDDD","LDLDL","UUUUUUUUUUU","LDLLLLDD","LLDLLLLLL","LLLDDLDL","DLLLDLL","DLLLLDD","LLLLLSDD","DDDDULLL","DDLLDDDD","LLLLLLLDLL","DLLLLDL","LLLLLLLLDL","LDLLLDL","DLDLDLD","LLDLDD","LLLDDDDDDDDD","ULLLLDDDDDD","LDDDLDDD","DDDDDDDDDDDDDDD","DDDDDDDDDDDDL","ULLULLL","LDLDLDLDLDLD","LLLDLLD","DDDDDDDLLLLLL","LDDDDDL","DDDLLLLLLLLL","LLDDL","LLLLLLDDL","LDLLDLL","LDLLDLDL","LLLLLLLLLLLLLLLDD","UULLLLLL","ULLLLLLLLLDD","LDDDDLL","LDLLDLLD","DDDLDD","DDLLLLLLLDD","LLLLLLLLS","UUUUUUDDDD","LLLLDDLD","UDDDDD","LLDDLDLL","DDDDDDDDLLLLLLL","UUUDDDDDD","DDDDLDDDD","LLDDLD","LLLLLDDLLL","DDLLLDDD","UUUUUUDDD","LLLLLDDLL","LLLLDDDDDDDDDD","DDDLLLLLLLL","LLLLLLLLLDDDDD","LDLLDD","LLLLLLLLLLLLLLLLLLLLL","LLLLLLLLLLLLLLLD","LLLSLLLL","DDDDLD","DDLDDD","DDDDUUUU","DLDLL","LDLLLLD","DLDLLLDL","LLLLSLLLL","LDLDLLDL","DDLDLLLL","DDDDDDDDDDDLLLLL","LLLLLLLLLLDDDDDD","UUUUUUUUUUUU","LLLDLDL","LLLLDDDDDDDDD","DDDDDLLLLLL","DDULLLLL","ULLLULL","LLLLLLLLLLLLLLDDDD","DLLDLLDL","LLLDLDLD","LLLDDDDDDDDDD","DDDDLLLLDDDD","LLLLSL","LDLDLLL","DLLLLLLLLD","LDLLLDLD","DDDDLDD","ULDDDLL","LLDLLLLLLL","LLLLLLSDD","DLDLLLL","ULLLLLLLLDDD","LLDLDLL","DDDDDDS","DDLLLLLLLLL","LDLLLDDL","ULLLLDLL","DDLLLDLL","DDLLDL","LLLLLSLLL","DLLLDDLL","LDLDLDLDL","DLLLDLDL","DLLDLLL","DLLDL","DLDLDLLL","LLDDLLD","DDDLLLLLDDD","DDSDDSDDDD","LLDDLLDL","DLLDLLLD","DLLLDDD","LLDLLDDL","LLLLLU","DLLDLDLL","LDDLDL","LDDLLD","LLDLLDLD","DDLLDDD","DDDDLLLD","DLLDDL","ULLLLLDDDDDD","DDDLDDDL","DDLLD","LLLLLDLLLLL","LLLDDLDD","LLDLDLLD","LDDDDLLL","DLLDDLLL","LLLLDDDDDDDDDDD","DLDLLDLL","LLDDDDDDDDD","DDDDDDUUU","DLDDLLLL","DDDLLD","LDDLLLLD","LDLLLLLLLL","DDDDUUU","LLDLDLDL","DLLLLDLD","DDLLLLDDDD","ULLLLDDDDD","LUULDDL","ULLLDDDDD","LDDLLLDL","ULLLLLLLLDDDD","DDLLLLDL","DLLLLLLLLLL","ULLLLLU","LLLLLSLL","DLLLLDDL","LDLDLLLD","DLDLLLLD","UUUDD","LDLDDLLL","LLLLLLDLLLL","LDLLD","DDDDDDUL","LDLD","DLLLLDDD","LDLLDDLL","UUUUD","LDDLLDLL","LLLLLLLLDDDDDDD","LLLDLDDL","DLLLDLLD","DDDDDDDDDDLLLLL","LLLLLDDDDDDDDD","DDDDDDDDUU","LLLLLDDDDDDDDDD","ULDDDDDDDD","UUULLL","LLLLLSLLLLL","LLLLLSLLLL","DLDLLD","LLLSDDDD","LLDDDDDDLL","DLLLDDDD","DLDLD","ULLLLLLLLLLLL","LLLLLLULLLLL","LLDLDDLL","LLLLLLLLLLLLLLDDD","DDDDLLD","LLLDDDLD","ULLLLULLLL","LDDLL","DDLLLDDL","DDDLLLLD","DDDL","ULDDDDDDD","LLLLLLLU","DDDLLDD","LLLLLLLLLLDDDDD","DDLDD","LLLLLLLLLLLLLLLLLLLLLL","UDLLLLLL","LLLLSDD","LDDLDLLL","DLDDLL","LLLLSLLLLL","LLLLSLLLLLL","LLDDDDDDDDDD","DLDDDD","ULLLDLLL","LLLDDDDLL","DDDDLDDD","DLDLDLDLDLDL","ULLLLLUL","DDLDLL","UUULLLLL","UDDDDDDL","LLLLLLDDDDDDDDD","LLLLLLLLLS","LLSLLL","LLDLD","DDDLDDDD","LLLLLLLLLLLLLLLLDD","LLLDDLD","LLLLLLSD","UUUUUUUUDD","LDLDDD","LLDLLDD","DDDDLLLDDDD","DDLLLLLLLLDD","LLLLDDDDLLLL","DDDDDU","UUUDDDUU","DDDDDDDDLLLLLLLL","LLLLDLLLLD","UUUUUUUUD","LLLLSDDD","LLLLLDDDDDDDDDDD","DDDLLLLLLDDD","DLLDDD","DLLDLD","LLDDLLLLL","UDDDDDDU","LSLLLL","LLLLLLULLLLLL","DDDDDDDDDLLLLL","LLLLLLDDLL","DDDDDDDDS","LLLLLSDDD","LDDLLDDL","ULLULLDD","DLLLLLLDD","ULLLLULLL","LLDLLDDD","UULLLL","ULLLULLLL","LLLLLLSLLL","LLLDDLLLLL","UUDDDDDDDD","LLLLLLU","DDDDDDLLLLLLLLL","ULLLDDDDDDDD","DDLDL","DLLDD","LDLDDL","LDDLDDL","LLLLLLDDDDDDDDDD","LLLLLLSLLLLLL","DDDLD","DDDDDDLD","DDLLLLLDDDD","LDDLDDDD","UUDDDDDDD","DUUUUUUU","LDDL","DDDUUU","ULULLLLL","LDLDLDD","LLLDDDDDDDDDDD","DLLDDLLD","UUUUUUUDDD","LLLDLDD","DDDDLLLDD","LLLLLDDDL","ULLLLLDL","ULULULUL","LLLLLLLDDL","LDDLLLDD","ULLLLLLLLLLD","DDDULLLL","LLLSLL","LLLLLLSL","LLLDDDLLLDDD","LLLDDDLLLL","LLLLDDDLLL","LDLLLDDD","LLLSLLLLL","LLLLDDDDL","LLLLDDDLL","LDDDL","LLLLLLULLLLLLL","DDDDDDDDDDLLLLLL","LLLLLLLSDD","UDDDDU","LLLDLDDD","LLLLLSLLLLLL","LLDDLDD","DLDDL","LDLLLDD","LLLLLLDDLLL","DDLDLLL","DDDDDDDDDDDU","LLDDLDL","DLLDLLD","LDDDDLDDDD","LLLLLLSLLLLL","DDDDDDDDDLLLLLL","UUUUUUUDDDD","ULDDDDD","LLLDLLLDDD","DDLLDDL","ULLLLLDDDDD","LLDDDLLD","UUUULLLL","ULLLLLUU","DDDDDDDLLLLLLL","LLLLDDDLLLL","DLDDLD","DDDDLLDDDD","DDSDDSDD","ULLDLLLL","LDDLDDLD","DDDDDDDDUUU","DLLDDLL","DDDDDDDDDDDDDDDDDD","LLLLLLLLLLLLLLLDDD","ULLLU","LLLLLLDLD","UUDDDDUU","LLLLLDDDDL","LLLLLLLLLLLLLLLDDDD","LLLSDD","LLLLLLSLLLL","LLLLLLLLLDDDDDDD","LSLLLLL","LDDDLD","ULLLLDDDDDDDD","DDDDLLLLLDDDD","DDDDDDDDDU","LLLLSDDDD","LDDLDDLL","ULLLLUDD","LDLLDDDD","ULLULLLD","LLLDDDDDDLLL","LLDDDDDL","ULLDDLLL","DDDLDL","LLLLLSL","LDLLDLD","LDLLDLDD","LDLDLLD","DLDLDD","DDDDLLLLLLLLL","LLLLDDDDLL","LLLDLLLLD","DDLLDLL","DDLLLLLLDDDD","ULLDD","UUUDDDDDDDD","ULULLLL","DDLDDLLL","LDLDLLDD","ULLLULLD","DLLDLLDLL","DDUUUUUU","LDDLLDD","ULULDDDD","LLLLLLLLDLL","LLLLSLL","LLLLDLLLLLL","DDLLLLLLLLLL","LLDLLDLLD","LLLLLSDDDD","LLLLLLLLLDL","DLDLDLDLD","LLLLLSD","LLLLLDDLLLL","DDDDDDDDDDDDLLL","DLDL","LLLLDDLLLLL","LLLLLLLDLLL","LLSLLLLL","DDLLLLLLD","DDLDDDDD","LDDLLLLLL","LLDDDDLLL","DLDDDL","LLLLLDDLLLLL","LLLLLLLLLLLLLLLLLDD","LLLLLLLLLLLDDDDD","LLLLLLLSLLLLLL","LDDLLDL","LLLLLLUU","DULLLLLD","UUUUDDDDDD","DLLD","UUDDD","LLLLLLLDLLLL","LLLLLLLLLDDDDDDDD","LDLLDDL","DDULLLL","ULLLDL","DLLLDLLLDLLL","LLLLDDDDLLL","LDLDLDDD","LLDLDDDD","DLDDD","DDDDDDDDDDU","LLUULL","LLLLLLSDDD","UULLDDDD","LLLLUU","LDLDDLDL","DDDLLLDL","LLLLLLLLSDD","DDDLDLLL","UULLLLL","ULLLLLLLLLLDDDD","DDDDDDDDUL","ULLLDDDLLLL","LLLSDDD","DDLDDLL","DDDSDDD","LLLULL","DDDDUL","DDDDDLLLLLLL","UUUUDUUU","DLDLDLL","LDLDDLDD","LLLLLLLLLLLDDDDDD","DDDDULLLL","ULDLLLLL","DDLDLD","DDDDDDLLLLLLLLLL","DDDDDLDD","DDDLLLLLDD","LDLDLDDL","ULDLDD","LLLLLLDDDL","DLLLLDLLL","LLLUUU","LLLLLDDDLL","DDLLDLLD","DLLLDDDL","DDDDDDDDDDDDLLLL","DLLLDDL","LLDDLDDL","ULLLULLLLL","DLDLLLD","ULLDLL","DLDLLLDD","LSLLLLLL","DLLDDDLL","DLLLLDLLLL","DDDLLDLL","ULLDDDDDDD","LLLLLLLSD","LLLLUL","DLLDLLDD","LLLSLLLLLL","UDLLLL","LLLLLLSLLLLLLL","UUULLLDD","DDLDDLD","LLLLLLLLLLLLLLLLD","DDDDDDDS","LULLLL","LLLLLLSDDDD","DDUUUUU","UDDDDDDDDD","LLSLLLL","DDDDLLLLDD","LLLLLLLSLLLLL","DDDLLLLDD","LDDLLLD","LLLLDLLLD","LLLLULLL","DDULLL","DDSULL","LDDDLLLD","LDDDDLDD","DDDDDDDDDDDDLL","LLLLLLLULLLLL","ULLLLLLLLLDDDD","UUUUUDUU","DDDDDLD","ULLDDDDDDDD","LLLLLLLDDDDDDDDD","ULLLLULLLLL","DDLLLDL","LLLLLSLLLLLLL","UUUDUUUU","DDUUUU","DLLLLLLLLLLL","LDDLD","LLLLLLULLLL","LLDLDLDD","UULLLLDD","ULUL","ULLLLUUU","ULLLDDDDDDD","LDDDLDLL","DLDDLDLL","LDLDDDDD","LLDDDDDDL","ULLLLLUD","DDDDLLLLLLDDDD","UULLLDDD","ULLLLLDDDDDDDD","DLLLDLLLL","LDDLLDLD","DLLLLLLDL","LLDDLLLLLL","DLDDDLLL","LLLLLULL","DDDDDDDUU","DDDLLLDDDLLL","UUDDDUU","LDDLDLDL","LDDDDDLL","DDDDDDDDDDDDDDDDDDDD","UULLUU","LLDDDLDD","UUU","LULULU","UUUDLLLL","UDDDUU","DLLLDDLD","DDLLDLDL","DDDUUUUU","LDLLDDDL","DLDDDDDD","SLLLLL","LLLDLLLLLLL","UDDDDDDDDL","LDLLDDLD","UULLL","LLDDDLDL","LLLLLDLLD","ULLLDLL","DDLDDLDDDDL","LLLLU","UUUUUUDU","ULLLLLULLLL","DDLDDDDL","ULLLLLULLLLL","DLLDDLDL","DLLLLLLLLLD","LLLLLLLSLLLL","UDDDDDDDDDD","ULLLLLULLL","LDDLLDDD","DLLLDLD","DDDDDUU","DDLDDLDDDD","UUUUUUUUUD","DLDLLDL","LLDDDDDDDDLL","LLDLLLLDL","LLLLLLLLLLLLLLLLLLLLLLL","DLLDDLD","DLDDLLL","DLDLDDLL","DDDDULL","LDDDLLDDD","LLDDLDLD","LLLLLLLLLLLLLLLLDDDD","DDLLLLDDD","LDLDDDLL","LLLDDDDLLLL","DLLDLDL","DLDLDLLD","LDLLLLDLL","LLULLLLL","UUUUULLL","UUUUUUUUDDDD","ULLLLDDDDDDD","LDDDDDDDDDL","UDUDUD","DUUUUU","LLLLSLLLLLLL","UDDDD","DLDDLLDL","DDLDLDLL","ULLULULL","DDDLDDL","DLLDLDLD","LLDLDDL","LLULLL","UDLDLDLD","UUULLLL","LLLLLLLULLLLLL","DLDDLLLD","ULLLLDL","LLDDDDDDDDDDD","LLDLDDLD","LLLLLLSLL","DDLDLLDL","DDLLLDLD","DDL","LLDLDLD","LDDDDDDDDDDL","LDDLDLLD","DLLDDDD","DDLDLLLD","ULLDLLL","DLLLDLDD","LDLDD","UDDDDDDDL","LLLLLLDDLLLL","DDDDDUUU","LDDLLLLLLL","UDUDUDUD","DDDLDLL","DLDLLDDL","LLLLLLSLLLLLLLL","DLLDLDDL","ULLULLD","LLLLDLLDD","LDDLDLDD","ULLLLLLLLLLDD","ULLLLLLDDDDDD","ULLLLLLLLLLLLL","ULLSDD","LDDDLDD","UDLLLLL","DLDDDDD","LLLLLLLLLLDDDDDDDD","LUUUUU","DDU","LULULL","LLLLLLLLLLLLLLLLLLLLLLLL","LLLLLLLSLLLLLLL","LDLDDLLD","LLLLLLLSLL","DLDLLDLD","DLDLLLLLL","UUUUUUUUUDD","LDDDLLDL","UUUUUUUUUUUUU","DDUUU","LDLLLLLLD","LDLDDDD","DDDDLLDL","DSDSDDD","DLDDLLD","LLLDDDLLLD","LDDLDDD","LLLLLLLDLD","LLULUL","LLDDLDDD","ULLLLLULL","LLLLDDLLLLDD","LDLDDLL","LLLDDLLDD","DLDLDLDD","LLLLLLLLLSDD","LLDDDDDLL","DDDDDLLD","LLLLLDLDL","LLLLLLDLLLLL","UUDUUUUU","LLLLLLLLSLLLLLL","LLLLLLUUUUUU","SSSSSS","LLLLLLLLLLLLDDDDDD","DDULL","LLLLLLLLLLSLLLLL","DDDDDS","LLDLDDD","DLLLLLDLL","ULLLLUD","DUUUU","LLLLLLLLSL","DLDDLDDL","LLLLLLLLLLLSLLLL","LLLLLDDDLLL","ULDLLL","ULLLLLLULLLL","UUUDDDDDDD","ULLLULLU","UULLLU","ULLLULUL","LDDLDLL","DUUUUUU","DDDDLDDDDL","LLLLLLLLSLLLLL","DDDLLDL","LLLLLLLLLDLL","ULLLLLLDDDDD","LLLLLLLSLLL","LLLLLLLLLSLLL","UDUUUUUU","LDLDLLLLL","DDDDDDUUUU","DULLLULL","DDDDDDULLL","LLDLLLLLLLL","ULLULLUL","LLDDLLLDD","LLLLUD","UUUD","ULLDDULL","ULLLLLLLLLDDD","LLLLLLDDDDL","DDDDDDDLLLLLLLL","UULLLLLD","LDLLDLLLL","LLLULLLL","LLDLLLLDLL","DDLDDLDDLDDL","LLLLLSLLLLLLLL","LDLLDDD","ULULU","LULLUL","LLLULU","LLLLLLLLLLLSLLLLL","DDDDDDLU","UULUUL","LLDDLLDDLLDD","LLLLLLLSL","DDLDDLDL","LLLLLLUD","UUUUUULL","UDDDUDDD","LLLDDDLLLLLL","ULLLUD","ULLLDDLL","LDDDDDDDDDDDD","UDDDDDDDDDDD","ULULL","ULLLLDDL","DDLLDDDL","DDDDLDDL","SLLLLLL","LLLLLLLDDLL","DDDDLLLLLDD","ULULULU","SLLLLLLL","LLLLDLLDL","UUDDUU","DDLLLLLLLLLDD","UUUULU","UUUDDUUU","UUULUU","LLUULU","DLLDLLLLL","LLUUUU","ULLULULU","ULUUUULL","DDLDDDLL","LLDLLLLLD","ULLLDULL","DDDDLLLLLLLLLL","ULLULLLU","LLLLLLLLLLSLLLL","DULLLLLLL","ULLUDDDD","LLLLLDDDDLLLLL","LLLLDDDDDDDDDDDD","DDDDU","DDDULL","DDULLLDD","LLLLLLLLSLLLL","LLDLDDDL","LLLDLDLLL","LLLLLLLSDDDD","LLDDDLD","UUUUDDDDD","DSDSDSDDD","DDDDULLLLL","DDLDDLLD","LLLLLLLULLLLLLL","ULLULLLLL","ULULLLUL","LDLLLLLLLLL","UUUULL","LLLDLLDLL","LDLLLLLDL","ULULULLL","DDDLLLLLLLDDD","DDUUUDD","LLLLLLLLULLLLL","LDDLDDLDDLDD","ULLUULLU","DLLLLLLU","ULULLLLU","LDDLDLD","LLLUDD","UULULL","LLLLLLLLLLLLLLLLDDD","UUUUUDDDDDD","LLDLLLDLL","DDDLDDLL","DDDUUUU","LDDDLLD","LLLLLLULLLLLLLL","DDDDDDULL","LLLLLLLLSLLL","UUUUUUUUDDD","LDLDDLD","ULLLUULL","ULULLULL","LLLLLLLLDLLL","LLLLLLLLLLSLLL","LLLLLLLDDLLL","DDDDDDDDDDS","LLLLLLLLLLLLDDDDD","UDDDDDDDDU","LLLLLLLLLLDL","ULLLLULU","LLUUUL","DUUUUUUD","LUULUU","LLLLLLLLLLLSLLL","ULULUUUL","LLLLLLLLLLLLSLLL","LDDDDDDLL","UUULLLDDD","ULLLULLLLLL","DDLLDDLD","ULULLULU","LLLLLLLSDDD","LLLLLLLLLSLLLL","DDLLDLD","ULLUL","LLLLLLLLLLLLLLLLLLDD","LLLLLLLLLSLLLLLL","DUDLUDUL","DLLLLDDDD","DDLDLLDD","UUULUL","LLLLLLLLDDL","LLLLLLLLLSLLLLL","ULLUUUUU","SSSSS","UULLLULL","DLDLLDDD","ULLULLUU","ULULUULU","LULUUU","LLLLLLLLSLLLLLLL","LLLLLLLSLLLLLLLL","LLLLLUUU","LLLDDLLLLLL","ULLLLUL","DDUUUUDD","DDLDDDL","LDDLDDLDDDD","LLLLUUUU","UULLLLLU","LLLULLL","ULULLLUU","ULLUULLL","DDDDDDDDDDDDDDL","LUULLU","LLLDLLLLLD","LLDDLLDDLL","LDDLDDLDDL","LLDDDLLLL","LLLDLLLDL","LUUULL","LUULLL","DLLDLDD","UULLUUUL","ULULLUUL","LDLDLDLDLDL","DDLDLDDL","ULUUULLL","UULLULLL","ULLLUUUU","DDUU","LLLDDDLLLLL","LLLLLLUUUUUUU","UUUDUUU","LLULUU","LLLLLLLLLLLSDD","ULLLLUUL","ULUULULU","LLLUUL","LLLLLDLLLLLL","LULLLLLL","UUDUUU","DDDDLDLL","LLSLLLLLL","LLLLDDDLLLLDDD","UUUULULL","UUULLUUL","LLLLLLLLLLLLSLLLLL","LULLL","DDDLLLDDDD","DDDDDDDDUUUU","LLLLDLDLL","LSLLL","DLDLDDDL","LDDDLLLLL","LDDDDDDDDDDDL","UULLLLUL","UULUUU","UUULLLLU","UULULU","ULUULULL","UUUUULUU","UUUDU","ULUULUUL","UUULLULL","ULLUUULU","ULULULLU","UULLLLUU","UUDUU","DULULLLL","UULLLUUU","DDDDLDL","ULLLULUU","UUULLLLD","LLLLLLLDLLLLLL","LLLLLLLLDLLLLLL","DDDLDLLD","DDLLLLLLLD","LLLLLLLLSLLLLLLLL","LLDLLDLLL","UUULULLL","LLLLLLDDDLLL","LLLDLLLDD","UUULUULL","ULLUULUL","UULUUULL","UULLULLU","LSLLLLLLL","LLLLSLLLLLLLL","DLLLLLDLLL","LDDDLLDDLLL","LLLSLLLLLLL","LDLLLDLLL","DLLLDLLLLL","LLLLSD","LLLLLDDDDLL","LLDDDLLDDD","LLLLLLDLDL","ULDDLLLL","LLLLDDLLLLLL","LLDLLLLLDL","UDDUDD","DDLLDLDD","LLLLLLDDS","UUUDDLLL","ULUULUUU","DLLDDDDD","DDUUDD","UULLULUU","DDLUL","DDDDDDDDDDDLLLLLL","LUUULU","DULLU","DULUL","LLLLLLLLDLLLL","LLLDDLLLD","DDDDDDDDULLL","DDDULLL","DDDDDDUD","UULULLLL","ULLLLLLLU","ULLULUUL","ULLUUULL","LLLUUD","LLLLLLDLLD","LLLLLLDDDLL","UUUUUUUUUUUUUU","LDDDLDDL","UDDLLLLL","UULLLUUL","DDDLLDDDD","DDUUL","ULULDD","UULULULU","UDUUU","DDLLLLLLLDDDD","ULUUUUUL","DLDDLLDD","LSLLDDDD","DDDDDDDDDDDDDDDDD","LLULL","DULLULLL","LULLLU","LLLLLLLLLLLSLLLLLL","LLLLLLLULLLL","UUUUUL","ULDDLL","DLLLLLLLDD","UULLUULU","UDDDUUDD","LLLLLLLLULLLLLL","DLDDLDL","UUUUUUDDDDDD","DDLLU","DDDLLLLLLLLLL","ULLLLSDD","LLLLLLLLU","LLLLLLLLLLLLLLLLLD","DDDDDDDDDDDS","UUULLULU","LLLLDLLLLLLL","DDDLLDDL","DDDDDDULLLL","LLDLLLDLLL","DLDLDDD","LLLLLLLLSD","UUUUUUUL","DDDDDLDL","LLLUL","UUUUUULU","DULLLLUL","LLLLLUDD","LSLLLLLLLL","DLDLLDD","ULLLLLDDDDDDD","UUULULUL","LLUUL","UULULLUL","LLUUUD","UUUULUUL","ULLDULLL","ULDDDDDDDDD","DDLLDDLLDD","ULLUULUU","ULUULLUL","ULUUULLU","UUULUUUU","UUUUDU","DDDDLLLLD","UULUUUUU","ULULULUU","DLDLDDL","LLLLLLULLLLDD","ULULULDD","DDDLLLLLLLLDDD","DDUULLLL","ULLLULLLDD","LLLLLDLLLLLD","ULLLUUUL","DDLDLDD","ULUULLUU","DLLUL","UUULLLUU","DDDDSDD","DDLLDDDDDD","DDDDDDLLLLDD","LLLLLLLLLLSLLLLLL","UUULLLUL","DDDDDDDUL","UUULULUU","LLLLLDDDDLLL","DLLUU","DLLLLLLLLLLD","ULLLLLSD","LLLLLLLLLLLLSLLLL","UDDDDUDD","LLLLLLLLULLLLLLL","DDLDLLD","DDDDLLLDDD","UUUDUU","ULULUULL","DDDUU","LLLLLLLDLLLLLLL","LUULUL","UULLUUUU","DDDDDDLLLLLDD","DLLULLLL","DDLDLDLD","DDDLDDLD","ULLLULDD","ULDLLLL","DDDDUDDD","LDDLDDDL","DDLDLDL","ULLLLLSDD","UDDDDDU","ULULLUUU","LDLDLDLDLDLDLD","LLLLLLLLLLLLSDD","DLLLDLLLD","DLDDDLDD","ULUUUULU","UUUUDDDDDDDD","UUUUUDDDDD","DUUULLLL","ULLULUUU","LDLLLLDLLL","LLLLLLLLLLLDDDDDDDD","ULLLLULLLLLL","LLULU","DLUULLUL","LLLLLLULLLLLDD","UUUUULUL","ULLLUDDD","LLLLDLDLLL","DDUDDUDD","DULLLULU","DLLLLLDDDD","LLLLLDDDDLLLL","UUULL","DLLDDLDD","UUULUULU","DDDDDDDDDDDDDL","ULLLUULU","UULUULLU","DUULLUUL","ULLLLLLLDDDDDD","ULUULLLU","DLLULULL","LUULL","DLDDDLLD","LLLLLLLLLLSDD","DDLU","DULULUUL","DLDDLDD","UULLULUL","DDLDDDLD","LLLLDDDDUU","DLULU","ULUUUUUU","LLLLLLLLDDLL","LLLLDLLLDL","DDUL","ULULUUUU","ULUULLLL","UDDUDDUDD","LLDDDDLD","LLULLU","UDUUUU","UUUULLUU","LLLLLLDDDDLLLLLL","DDDLDLDL","ULUUULUL","UUULULLU","UUDDUUDD","ULLLLLDDS","DLLDDDL","DDDDDDLLLLLLDD","UULUULLL","UULULULL","DLLLULLU","ULULLLLD","DULLLLLU","LLDLDLLLL","DLDDDDL","ULULUD","UUUULLLU","UUUULLUL","UUULLUUU","DUUULLUL","DUUULULU","UULLUULL","DDDDDDLDD","DDDDUUUUU","DDDLLLLLD","LLLLLLUL","DLLLLLLLDL","LLDLLLLDD","DULULLLU","DDDDLLDDD","UULUUUUL","DULULULU","DDDDLLLLLLLDDDD","LLDLLLLLLD","LLLLLDLDD","UULULLLU","LLLDDDDLLLLLL","LLLLLLDDDDDDDDDDD","DLDLDDDD","LLLLLLLLLLLLLLLLLDDDD","DDDDLDLD","LLDDDDLLLL","LLLLLLLDDDL","DDLD","LLLUU","DDDLDLD","DDULU","DUULLLUL","UUUUULLU","DLLDLDDD","DDLDLDDD","ULLUUUUL","DLLUUULU","ULLU","DUULLLLL","UULUULUL","UULULLUU","LLLLDU","DLLUULUU","DDDDDDDDDLLLLLLL","DLLLLLUU","ULUUULUU","DDDDDDDUUU","ULDDD","LLUUU","DLDLDLDLDLD","DDLLLDDLL","LLDDDDDDDLL","DDDLLDLD","ULLDULLD","DLLLULLL","UULLLULU","DULULULL","UULUULUU","DDLLLLLDDD","DULULLUL","UDDUDDDD","UUUULULU","DDDDLLLLLLDD","DUULU","DLLLLULU","DDULLLLLL","DLLLULUU","DDDUDDDD","LLLLLDLLDL","UUDDDDLL","DLDLLLLLLL","DDLLLDDLLL","LLLLLSLLLLLLLLL","LLLLLLLLLLLLSLLLLLL","ULLLUDD","LLLDULLL","DUUUL","DDDDDDSS","UULULUUL","LLLDDDDDDDDLLL","DUULLLLU","LLDLLDLLLL","DUULLULU","LLLLLUU","DDLDDDDDD","DUUULLUU","DDLUU","LLLLDLLDLL","DLDDDLL","UUUULUUU","LLDLDLLLLL","DLLLU","LLLLLLLDLLLLLLLL","LLLLLDLLLD","LLULLD","LDLLLLDDL","DDDLDLDD","UUULLU","DDDDDDDDDS","DUULULUU","UDDUDDD","ULLLUUU","DLULUUUL","UDDDDL","DUUUULLU","LLLLLLLLLDDL","LLLLLLLLLLSLLLLLLL","LLLUUUDD","LDLLLDLLLL","DLDDDLD","LDDDDLD","DULUUULL","DLLUUULL","DULUULLU","UULUUULU","LLLLLDDS","ULLLLLDDDLLLL","ULLDL","UULLLD","LLLDDDDLLLLL","DULLLUUL","LLLDLLDLLL","DUULULLL","UULLUL","DDDDLLLLLLLLLLL","ULLLLLLDDDDDDDD","ULLLLUU","DLUUULUL","DULUULLL","DDDDDDDLDD","DLLULLLU","ULLLLULD","ULLDLLLD","DULLULUL","DLLDDDDL","LUUUUL","DUULD","DLUUUULL","DUUULLLU","LLLLLLLLLLLLLSLLLLL","LUUUU","UULLLDD","DDULLLLDD","DLLULL","UULLDD","DSULL","DLLLUULL","UULULUUU","ULUUL","DUUUULUU","DLULLULL","UDLLLLLD","DDLDLLLLL","UULUL","ULLLLLLULLL","LLLLLLDS","UDDDDDDDU","LLLLLLLLLDLLL","DLLUULLL","LLLDDDDDDDDDDDD","DLLLLLDDD","DDDDDDDDDDDDDDDL","ULUDDD","DULLUULL","LLLLLUD","ULLLLLLLLLLLLLL","LDDDLDLD","UUUUDUU","UDDDDDUD","DLULLLLU","LLLDLLDDD","LLLLLLLLLLLLLLLLLDDD","ULDDDDLL","DULLUULU","DUUUULUL","LDLLLLLLLD","LLDLLDDDD","DDLLDDLLDDLL","DLULULLL","DULUULUL","DULLLU","DLLLULUL","DUULLLUU","LULLUU","DUULLULL","DLDDDDLL","LLSLLLLLLL","DDDDDDULLLLL","ULLULLLLLL","DULUU","DULLULLU","LDDDDLLD","ULULLLDD","DLLLLLUL","DUDUDUDU","LLLLLLDLLLLLL","ULDDULDD","DULLUUUL","LLLLLDDDLLLL","ULDULL","LLLLLDDDLLLLL","DLLLUUUU","LUDDDDDD","ULDULD","UDLLLLDD","ULLLDLLLL","DUUULUUU","ULLD","UUUDUUUD","ULLLLLLS","DUULULUL","DUULUUUL","UDDUDDUD","DLDDDLDL","UUUUUUUUUDDD","LLDDDDDDLLL","DLDDLDDD","LLLLLLLLLLS","DDULLDD","DULULLUU","DUULULLU","UUDDUUUU","LLLLLLLLLLLDL","DDDDDDLLLLLLLLLLL","ULLLLUUD","DLDLLLLLD","UUUDDDU","DULUULUU","LLLLLLLLLLLLLDDDDDD","ULLLULLLD","DLLUULLU","LULUUL","DUUULUUL","UUUDDUU","LLLDLLLDLL","DUUUUUUL","DUULL","LDDLLLDDL","DDLLLLLLLLLLL","UUUUDDUU","DDDDDDDDLLLLLLLLL","ULLUU","LLLLULLD","UUUDDDDU","LLLLLLLLLSLL","DDSDDSDDDDS","DLLUUUUL","UULUU","DLUUULLL","LLLLLLLLDLLLLLLL","DULULUUU","DLLDDDLD","DLUUULUU","DDDDDDLLD","DULULU","ULL","ULUUU","ULLDDLL","DULUUULU","DUUUUULU","UUUUUDDU","LLLLULL","LLLLDDDDDDLLLL","UUDD","DUULUULL","UUUUL","DLLLDDLLL","LLLLLLLLLLLLLDDDDD","ULULLLD","ULLLLLDLL","DDDDDUDD","LLLLLLDDDDLLL","DLULLLLL","DLUULULL","ULLLLLLLLLLLDD","DULLLUUU","LLLDLDLLLL","LLLLLDLLDD","ULLLLLLDS","DULLLLD","LUUUUUUU","ULLLLLLLLLLDDD","ULLUDD","ULLLLLLLLLLLD","LLLLUULL","DLULUULU","DDDDSDDDD","DDDUUDDD","LLLLLLLLLLLLLSLLLL","DLLLLUUU","DLLULLUU","DUUUULLL","DUULUULU","LLDDDLLLLL","LLLDDDLLLLLLLL","DDDDDDLLLDD","DUUULULL","DLDULU","DLUUULLU","DULLUUUU","DUUDU","LLLLLLLLLLLLSLLLLLLL","LULULULU","LLLLLDDLD","DLUULLLL","DDDDUUDD","LLLLLLLLLLSLL","LULLU","DLLULLUL","DULUUUUL","DDSDDSDDS","ULLLLLULLLLLDDDD","ULULUDDD","ULLLLLUDD","LDLDDDL","DUULUUUU","LLLDDDDDDDLLL","LLLLLLLLLLLLDDDDDDDD","DLDDLDLD","LLLDDDDDLLL","DUULLUUU","UDUDDDDD","LUUUL","LLLLUDDD","DULUUUUU","ULUDDDD","LDLLDLLDL","UUULUUUL","DLDD","LULUULUL","LULUL","DUDUUUUU","DLLLLULL","LLLLLLDDLLLLLL","DDDUDDD","DLLLLLLDLL","LLLLLLLLLLLLDL","LUUULLUU","DDLLLLLLLLLLDD","LLLLLLLLLSLLLLLLL","UDDDDDUU","LLLLDLLDDDD","DULLULUU","LLLLLLSS","DULLLLUU","LLLLDDDLLLLL","DLUULUUU","LLLLLLLLLLLSLLLLLLL","UDLDLD","DUDDDDDD","UUUDDDLL","LDLLDLLLLL","LLLDDDLLLLLLL","LDLDLLLLLL","DLULLLUU","LLLLSS","LLLLLLLLSDDD","UUUUUUUUUUUUUUU","LLLLLLDDLLLLL","UUDUUUU","DLULLUUU","LLLDLLDDDD","SLLLLLS","ULULULUD","LLLLLLDDDDLL","DDDDLLLLDDD","LLLLUUU","UUUDULLL","DULULL","LLLLLLLDLLLLL","LLLUULLL","LLLLLLULLLLLLLLL","LLLLLLLLSLL","UUUUUUUUUUDD","LLLULLLD","LDLDDDDL","LLUUUULL","ULLDDDLL","LDLDLDLLL","LLLLLLLLLDLLLL","ULULDDD","LLLLLDLDLL","LLLLLLLLLLDLLLL","UDDUDDU","DLLUUL","ULLLULLLLLLL","DDDDDULL","LLLLLLLLLLLLLSDD","DLLLLUUL","LUULU","DLUUUUUL","DDDULLLLL","LLLLLLLLDDDL","DUUUUULL","DLUUL","LLLLLLUUUUUUUU","LLDDLLDDD","ULDDDDDDDDDD","LLLLLLDU","DLULUULL","DDDUL","SLLLLLLLL","LLUUUUUU","DLUULLUU","LLLLLLSLLLLLLLLL","LLSLLLLLLLL","UUUDDDLD","LLLSLLLLLLLL","LLLLSLLLLLLLLL","DDUDDDDD","DLLDLLLLLL","LULLLLLLDD","DDLLDDLLL","LDDLLLLDL","LLLLLLLDDDLL","DLLUUUUU","LLLDLLLLDL","ULLLLDLD","DLLLUULU","LLLLDDDU","LLLLLLLLLSD","DLUUUULU","DLLLLDDLL","LULLLLLU","DLLUULUL","UULLU","LLLLLLLLLLLSL","LDLDLDLDLDLDLDLD","DLLLUL","ULUUUD","DLDDDDDL","ULLLDLLD","LLLDLLLDLLLD","DLDLDDLD","LLLDDDDLLLLLLLL","LLLLLDDU","LLLLLLLLSDDDD","LLDDLLLLD","DLULLULU","LLLULLLU","LLLU","ULLLLLDS","LLLLLLLLDLLLLLLLL","UULLLLD","DLDUU","DLULUUUU","UUDDDDDU","LLULUD","LLLLLLULLLDD","LDLLLLLDLL","UUUULLLD","LLLLLLLLLLLLLLLLLLD","DDUDDU","DUUUUD","DLLULUUU","DDUDDDD","LSSL","UULDUU","LLDDDDLLDDDD","UDDDDUU","DDDDDDDDULLLL","UUUUDDDDDDD","LLULLLLU","DLULLUUL","USLLLLLDDDD","LLLLLLLDS","LLLLLLLLDLLLLL","LLLLLLLLLLDLL","ULLLLLLLDDDDD","LLLLLLLLLLSL","LDDDDLDL","UUUULLL","LLLSL","LLLLDDDDDDDDLLLL","ULLLLLS","ULLLLDUL","DDDUDDDU","LLUDLU","UUUDUDD","DDDDLLLLLLLLDDDD","DDLLLLLU","DLLLLLLLLLLLL","LUULLLUU","LLULLLL","UUULU","UUDDUUU","LLLDDDDLLLLLLL","DDDLLLLLLDD","LLLDLLLLDD","DULLD","DLULLL","DUUUDUUU","LLDLLLDDDD","LLLLLLLLLLLLLLLLLLLDD","LLLLLLLDDDDDDDDDD","LDLLLLLDD","LLUULLLL","UUULLLD","UUUUUDDDDDDDD","LDLDLDLDLL","DDDDDDUUUUU","DDDDDDDLD","UDLLL","UUDDLLLL","UUDDDDU","LULLLULL","DDDDDDDLU","DLULLU","LLLLLLLLDDLLL","LLLLULUU","DLULLLUL","LLLDDLLLLD","DLULL","DLDLDLDLL","LLLLLLLLLLLLLLLLLLLLLLLLLL","DULDL","ULLLUDDDD","ULLLDU","DDDLLLLDDDD","DULUUU","DDDUUUDD","ULLLLDDU","SDDDDDDS","LLLUD","DUULLU","DLLULUUL","LDDDDLLLL","LLLLLLLUUUUUU","LLLLLLLLLLDLLL","LDDDDDLD","LDLLLLLLDL","DULLUL","UDULLLLL","DDUDD","DLUULUUL","LLLLDDDDU","DUUUUDUU","LLLLDDDDLLLLL","LLLUUULL","LLLLLLLLULLLL","DUUDUUUU","LDDDLDDDD","LLLLLLLLLLLSLL","ULDLLLLU","DLUULULU","LDDDLDL","ULLLLLDU","LUUUUULL","LLDULL","LLLLULLLL"],L.blacklistedSubstrings=["12345678","password","23456789","11198","land","blue","04199","07199","02199","06199","08199","angel","10199","09199","12199","11199","01197","05197","07197","a199","04197","03197","10197","08197","123123","12197","06197","master","dragon","09197","fish","02197","black","11197","a200","2112","fire","mike","baby","pussy","line","test","mark","cher","wood","mama","bear","cool","ling","anne","fred","illa","a198","anti","alle","marc","monkey","life","man1","dick","ness","good","daniel","sexy","o123","time","assi","gold","shan","shadow","rain","ters","alli","ford","play","mont","anta","mine","qazwsx","ache","stra","erry","michael","dima","green","sher","nick","shar","wolf","ring","killer","suck","tina","robert","01196","even","elin","aris","2211","dark","bird","jordan","paul","1108","scar","ones","lock","123321","0909","arri","mustang","rose","shit","asta","money","121212","0505","arch","03196","football","stro","hill","01019","letmein","dman","chin","10219","04196","05196","amil","pant","baseball","porn","david","james","onic","eron","10419","mini","stal","ison","abc123","lover","ander","alen","30319","t123","erin","ina1","vers","0303","ings","martin","mega","olly","ante","hello","11119","0108","90519","00119","08196","21219","shka","10196","hunter","30119","40419","00319","30219","02196","yboy","666666","10619","1102","vlad","70719","pers","1211","nova","12196","10919","anni","sara","lian","010119","07196","30419","0707","elli","oker","50219","er123","atch","00519","00419","rest","06196","50319","side","na19","60619","1107","50419","1210","00619","50819","80319","11196","90919","1109","tran","arma","anton","30519","50719","andrew","l123","09196","50119","31019","enny","0808","40219","90619","01119","80219","34567890","fuckyou","70219","00719","40519","anch","sweet","30719","80519","51219","40619","80419","soccer","21119","2108","00819","70419","60319","1204","60519","80819","1205","1002","elly","race","00919","7777777","60219","stic","steve","40319","70519","west","41019","90419","30619","thomas","01219","51019","boob","tche","30819","less","assa","60719","allo","ital","poli","light","50919","lion","30919","50619","90319","70319","2109","80119","ment","70919","70119","60419","60119","40719","40819","81219","80719","0404","70819","1208","0112","31219","0107","asti","90119","harley","each","70619","40119","51119","0304","80619","90719","bone","well","41219","0606","80919","71019","10101","1206","phil","0105","brand","1209","61219","1202","90819","1105","696969","71119","lick","ista","11111111","91019","lisa","more","0110","1005","123qwe","91219","1106","alis","60819","0106","60919","1000","41119","stre","arry","1207","llin","1007","charlie","enko","40919","1203","1004","k123","1110","31119","71219","long","61019","buster","apple","1003","wing","91119","ivan","1123","reat","1103","81019","61119","tori","0506","batman","stri","2212","anov","sion","2107","leon","1104","81119","isha","2102","a197","power","summer","superman","anya","qwertyui","sing","3108","pepper","1312","2311","george","ence","nker","lore","2110","tech","alan","3112","87654321","1006","card","2106","1008","part","ryan","ross","123a","liver","amin","gran","1402","cock","aron","william","ssie","gene","2512","2301","01200","elan","ipper","ding","para","rish","maria","nson","dave","frank","sasha","1311","2103","moon","rill","buck","tigger","amel","mara","hand","2105","1812","ollo","2309","roni","kate","1512","happy","2525","2505","0405","1301","21985","redd","2202","arth","terr","iloveyou","hockey","2310","mper","2501","2210","3012","per1","2206","adam","3107","abri","tron","emen","0123","olli","11991","isto","game","cent","1009","3110","2305","achi","arta","emin","21990","1310","ladi","hawk","gfhjkm","moni","21989","gate","ines","ing1","lone","llen","ania","elis","mary","alina","2412","ardo","tall","itte","crea","mani","2204","indi","dogg","1478","shel","0502","0305","tree","ning","ation","peter","real","scott","miss","ucki","sant","slav","liza","erna","3010","olle","2510","oria","enne","meli","asca","0308","0708","chie","access","1510","reds","bass","justin","esse","sche","1305","0508","roll","1412","jxrf","2511","sman","2104","1504","0905","niko","hammer","arre","ender","2303","erto","0507","hall","1410","2207","2410","1502","1501","svet","sama","2203","1303","ingo","bitch","1308","2205","1503","esta","0501","1511","98765432","1404","222222","112233","2503","ress","m123","2504","0212","pres","2304","f123","ming","lucky","lass","fuckme","jessica","1307","1306","lash","1302","0211","an19","tlan","jennifer","1405","link","acker","2306","0306","ener","harr","0301","0503","0302","marl","1235","0509","0809","wild","1612","21984","lori","1411","2411","cola","ger1","andrea","1221","21992","0310","avis","0803","snow","came","3003","1507","illo","mist","sandr","cand","rate","1711","silver","hant","1508","daddy","3001","franc","unny","90219","taylor","1304","2401","ashi","3004","freedom","1704","3105","dead","2208","2509","0607","amanda","0307","joshua","11984","1805","arie","asse","1403","trin","2209","1705","yman","rett","kell","jeff","0609","inst","2502","stas","matthew","lanc","0608","2507","alia","1605","0406","alie","2404","tana","bble","ngle","21991","1801","2307","face","stone","1611","1309","1408","2606","hone","1401","mash","anas","mann","aren","wertyuio","son1","2508","8888888","00219","3006","0504","nicole","1712","1213","1707","poop","1407","asper","3103","dallas","erri","dream","denis","teri","2805","mina","ader","diamond","ride","eral","asshole","0912","ashley","team","cheese","bobb","2506","1406","1710","11983","thunder","ister","hero","roman","er19","2405","chen","3005","21983","n200","ginger","serge","0908","2707","kiss","1811","1604","2406","smoke","0309","lord","maggie","trustno1","2611","1509","mila","wall","2601","s200","pack","1802","arme","trac","1703","2909","0311","44444","orne","2812","1606","arne","i123","dude","2711","cookie","1702","2308","kara","0512","sere","1706","sunshine","holl","tell","1601","2403","101198","1803","ertyuiop","wind","2801","1610","2802","1603","2701","ers1","anny","2612","21982","ound","radi","1506","nman","0407","arro","0408","0510","stat","mail","11992","1804","0807","2808","1602","1810","east","2703","2811","nika","enda","astr","barb","victor","osto","abel","2710","2905","ember","0709","1806","ckle","0711","1409","2901","0312","1808","ker1","2605","rena","arke","olga","n199","colo","0410","ckie","rach","2904","2603","0403","dina","2704","2803","alon","corn","2712","ally","papa","0906","anthony","otte","icks","rona","0704","2804","audi","2810","0702","2602","iner","cart","2604","11982","reak","2702","russ","bron","tain","0605","0910","hbyf","1709","pimp","bond","03200","ristin","1608","0602","devil","2903","shot","phan","08200","etro","2610","05200","1230","lant","2402","house","aran","ana1","enter","mali","slan","2408","2407","01195","erse","ardi","159753","gust","cali","kova","azer","e200","1222","chil","andra","2705","0610","chelsea","princess","0902","1809","ermi","2607","ango","oose","0710","3007","hack","atan","0402","11980","0511","04200","adri","0401","on12","nokia","lady","0805","onde","0601","0412","z123","essa","0603","0810","plan","0411","michelle","maks","inde","2906","blow","nasty","0701","computer","aine","mira","ucks","core","2912","qwerty1","2409","1708","lson","aint","0812","0911","2709","1609","toni","iron","eave","1088","ture","oner","some","0705","tere","onta","skin","vent","3009","fast","merlin","4123","1807","0706","0802","0901","1607","2910","0806","0904","11981","atur","02200","09200","2911","tten","elena","0612","white","manu","zxcvbnm","yankees","0604","blin","ammy","2907","samm","0001","nica","acha","2609","starwars","oleg","1018","2807","0801","alls","water","12200","guitar","boom","tara","0409","0611","0804","mate","2809","nell","rton","boot","ffff","vill","2708","bles","maxim","ster1","3008","eeee","0907","flor","riel","rebe","maha","lton","2468","berg","0712","2806","chicken","tony","jackson","tick","cham","igma","avel","anut","ales","lane","ichi","2608","nche","welcome","0903","2706","ckers","lari","onne","inka","apri","kari","dann","07200","adis","10200","call","pion","london","pink","ddie","0703","erson","sport","eren","peac","1qaz2wsx","11200","1029","03195","beer","lala","sssss","metal","opper","ydog","brown","carol","buff","r200","amor","ennis","cros","brad","2424","init","anes","frog","esto","06200","igor","fant","21993","12011","13579","ncc1701","cast","eddy","rush","n198","rris","stel","05195","kins","11993","enta","0000000","magic","kman","vert","10195","2908","4789","ease","tera","arsenal","0811","them","erre","rter","1100","21980","5150","rome","6123","sham","1194","lman","bigdog","brian","uffy","jake","greg","poll","moto","aser","21981","rando","rash","8963","ooke","sparky","oger","jason","wwww","golfer","jane","arat","eagles","rado","ping","scooter","assword1","medi","lera","poke","nett","arge","sten","high","cont","ddog","user","ambo","anim","phoenix","3344","nity","mars","oren","ashe","octo","orma","work","stud","conn","2369","coll","der1","spider","7896","onte","y200","teen","elvi","sting","hanna","lips","rida","marina","yama","term","tigers","kenn","brit","10203","anad","ooper","08195","atte","bast","vika","billy","ferrari","ishi","kkkk","river","tttt","llar","lakers","rend","04195","11195","able","rita","trip","nice","ilan","barn","seve","usty","bbie","boss","dash","iris","itan","sana","cass","ka19","nina","feli","soni","anil","ussi","aram","ampi","ablo","olla","ton1","toma","gman","rama","02195","spri","isco","rack","mers","admi","lade","olan","333333","inal","tani","1089","1078","lana","temp","lly1","unner","09195","adin","12195","9090","rent","man2","honda","tany","na12","131313","4545","jami","nake","r1234","ples","acki","vova","back","ghbdtn","g123","hema","estr","onald","stia","5252","book","cccc","dale","secret","1515","anis","mana","anal","rell","rion","1415","corvette","emil","madd","tink","icky","h123","103198","tine","surf","ssan","bang","speed","1128","onnie","bubba","23232","best","iant","lter","hhhh","nathan","gent","gina","vera","eart","riss","apol","marine","llis","ager","9999999","spec","renc","q1w2e3r4","lley","llll","07195","arad","mous","iann","rola","iter","aper","fylh","slayer","anet","erpo","trav","carlo","rrrr","orange","lent","herm","spir","cana","1232","kola","adim","01010","alexand","1414","ass1","alic","mish","a196","mily","drum","ter2","smith","11979","tits","asia","acka","21994","dger","r199","moll","ores","egor","ishe","x123","tyle","rangers","osta","alpha","haha","jesus","wer1","herr","nders","020219","clar","buddy","olas","tian","lovem","vfvf","rney","ley1","mans","oopy","rami","orth","lice","ttie","mero","babe","o200","carr","barr","lder","brook","klas","nikita","acer","anic","2334","21978","open","er20","er11","ina2","cowboys","mano","an123","read","anit","bara","rsch","iber","ties","gian","field","obby","q123","outh","ilia","anci","anga","na20","32323","down","ravi","ktor","llan","ine1","bren","112198","amat","21979","beat","3141","ndia","11978","solo","road","alma","amma","steph","internet","nich","bbbbb","nite","vita","arde","form","rans","ndro","austin","enna","mall","bloo","ants","107198","endo","1087","valer","icia","mack","ommy","anana","erbo","simp","dent","arty","1191","mach","asha1","cris","appe","simon","nard","alker","lovel","arga","icker","06195","mela","music","teme","bigg","chik","ler1","bite","rocke","nkin","ver1","lica","domin","geni","105198","aska","izard","coco","banan","tomm","11994","tasha","gang","anka","pook","petr","101199","stya","oone","illie","inner","adma","icho","iman","donn","0100","5123","inky","etta","123654","gand","tewa","9632","slut","maverick","lama","amber","mala","ksan","mona","mino","ddddd","bart","8097","eres","lolo","qazxsw","arks","olina","scha","brie","8098","ugar","richard","here","ntan","hamp","ysta","marg","mmmmm","01020","crazy","oles","soft","wins","drey","ney1","pire","gera","3000","serv","eddi","mercedes","alte","1321","dust","020319","020419","spank","unda","1017","qweasd","erbe","yfcn","magn","shor","horse","aaaaaaa","bern","reme","lett","snoop","artem","egas","guar","plat","bandit","nsta","2580","rdon","s199","108198","dona","horny","asil","ordo","nny1","1472","hear","walk","abbi","otto","baba","8912","ickl","boog","inha","erica","ical","1028","10120","1098","kota","ican","dest","harm","raci","onco","rice","evel","789456","qwas","post","tard","atar","unch","aleks","arah","hers","whatever","amba","guin","ellow","mode","1q2w3e","doug","natas","ffin","8050","tele","winn","1593","202198","burn","a111","steelers","lvin","nada","veta","erti","nna1","madi","ulle","zzzzzz","ena1","duck","4242","indo","oron","matrix","fhby","11995","020819","9119","andal","hoot","eway","abcde","deli","chas","issi","pand","iden","orte","list","rost","laster","punk","nior","heri","polo","nand","kitty","butter","rini","cking","110198","yana","olive","start","linda","1090","pala","051987","21977","1717","chuc","rule","020519","nima","entr","ailey","ador","haro","turn","eder","atti","brea","koff","hans","vero","mati","julia","arce","izza","7891","fucker","011990","orri","erik","leas","mother","natali","thead","arco","rant","erta","b123","020119","gator","heel","ard1","grea","anat","mer1","vfrc","020619","olden","ick1","help","bbit","mera","akot","pool","erst","erni","8951","inch","lame","nchi","death","5555555","1058","kati","011987","aras","lexi","rrie","ierr","mili","dboy","ates","kristi","perf","case","bean","asto","randy","oris","iles","falcon","1516","5050","llio","nati","inni","91989","anki","rame","kevin","207198","a2010","lest","a123456","rega","friend","chevy","aval","andon","red1","verp","lava","omar","kiri","as12","cara","amir","olit","hani","annon","tive","okey","nther","1092","estin","ickey","204198","11977","unit","dance","031988","arba","trai","juan","d1234","rger","11975","1079","020719","dell","rabb","rmin","thor","rlan","jean","jone","scorpio","11976","p123","shal","erlo","nest","hele","5566","en12","want","ayne","est1","erem","issy","208198","ygir","burg","s1234","forever","ions","enka","flower","uren","sass","051990","ashk","theb","isse","scho","2119","camp","031987","201198","tima","0012","ophi","les1","rene","9874","late","oome","205198","chip","hica","ento","loves","2131","pace","21976","inke","ction","little","duke","206198","elic","onat","ancer","sala","doll","onik","eria","cord","eanu","chang","gord","kaka","diab","asdfghj","elia","1237","umpe","dies","alam","gala","fort","nine","11121","1118","rker","2128","071987","avan","soph","oshi","knight","bomb","arra","jimmy","1314","1285","mple","like","imbo","bigt","1324","dodge","rchi","fend","ikol","1129","ocky","r198","1022","lege","inat","llo1","bber","041988","rade","ebel","kass","robi","elec","hari","aldo","otti","stef","ssma","erda","luca","samu","leri","tati","ears","adel","frea","iano","ya19","offe","yell","ochka","geli","esha","15051","dmin","morgan","bella","onna","21995","8910","31991","ameri","annah","isla","truck","asmin","071986","020919","anthe","s198","compa","beth","041986","a777","121987","061986","raider","grac","atash","051988","stle","joke","041987","male","4455","driv","tita","051986","nato","amal","0010","3030","patrick","09876","jjjjj","charle","item","41984","edog","1290","121986","stop","demon","ious","lissa","cheste","5935","4725","chol","warr","atro","entin","umbe","ma19","22011","tata","asan","host","skip","on19","lipp","abra","nish","alib","erro","ench","mpir","1190","1077","10111","10121","dogs","lphin","nnet","ippy","berl","71990","llet","011988","junio","203198","41985","arit","71985","cons","ronc","craft","ongo","ingl","1086","ka12","iking","81990","ooooo","ergi","ritt","hester","10011","031986","cats","brav","011986","7258","2123","k199","lita","81985","011985","0990","johnny","terp","samsung","mang","city","71989","micke","huck","91986","etty","desi","aura","021019","oser","fall","key1","ssin","timo","joseph","viki","orgi","061987","world","anja","iabl","hjcn","mass","hank","5454","anky","comm","21975","051985","91988","81987","arsh","fami","q2w3e4r","051989","obra","twin","011989","gabr","rles","muff","elove","209198","61990","1127","071988","qqqqqq","imbe","erty12","baile","061988","ilip","rico","dward","rova","erde","ghjc","lect","eone","cky1","irina","0019","monster","9357","oster","lish","edwar","3698","shing","inho","idas","1245","01041","shak","1038","ppppp","girls","5656","45612","yste","5000","smar","amie","ners","raven","pean","meric","ulie","laure","look","n1234","210198","101987","2344","idge","ymrf","rpoo","31985","ffer","081988","viper","tton","thing","031990","choo","101986","41990","oodl","right","miller","31989","evan","onto","bian","eigh","manc","lace","lema","ggggg","heather","nnnn","tenn","orin","emar","ssio","hort","loui","camaro","squi","carm","31983","061985","8908","inga","2341","kath","7852","kbyf","stea","view","lldog","pson","ty123","ris1","ert1","1234q","eles","ouch","20011","hman","ova1","arik","dirt","1188","8904","name","ooby","christi","dria","ethe","plea","ra19","1080","boro","dako","pain","earl","rple","ocket","deep","livi","elon","01031","1068","61989","sabe","01021","tyrj","hark","ontr","rink","vfhb","amant","utch","in12","lean","01091","hara","nsto","rocks","e1234","20021","dolphi","asda","iell","anin","fghjk","icki","albert","rato","latin","bulldo","1082","505198","popo","ceman","eras","dog1","23021","mell","71983","mario","ber1","smile","rlos","hane","roke","1016","homer","ntai","xxxxxxx","winte","storm","lova","purpl","kare","41991","coob","091987","nita","count","021988","okin","2342","081989","diana","ione","ntha","pira","pear","dawg","beav","imal","obbi","aroli","71984","2333","081986","tdog","bigbo","rove","erba","blad","bett","usha","ndri"]}(Constants=exports.Constants||(exports.Constants={})); +"use strict";var Constants;exports.__esModule=!0,function(L){L.LOWERCASE_LETTERS=new RegExp("[a-z]"),L.LOWERCASE_LETTERS_GLOBAL=new RegExp("[a-z]","g"),L.UPPERCASE_LETTERS=new RegExp("[A-Z]"),L.UPPERCASE_LETTERS_GLOBAL=new RegExp("[A-Z]","g"),L.NONALPHA=new RegExp("[^A-Za-z]"),L.DIGITS=new RegExp("[0-9]"),L.DIGITS_GLOBAL=new RegExp("[0-9]","g"),L.SYMBOLS=new RegExp("[^A-Za-z0-9]"),L.SYMBOLS_GLOBAL=new RegExp("[^A-Za-z0-9]","g"),L.startASCII=32,L.endASCII=126,L.METER_STRINGENCY_SCALE_FACTOR=67/12,L.commonStructures=["LLLLLL","LLLLLLLL","LLLLLLL","DDDDDDDD","DDDDDD","LLLLL","DDDDDDD","LLLLLLDD","LLLLLLLLL","LLLL","DDDD","LLLLLLLD","LLLLLD","LLLLLLLLLL","LLLLLDD","LLLLDDDD","LLLLLLD","LLLLDD","LLLLLDDD","DDDDD","LLLDDD","LLLDDDD","DDDDDDDDD","LLLLLLLLLLL","DDDDDDL","LLLLLDDDD","LLLLDDD","LLLLLLLDD","DDDDDDDDDD","LLLLLLLLLLLL","LLLLLLDDDD","DDDDDDDDL","UUUUUUUU","LLLLLLDDD","LLDDDD","DDDDDDDDDDD","ULLLLL","LLLLLLLLDD","LLLLLLLLD","ULLLLLLL","UUUUUU","ULLLLLLD","LLLLLLLLLLLLL","ULLLLLL","LLLLLLLDDDD","LLLLLLLDDD","ULLLLLD","DDDDLLLL","LLLLLLLLLLLLLL","LLLLD","LLDDDDDD","DLLLLLLL","UUUUUUU","LLLLLLLLLD","DDLLLLLL","DDDDLL","DDDDDDLL","LDDDDDD","LLLDDDDD","ULLLLLDD","LLLLLLLLDDDD","DDDLLL","LLLLLLLLLDD","DDDDDDDL","LLLLLLLLLLLLLLL","DDDDLLL","DULLLLL","DULLLLLL","LLLDDDDDD","ULLLLD","LLLLLLLLDDD","DLLLLL","DDDDDDLLL","LLLLDLLL","LLLLDDDDDD","ULLLL","LLLDD","LDDDDDDD","LLLDLLLL","LLLLLLLLLLLLLLLL","DDLLLL","LLLDDLLL","DDDDDDDDDDDD","DLLLLLL","DDLLLLL","LLLLLDLL","LLLLLLLLLLDD","LLDDDDD","LLLLLDDDDDD","DDDLLLLL","LDDDDDDDD","DDDDDDLLLL","UUUUU","LLLLLLDL","LDDDDD","ULLLDDDD","ULLLLDDD","ULLLLLLLL","LLLLLLLLLDDD","DDDDDL","LLLLLLDDDDDD","LLLLLLLLLLDDDD","DULLLL","ULLLLDD","LLLLDDDDD","LLLLDL","LDLLLLLL","LLDLLLLL","LLLDLL","LLDLLL","LLLLLLLLLLD","LLLDLLL","LLLLLDDDDD","DDDDLLLLL","LDLDLDLD","DDDDDDDDLL","DDDDDDDDLLL","LLLLLLLLLDDDD","DDDLLLL","DDDDDDDDLLLL","DLLLLLLD","LLDDD","LDLDLD","LLLD","DDDDDDDDDL","DLLLDLLL","LDLLLL","LLLLDDDDDDDD","LLLLDLL","UUUU","ULLLLDDDD","LLLLLDL","ULLLLLLDD","DDLLLLDD","LLLLLLDDDDD","LLDDLL","DDDDLLLLLL","DDDDDLLL","DDDDDDDDDDDL","DDDDDDDDDDL","LLLDDDDDDDD","LDDDDL","LLLLDDLL","ULLL","LLLLLLLLLLLDD","LLLLLLLLLLLLLLLLL","DDDDDDLLLLL","LLLLLLLLLLLLDD","LLLLLLLLLLLD","ULLLLLDDDD","LDDDLL","ULLLLLLLLL","ULLLDD","LLLDDDDDDD","LLDDDDDDD","LLLDLLLD","DDLLLDD","DDDDDDDLL","LLDDDDDDDD","ULLLLLLLD","LLLLLDDL","DLDLDLDL","LLDDDDLL","DDDDDDDLLL","DLDLDL","ULLLLLDDD","LLLLLDDDDDDDD","UUUUUUDD","LLDLLLL","LLLLLLLLLLDDD","LDDDDDDL","DDDDDLL","ULLLD","LLLLDDDDDDD","LLDDLLLL","LLLDDDLL","DDDDDDLLLLLL","DLLLLD","DLLLL","LLLLLLLLLLLLLLLLLL","LLLDDLL","ULLLLLLLDD","LLDDLLDD","UUUUUUUUU","LLLLLLLLLLLDDDD","DULLL","ULLLDDD","DDLLLLLLL","LLL","UUUUDDDD","DDLLDD","DDDLLLLLL","DDDDDDDDLLLLL","LLLDDL","DLLLLLD","DDDDDDDLLLL","LDLLLLL","UUUDDDD","LLLLLLLDDDDDD","DLLLLLLLL","LLLLLLLLLLLDDD","LLLLLLLLLLLLLDD","LLLLLLDDDDDDDD","UUUUUD","UUUUDD","LDDLLLLL","LLLLDLLLL","DDDDLLLLLLL","LLLLLDDDDDDD","DDDDL","UUUDDD","LLLLLLLLLLLLD","UUDDDD","UUUUUUUD","LLLLLLLLLLLLDDDD","LDLDLDLDLD","LDDD","LLDLLD","DDDDDDU","LLLLDDL","LLLDDDDL","UUUUUDD","LLLLLLLDDDDD","DDLLLLLDD","UDDDDDD","LLDD","LDDDD","LLDDDLL","ULLLULLL","DDDDLLLLLLLL","LDLLLDLL","DDDDDLLLL","LDDLLL","LLLLLDLD","ULLLLLLDDD","ULLLLU","DDLLL","LLDDLLL","ULLLLLLDDDD","LDDLDD","LDLLDL","ULLLLLLLLLL","LLDLLLDL","","LLLLDLLD","LLDLLDLL","LLLDL","LLDLLLLD","ULDDDDDD","ULLULL","LLLDDDLLL","UUUUUDDD","LLDLL","UUUUUUD","LLLLDDDL","LLLLLLLLLLLLLD","LLLLLLLLDDDDDD","UUUUUUUUUU","LDLLLLDL","LLLLDLDL","LDLLDLLL","LLLLLLLLLLLLLLLLLLL","DLDLLLLL","DDDLLLDDD","DDDDDLLLLL","LLLDDDL","DLLLLDLL","LLLDLLDL","LLLLLLLLLLLLDDD","LDDDDDDDDD","ULLLLLLLLD","LDLDLLLL","LLLLLLLLLLLLLLDD","DDLLLLLLLL","LLDLDLLL","DLLLLLDL","DDDDDDDDU","DDDDDDDDLLLLLL","LDDDDDDDDDD","LDLLLLLD","DDLLLLLLDD","LLDDDL","LLLDLDLL","DLLL","ULLDDDD","DDLLDLLL","DLLLLLLLLL","DLLDLLLL","DDDLL","LLLLLLDDDDDDD","DDD","LLLLLLLDDDDDDDD","LLLDLD","DDLLLLLD","DLLDLL","LLLLLLDLL","UUDDDDDD","DDDDDDDDDLLL","LLDDDLLL","ULLLLLLLLDD","ULULLL","DDLLDDLL","DLLLLLDD","LDLLL","DDDDDDDLLLLL","DDLDDLDDL","ULULUL","ULLLUL","LDLLLD","UDDDDDDDD","LLLLLDLLL","LDLDLL","ULLLLULL","DDDDDDDDDDDDD","ULLLLLLLDDDD","UUUUDDD","LLLLLLLLLLLLLLLLLLLL","DDDDDDDDDDDDDD","DDDLDDD","DDLDDL","DLLLDL","ULLLUU","DLDLDLDLDL","ULLLLLLLDDD","ULLDDD","LLLLLLDLLL","DDDLLLLLLL","DDDDDDDDDDLL","DDLLLDDDD","UDDDDDDD","ULUULL","ULULLU","ULLLLLLLLLD","ULUULU","DDDDDDDDDLL","LLLLLDLLLL","DDDDDDDDDDDLLLL","ULUUUL","ULUUUU","ULLUUU","ULLULU","ULLUUL","LLDLDL","LLLLLLLDL","LLLLLLLS","LLDL","LLLLLLLLLLLLLLD","LDDDDDDDDL","LDDDLLL","LLLLLLS","ULULUU","LDDDDDDDDDDD","LLLLLLLLLLLLLDDD","LLLLLLLLLDDDDDD","DDDDDDLLLLLLL","DDDDDDDDDDLLL","LLLDDLLD","DDDLLDDD","LDDLDDLDD","LLLDLLLLL","ULLLLLLLLLLL","LLLLDDLLL","DDLLLD","LLLDDDDLLL","DDDDDDDDDDDLLL","LDLDLDL","LLLLLLLLDDDDD","LLLLSLLL","LLLLLLLLDDDDDDDD","DLLLDD","LLLLDLD","DDDDDDDDDDDDDDDD","DLDLLL","UUUUUDDDD","DDDDDDDDDDLLLL","LLLLDLLLLL","DLLLD","DDDDDDDU","DDDDDDUU","DDDLLLDD","LLDDDDL","DLLLLLLLD","LLLSLLL","LDDLLLL","ULLLDDDDDD","LLLLLLLLLLLLLDDDD","DDLLLLD","ULLULLLL","LLLDDLLLL","LLLLDDLLLL","DDDLLLLDDD","LDLL","LDDDDDDDL","LLLDLLLLLL","DDDDDDDDDLLLL","LDDDLLDD","LDDDLLLL","LLDDLLLD","DDDDDDDDDDDLL","LLLDLLDD","DDLL","DDDDUU","DDLDDLDD","DDDDDDLLLLLLLL","DDLDDDD","DDDDLLDD","LLLLLS","ULLDDDDDD","LLDLLDL","LDLDLDLL","LLLLDLDD","LDLLLLLLL","DDDLLLD","LLDLLLDD","ULLDDDDD","ULLLLLLU","ULDDDD","LLLDDLLLDD","UUUUUUUDD","LLLLLLLDDDDDDD","UUUDDDDD","LLDLLLD","UUDDDDD","LDLDL","UUUUUUUUUUU","LDLLLLDD","LLDLLLLLL","LLLDDLDL","DLLLDLL","DLLLLDD","LLLLLSDD","DDDDULLL","DDLLDDDD","LLLLLLLDLL","DLLLLDL","LLLLLLLLDL","LDLLLDL","DLDLDLD","LLDLDD","LLLDDDDDDDDD","ULLLLDDDDDD","LDDDLDDD","DDDDDDDDDDDDDDD","DDDDDDDDDDDDL","ULLULLL","LDLDLDLDLDLD","LLLDLLD","DDDDDDDLLLLLL","LDDDDDL","DDDLLLLLLLLL","LLDDL","LLLLLLDDL","LDLLDLL","LDLLDLDL","LLLLLLLLLLLLLLLDD","UULLLLLL","ULLLLLLLLLDD","LDDDDLL","LDLLDLLD","DDDLDD","DDLLLLLLLDD","LLLLLLLLS","UUUUUUDDDD","LLLLDDLD","UDDDDD","LLDDLDLL","DDDDDDDDLLLLLLL","UUUDDDDDD","DDDDLDDDD","LLDDLD","LLLLLDDLLL","DDLLLDDD","UUUUUUDDD","LLLLLDDLL","LLLLDDDDDDDDDD","DDDLLLLLLLL","LLLLLLLLLDDDDD","LDLLDD","LLLLLLLLLLLLLLLLLLLLL","LLLLLLLLLLLLLLLD","LLLSLLLL","DDDDLD","DDLDDD","DDDDUUUU","DLDLL","LDLLLLD","DLDLLLDL","LLLLSLLLL","LDLDLLDL","DDLDLLLL","DDDDDDDDDDDLLLLL","LLLLLLLLLLDDDDDD","UUUUUUUUUUUU","LLLDLDL","LLLLDDDDDDDDD","DDDDDLLLLLL","DDULLLLL","ULLLULL","LLLLLLLLLLLLLLDDDD","DLLDLLDL","LLLDLDLD","LLLDDDDDDDDDD","DDDDLLLLDDDD","LLLLSL","LDLDLLL","DLLLLLLLLD","LDLLLDLD","DDDDLDD","ULDDDLL","LLDLLLLLLL","LLLLLLSDD","DLDLLLL","ULLLLLLLLDDD","LLDLDLL","DDDDDDS","DDLLLLLLLLL","LDLLLDDL","ULLLLDLL","DDLLLDLL","DDLLDL","LLLLLSLLL","DLLLDDLL","LDLDLDLDL","DLLLDLDL","DLLDLLL","DLLDL","DLDLDLLL","LLDDLLD","DDDLLLLLDDD","DDSDDSDDDD","LLDDLLDL","DLLDLLLD","DLLLDDD","LLDLLDDL","LLLLLU","DLLDLDLL","LDDLDL","LDDLLD","LLDLLDLD","DDLLDDD","DDDDLLLD","DLLDDL","ULLLLLDDDDDD","DDDLDDDL","DDLLD","LLLLLDLLLLL","LLLDDLDD","LLDLDLLD","LDDDDLLL","DLLDDLLL","LLLLDDDDDDDDDDD","DLDLLDLL","LLDDDDDDDDD","DDDDDDUUU","DLDDLLLL","DDDLLD","LDDLLLLD","LDLLLLLLLL","DDDDUUU","LLDLDLDL","DLLLLDLD","DDLLLLDDDD","ULLLLDDDDD","LUULDDL","ULLLDDDDD","LDDLLLDL","ULLLLLLLLDDDD","DDLLLLDL","DLLLLLLLLLL","ULLLLLU","LLLLLSLL","DLLLLDDL","LDLDLLLD","DLDLLLLD","UUUDD","LDLDDLLL","LLLLLLDLLLL","LDLLD","DDDDDDUL","LDLD","DLLLLDDD","LDLLDDLL","UUUUD","LDDLLDLL","LLLLLLLLDDDDDDD","LLLDLDDL","DLLLDLLD","DDDDDDDDDDLLLLL","LLLLLDDDDDDDDD","DDDDDDDDUU","LLLLLDDDDDDDDDD","ULDDDDDDDD","UUULLL","LLLLLSLLLLL","LLLLLSLLLL","DLDLLD","LLLSDDDD","LLDDDDDDLL","DLLLDDDD","DLDLD","ULLLLLLLLLLLL","LLLLLLULLLLL","LLDLDDLL","LLLLLLLLLLLLLLDDD","DDDDLLD","LLLDDDLD","ULLLLULLLL","LDDLL","DDLLLDDL","DDDLLLLD","DDDL","ULDDDDDDD","LLLLLLLU","DDDLLDD","LLLLLLLLLLDDDDD","DDLDD","LLLLLLLLLLLLLLLLLLLLLL","UDLLLLLL","LLLLSDD","LDDLDLLL","DLDDLL","LLLLSLLLLL","LLLLSLLLLLL","LLDDDDDDDDDD","DLDDDD","ULLLDLLL","LLLDDDDLL","DDDDLDDD","DLDLDLDLDLDL","ULLLLLUL","DDLDLL","UUULLLLL","UDDDDDDL","LLLLLLDDDDDDDDD","LLLLLLLLLS","LLSLLL","LLDLD","DDDLDDDD","LLLLLLLLLLLLLLLLDD","LLLDDLD","LLLLLLSD","UUUUUUUUDD","LDLDDD","LLDLLDD","DDDDLLLDDDD","DDLLLLLLLLDD","LLLLDDDDLLLL","DDDDDU","UUUDDDUU","DDDDDDDDLLLLLLLL","LLLLDLLLLD","UUUUUUUUD","LLLLSDDD","LLLLLDDDDDDDDDDD","DDDLLLLLLDDD","DLLDDD","DLLDLD","LLDDLLLLL","UDDDDDDU","LSLLLL","LLLLLLULLLLLL","DDDDDDDDDLLLLL","LLLLLLDDLL","DDDDDDDDS","LLLLLSDDD","LDDLLDDL","ULLULLDD","DLLLLLLDD","ULLLLULLL","LLDLLDDD","UULLLL","ULLLULLLL","LLLLLLSLLL","LLLDDLLLLL","UUDDDDDDDD","LLLLLLU","DDDDDDLLLLLLLLL","ULLLDDDDDDDD","DDLDL","DLLDD","LDLDDL","LDDLDDL","LLLLLLDDDDDDDDDD","LLLLLLSLLLLLL","DDDLD","DDDDDDLD","DDLLLLLDDDD","LDDLDDDD","UUDDDDDDD","DUUUUUUU","LDDL","DDDUUU","ULULLLLL","LDLDLDD","LLLDDDDDDDDDDD","DLLDDLLD","UUUUUUUDDD","LLLDLDD","DDDDLLLDD","LLLLLDDDL","ULLLLLDL","ULULULUL","LLLLLLLDDL","LDDLLLDD","ULLLLLLLLLLD","DDDULLLL","LLLSLL","LLLLLLSL","LLLDDDLLLDDD","LLLDDDLLLL","LLLLDDDLLL","LDLLLDDD","LLLSLLLLL","LLLLDDDDL","LLLLDDDLL","LDDDL","LLLLLLULLLLLLL","DDDDDDDDDDLLLLLL","LLLLLLLSDD","UDDDDU","LLLDLDDD","LLLLLSLLLLLL","LLDDLDD","DLDDL","LDLLLDD","LLLLLLDDLLL","DDLDLLL","DDDDDDDDDDDU","LLDDLDL","DLLDLLD","LDDDDLDDDD","LLLLLLSLLLLL","DDDDDDDDDLLLLLL","UUUUUUUDDDD","ULDDDDD","LLLDLLLDDD","DDLLDDL","ULLLLLDDDDD","LLDDDLLD","UUUULLLL","ULLLLLUU","DDDDDDDLLLLLLL","LLLLDDDLLLL","DLDDLD","DDDDLLDDDD","DDSDDSDD","ULLDLLLL","LDDLDDLD","DDDDDDDDUUU","DLLDDLL","DDDDDDDDDDDDDDDDDD","LLLLLLLLLLLLLLLDDD","ULLLU","LLLLLLDLD","UUDDDDUU","LLLLLDDDDL","LLLLLLLLLLLLLLLDDDD","LLLSDD","LLLLLLSLLLL","LLLLLLLLLDDDDDDD","LSLLLLL","LDDDLD","ULLLLDDDDDDDD","DDDDLLLLLDDDD","DDDDDDDDDU","LLLLSDDDD","LDDLDDLL","ULLLLUDD","LDLLDDDD","ULLULLLD","LLLDDDDDDLLL","LLDDDDDL","ULLDDLLL","DDDLDL","LLLLLSL","LDLLDLD","LDLLDLDD","LDLDLLD","DLDLDD","DDDDLLLLLLLLL","LLLLDDDDLL","LLLDLLLLD","DDLLDLL","DDLLLLLLDDDD","ULLDD","UUUDDDDDDDD","ULULLLL","DDLDDLLL","LDLDLLDD","ULLLULLD","DLLDLLDLL","DDUUUUUU","LDDLLDD","ULULDDDD","LLLLLLLLDLL","LLLLSLL","LLLLDLLLLLL","DDLLLLLLLLLL","LLDLLDLLD","LLLLLSDDDD","LLLLLLLLLDL","DLDLDLDLD","LLLLLSD","LLLLLDDLLLL","DDDDDDDDDDDDLLL","DLDL","LLLLDDLLLLL","LLLLLLLDLLL","LLSLLLLL","DDLLLLLLD","DDLDDDDD","LDDLLLLLL","LLDDDDLLL","DLDDDL","LLLLLDDLLLLL","LLLLLLLLLLLLLLLLLDD","LLLLLLLLLLLDDDDD","LLLLLLLSLLLLLL","LDDLLDL","LLLLLLUU","DULLLLLD","UUUUDDDDDD","DLLD","UUDDD","LLLLLLLDLLLL","LLLLLLLLLDDDDDDDD","LDLLDDL","DDULLLL","ULLLDL","DLLLDLLLDLLL","LLLLDDDDLLL","LDLDLDDD","LLDLDDDD","DLDDD","DDDDDDDDDDU","LLUULL","LLLLLLSDDD","UULLDDDD","LLLLUU","LDLDDLDL","DDDLLLDL","LLLLLLLLSDD","DDDLDLLL","UULLLLL","ULLLLLLLLLLDDDD","DDDDDDDDUL","ULLLDDDLLLL","LLLSDDD","DDLDDLL","DDDSDDD","LLLULL","DDDDUL","DDDDDLLLLLLL","UUUUDUUU","DLDLDLL","LDLDDLDD","LLLLLLLLLLLDDDDDD","DDDDULLLL","ULDLLLLL","DDLDLD","DDDDDDLLLLLLLLLL","DDDDDLDD","DDDLLLLLDD","LDLDLDDL","ULDLDD","LLLLLLDDDL","DLLLLDLLL","LLLUUU","LLLLLDDDLL","DDLLDLLD","DLLLDDDL","DDDDDDDDDDDDLLLL","DLLLDDL","LLDDLDDL","ULLLULLLLL","DLDLLLD","ULLDLL","DLDLLLDD","LSLLLLLL","DLLDDDLL","DLLLLDLLLL","DDDLLDLL","ULLDDDDDDD","LLLLLLLSD","LLLLUL","DLLDLLDD","LLLSLLLLLL","UDLLLL","LLLLLLSLLLLLLL","UUULLLDD","DDLDDLD","LLLLLLLLLLLLLLLLD","DDDDDDDS","LULLLL","LLLLLLSDDDD","DDUUUUU","UDDDDDDDDD","LLSLLLL","DDDDLLLLDD","LLLLLLLSLLLLL","DDDLLLLDD","LDDLLLD","LLLLDLLLD","LLLLULLL","DDULLL","DDSULL","LDDDLLLD","LDDDDLDD","DDDDDDDDDDDDLL","LLLLLLLULLLLL","ULLLLLLLLLDDDD","UUUUUDUU","DDDDDLD","ULLDDDDDDDD","LLLLLLLDDDDDDDDD","ULLLLULLLLL","DDLLLDL","LLLLLSLLLLLLL","UUUDUUUU","DDUUUU","DLLLLLLLLLLL","LDDLD","LLLLLLULLLL","LLDLDLDD","UULLLLDD","ULUL","ULLLLUUU","ULLLDDDDDDD","LDDDLDLL","DLDDLDLL","LDLDDDDD","LLDDDDDDL","ULLLLLUD","DDDDLLLLLLDDDD","UULLLDDD","ULLLLLDDDDDDDD","DLLLDLLLL","LDDLLDLD","DLLLLLLDL","LLDDLLLLLL","DLDDDLLL","LLLLLULL","DDDDDDDUU","DDDLLLDDDLLL","UUDDDUU","LDDLDLDL","LDDDDDLL","DDDDDDDDDDDDDDDDDDDD","UULLUU","LLDDDLDD","UUU","LULULU","UUUDLLLL","UDDDUU","DLLLDDLD","DDLLDLDL","DDDUUUUU","LDLLDDDL","DLDDDDDD","SLLLLL","LLLDLLLLLLL","UDDDDDDDDL","LDLLDDLD","UULLL","LLDDDLDL","LLLLLDLLD","ULLLDLL","DDLDDLDDDDL","LLLLU","UUUUUUDU","ULLLLLULLLL","DDLDDDDL","ULLLLLULLLLL","DLLDDLDL","DLLLLLLLLLD","LLLLLLLSLLLL","UDDDDDDDDDD","ULLLLLULLL","LDDLLDDD","DLLLDLD","DDDDDUU","DDLDDLDDDD","UUUUUUUUUD","DLDLLDL","LLDDDDDDDDLL","LLDLLLLDL","LLLLLLLLLLLLLLLLLLLLLLL","DLLDDLD","DLDDLLL","DLDLDDLL","DDDDULL","LDDDLLDDD","LLDDLDLD","LLLLLLLLLLLLLLLLDDDD","DDLLLLDDD","LDLDDDLL","LLLDDDDLLLL","DLLDLDL","DLDLDLLD","LDLLLLDLL","LLULLLLL","UUUUULLL","UUUUUUUUDDDD","ULLLLDDDDDDD","LDDDDDDDDDL","UDUDUD","DUUUUU","LLLLSLLLLLLL","UDDDD","DLDDLLDL","DDLDLDLL","ULLULULL","DDDLDDL","DLLDLDLD","LLDLDDL","LLULLL","UDLDLDLD","UUULLLL","LLLLLLLULLLLLL","DLDDLLLD","ULLLLDL","LLDDDDDDDDDDD","LLDLDDLD","LLLLLLSLL","DDLDLLDL","DDLLLDLD","DDL","LLDLDLD","LDDDDDDDDDDL","LDDLDLLD","DLLDDDD","DDLDLLLD","ULLDLLL","DLLLDLDD","LDLDD","UDDDDDDDL","LLLLLLDDLLLL","DDDDDUUU","LDDLLLLLLL","UDUDUDUD","DDDLDLL","DLDLLDDL","LLLLLLSLLLLLLLL","DLLDLDDL","ULLULLD","LLLLDLLDD","LDDLDLDD","ULLLLLLLLLLDD","ULLLLLLDDDDDD","ULLLLLLLLLLLLL","ULLSDD","LDDDLDD","UDLLLLL","DLDDDDD","LLLLLLLLLLDDDDDDDD","LUUUUU","DDU","LULULL","LLLLLLLLLLLLLLLLLLLLLLLL","LLLLLLLSLLLLLLL","LDLDDLLD","LLLLLLLSLL","DLDLLDLD","DLDLLLLLL","UUUUUUUUUDD","LDDDLLDL","UUUUUUUUUUUUU","DDUUU","LDLLLLLLD","LDLDDDD","DDDDLLDL","DSDSDDD","DLDDLLD","LLLDDDLLLD","LDDLDDD","LLLLLLLDLD","LLULUL","LLDDLDDD","ULLLLLULL","LLLLDDLLLLDD","LDLDDLL","LLLDDLLDD","DLDLDLDD","LLLLLLLLLSDD","LLDDDDDLL","DDDDDLLD","LLLLLDLDL","LLLLLLDLLLLL","UUDUUUUU","LLLLLLLLSLLLLLL","LLLLLLUUUUUU","SSSSSS","LLLLLLLLLLLLDDDDDD","DDULL","LLLLLLLLLLSLLLLL","DDDDDS","LLDLDDD","DLLLLLDLL","ULLLLUD","DUUUU","LLLLLLLLSL","DLDDLDDL","LLLLLLLLLLLSLLLL","LLLLLDDDLLL","ULDLLL","ULLLLLLULLLL","UUUDDDDDDD","ULLLULLU","UULLLU","ULLLULUL","LDDLDLL","DUUUUUU","DDDDLDDDDL","LLLLLLLLSLLLLL","DDDLLDL","LLLLLLLLLDLL","ULLLLLLDDDDD","LLLLLLLSLLL","LLLLLLLLLSLLL","UDUUUUUU","LDLDLLLLL","DDDDDDUUUU","DULLLULL","DDDDDDULLL","LLDLLLLLLLL","ULLULLUL","LLDDLLLDD","LLLLUD","UUUD","ULLDDULL","ULLLLLLLLLDDD","LLLLLLDDDDL","DDDDDDDLLLLLLLL","UULLLLLD","LDLLDLLLL","LLLULLLL","LLDLLLLDLL","DDLDDLDDLDDL","LLLLLSLLLLLLLL","LDLLDDD","ULULU","LULLUL","LLLULU","LLLLLLLLLLLSLLLLL","DDDDDDLU","UULUUL","LLDDLLDDLLDD","LLLLLLLSL","DDLDDLDL","LLLLLLUD","UUUUUULL","UDDDUDDD","LLLDDDLLLLLL","ULLLUD","ULLLDDLL","LDDDDDDDDDDDD","UDDDDDDDDDDD","ULULL","ULLLLDDL","DDLLDDDL","DDDDLDDL","SLLLLLL","LLLLLLLDDLL","DDDDLLLLLDD","ULULULU","SLLLLLLL","LLLLDLLDL","UUDDUU","DDLLLLLLLLLDD","UUUULU","UUUDDUUU","UUULUU","LLUULU","DLLDLLLLL","LLUUUU","ULLULULU","ULUUUULL","DDLDDDLL","LLDLLLLLD","ULLLDULL","DDDDLLLLLLLLLL","ULLULLLU","LLLLLLLLLLSLLLL","DULLLLLLL","ULLUDDDD","LLLLLDDDDLLLLL","LLLLDDDDDDDDDDDD","DDDDU","DDDULL","DDULLLDD","LLLLLLLLSLLLL","LLDLDDDL","LLLDLDLLL","LLLLLLLSDDDD","LLDDDLD","UUUUDDDDD","DSDSDSDDD","DDDDULLLLL","DDLDDLLD","LLLLLLLULLLLLLL","ULLULLLLL","ULULLLUL","LDLLLLLLLLL","UUUULL","LLLDLLDLL","LDLLLLLDL","ULULULLL","DDDLLLLLLLDDD","DDUUUDD","LLLLLLLLULLLLL","LDDLDDLDDLDD","ULLUULLU","DLLLLLLU","ULULLLLU","LDDLDLD","LLLUDD","UULULL","LLLLLLLLLLLLLLLLDDD","UUUUUDDDDDD","LLDLLLDLL","DDDLDDLL","DDDUUUU","LDDDLLD","LLLLLLULLLLLLLL","DDDDDDULL","LLLLLLLLSLLL","UUUUUUUUDDD","LDLDDLD","ULLLUULL","ULULLULL","LLLLLLLLDLLL","LLLLLLLLLLSLLL","LLLLLLLDDLLL","DDDDDDDDDDS","LLLLLLLLLLLLDDDDD","UDDDDDDDDU","LLLLLLLLLLDL","ULLLLULU","LLUUUL","DUUUUUUD","LUULUU","LLLLLLLLLLLSLLL","ULULUUUL","LLLLLLLLLLLLSLLL","LDDDDDDLL","UUULLLDDD","ULLLULLLLLL","DDLLDDLD","ULULLULU","LLLLLLLSDDD","LLLLLLLLLSLLLL","DDLLDLD","ULLUL","LLLLLLLLLLLLLLLLLLDD","LLLLLLLLLSLLLLLL","DUDLUDUL","DLLLLDDDD","DDLDLLDD","UUULUL","LLLLLLLLDDL","LLLLLLLLLSLLLLL","ULLUUUUU","SSSSS","UULLLULL","DLDLLDDD","ULLULLUU","ULULUULU","LULUUU","LLLLLLLLSLLLLLLL","LLLLLLLSLLLLLLLL","LLLLLUUU","LLLDDLLLLLL","ULLLLUL","DDUUUUDD","DDLDDDL","LDDLDDLDDDD","LLLLUUUU","UULLLLLU","LLLULLL","ULULLLUU","ULLUULLL","DDDDDDDDDDDDDDL","LUULLU","LLLDLLLLLD","LLDDLLDDLL","LDDLDDLDDL","LLDDDLLLL","LLLDLLLDL","LUUULL","LUULLL","DLLDLDD","UULLUUUL","ULULLUUL","LDLDLDLDLDL","DDLDLDDL","ULUUULLL","UULLULLL","ULLLUUUU","DDUU","LLLDDDLLLLL","LLLLLLUUUUUUU","UUUDUUU","LLULUU","LLLLLLLLLLLSDD","ULLLLUUL","ULUULULU","LLLUUL","LLLLLDLLLLLL","LULLLLLL","UUDUUU","DDDDLDLL","LLSLLLLLL","LLLLDDDLLLLDDD","UUUULULL","UUULLUUL","LLLLLLLLLLLLSLLLLL","LULLL","DDDLLLDDDD","DDDDDDDDUUUU","LLLLDLDLL","LSLLL","DLDLDDDL","LDDDLLLLL","LDDDDDDDDDDDL","UULLLLUL","UULUUU","UUULLLLU","UULULU","ULUULULL","UUUUULUU","UUUDU","ULUULUUL","UUULLULL","ULLUUULU","ULULULLU","UULLLLUU","UUDUU","DULULLLL","UULLLUUU","DDDDLDL","ULLLULUU","UUULLLLD","LLLLLLLDLLLLLL","LLLLLLLLDLLLLLL","DDDLDLLD","DDLLLLLLLD","LLLLLLLLSLLLLLLLL","LLDLLDLLL","UUULULLL","LLLLLLDDDLLL","LLLDLLLDD","UUULUULL","ULLUULUL","UULUUULL","UULLULLU","LSLLLLLLL","LLLLSLLLLLLLL","DLLLLLDLLL","LDDDLLDDLLL","LLLSLLLLLLL","LDLLLDLLL","DLLLDLLLLL","LLLLSD","LLLLLDDDDLL","LLDDDLLDDD","LLLLLLDLDL","ULDDLLLL","LLLLDDLLLLLL","LLDLLLLLDL","UDDUDD","DDLLDLDD","LLLLLLDDS","UUUDDLLL","ULUULUUU","DLLDDDDD","DDUUDD","UULLULUU","DDLUL","DDDDDDDDDDDLLLLLL","LUUULU","DULLU","DULUL","LLLLLLLLDLLLL","LLLDDLLLD","DDDDDDDDULLL","DDDULLL","DDDDDDUD","UULULLLL","ULLLLLLLU","ULLULUUL","ULLUUULL","LLLUUD","LLLLLLDLLD","LLLLLLDDDLL","UUUUUUUUUUUUUU","LDDDLDDL","UDDLLLLL","UULLLUUL","DDDLLDDDD","DDUUL","ULULDD","UULULULU","UDUUU","DDLLLLLLLDDDD","ULUUUUUL","DLDDLLDD","LSLLDDDD","DDDDDDDDDDDDDDDDD","LLULL","DULLULLL","LULLLU","LLLLLLLLLLLSLLLLLL","LLLLLLLULLLL","UUUUUL","ULDDLL","DLLLLLLLDD","UULLUULU","UDDDUUDD","LLLLLLLLULLLLLL","DLDDLDL","UUUUUUDDDDDD","DDLLU","DDDLLLLLLLLLL","ULLLLSDD","LLLLLLLLU","LLLLLLLLLLLLLLLLLD","DDDDDDDDDDDS","UUULLULU","LLLLDLLLLLLL","DDDLLDDL","DDDDDDULLLL","LLDLLLDLLL","DLDLDDD","LLLLLLLLSD","UUUUUUUL","DDDDDLDL","LLLUL","UUUUUULU","DULLLLUL","LLLLLUDD","LSLLLLLLLL","DLDLLDD","ULLLLLDDDDDDD","UUULULUL","LLUUL","UULULLUL","LLUUUD","UUUULUUL","ULLDULLL","ULDDDDDDDDD","DDLLDDLLDD","ULLUULUU","ULUULLUL","ULUUULLU","UUULUUUU","UUUUDU","DDDDLLLLD","UULUUUUU","ULULULUU","DLDLDDL","LLLLLLULLLLDD","ULULULDD","DDDLLLLLLLLDDD","DDUULLLL","ULLLULLLDD","LLLLLDLLLLLD","ULLLUUUL","DDLDLDD","ULUULLUU","DLLUL","UUULLLUU","DDDDSDD","DDLLDDDDDD","DDDDDDLLLLDD","LLLLLLLLLLSLLLLLL","UUULLLUL","DDDDDDDUL","UUULULUU","LLLLLDDDDLLL","DLLUU","DLLLLLLLLLLD","ULLLLLSD","LLLLLLLLLLLLSLLLL","UDDDDUDD","LLLLLLLLULLLLLLL","DDLDLLD","DDDDLLLDDD","UUUDUU","ULULUULL","DDDUU","LLLLLLLDLLLLLLL","LUULUL","UULLUUUU","DDDDDDLLLLLDD","DLLULLLL","DDLDLDLD","DDDLDDLD","ULLLULDD","ULDLLLL","DDDDUDDD","LDDLDDDL","DDLDLDL","ULLLLLSDD","UDDDDDU","ULULLUUU","LDLDLDLDLDLDLD","LLLLLLLLLLLLSDD","DLLLDLLLD","DLDDDLDD","ULUUUULU","UUUUDDDDDDDD","UUUUUDDDDD","DUUULLLL","ULLULUUU","LDLLLLDLLL","LLLLLLLLLLLDDDDDDDD","ULLLLULLLLLL","LLULU","DLUULLUL","LLLLLLULLLLLDD","UUUUULUL","ULLLUDDD","LLLLDLDLLL","DDUDDUDD","DULLLULU","DLLLLLDDDD","LLLLLDDDDLLLL","UUULL","DLLDDLDD","UUULUULU","DDDDDDDDDDDDDL","ULLLUULU","UULUULLU","DUULLUUL","ULLLLLLLDDDDDD","ULUULLLU","DLLULULL","LUULL","DLDDDLLD","LLLLLLLLLLSDD","DDLU","DULULUUL","DLDDLDD","UULLULUL","DDLDDDLD","LLLLDDDDUU","DLULU","ULUUUUUU","LLLLLLLLDDLL","LLLLDLLLDL","DDUL","ULULUUUU","ULUULLLL","UDDUDDUDD","LLDDDDLD","LLULLU","UDUUUU","UUUULLUU","LLLLLLDDDDLLLLLL","DDDLDLDL","ULUUULUL","UUULULLU","UUDDUUDD","ULLLLLDDS","DLLDDDL","DDDDDDLLLLLLDD","UULUULLL","UULULULL","DLLLULLU","ULULLLLD","DULLLLLU","LLDLDLLLL","DLDDDDL","ULULUD","UUUULLLU","UUUULLUL","UUULLUUU","DUUULLUL","DUUULULU","UULLUULL","DDDDDDLDD","DDDDUUUUU","DDDLLLLLD","LLLLLLUL","DLLLLLLLDL","LLDLLLLDD","DULULLLU","DDDDLLDDD","UULUUUUL","DULULULU","DDDDLLLLLLLDDDD","LLDLLLLLLD","LLLLLDLDD","UULULLLU","LLLDDDDLLLLLL","LLLLLLDDDDDDDDDDD","DLDLDDDD","LLLLLLLLLLLLLLLLLDDDD","DDDDLDLD","LLDDDDLLLL","LLLLLLLDDDL","DDLD","LLLUU","DDDLDLD","DDULU","DUULLLUL","UUUUULLU","DLLDLDDD","DDLDLDDD","ULLUUUUL","DLLUUULU","ULLU","DUULLLLL","UULUULUL","UULULLUU","LLLLDU","DLLUULUU","DDDDDDDDDLLLLLLL","DLLLLLUU","ULUUULUU","DDDDDDDUUU","ULDDD","LLUUU","DLDLDLDLDLD","DDLLLDDLL","LLDDDDDDDLL","DDDLLDLD","ULLDULLD","DLLLULLL","UULLLULU","DULULULL","UULUULUU","DDLLLLLDDD","DULULLUL","UDDUDDDD","UUUULULU","DDDDLLLLLLDD","DUULU","DLLLLULU","DDULLLLLL","DLLLULUU","DDDUDDDD","LLLLLDLLDL","UUDDDDLL","DLDLLLLLLL","DDLLLDDLLL","LLLLLSLLLLLLLLL","LLLLLLLLLLLLSLLLLLL","ULLLUDD","LLLDULLL","DUUUL","DDDDDDSS","UULULUUL","LLLDDDDDDDDLLL","DUULLLLU","LLDLLDLLLL","DUULLULU","LLLLLUU","DDLDDDDDD","DUUULLUU","DDLUU","LLLLDLLDLL","DLDDDLL","UUUULUUU","LLDLDLLLLL","DLLLU","LLLLLLLDLLLLLLLL","LLLLLDLLLD","LLULLD","LDLLLLDDL","DDDLDLDD","UUULLU","DDDDDDDDDS","DUULULUU","UDDUDDD","ULLLUUU","DLULUUUL","UDDDDL","DUUUULLU","LLLLLLLLLDDL","LLLLLLLLLLSLLLLLLL","LLLUUUDD","LDLLLDLLLL","DLDDDLD","LDDDDLD","DULUUULL","DLLUUULL","DULUULLU","UULUUULU","LLLLLDDS","ULLLLLDDDLLLL","ULLDL","UULLLD","LLLDDDDLLLLL","DULLLUUL","LLLDLLDLLL","DUULULLL","UULLUL","DDDDLLLLLLLLLLL","ULLLLLLDDDDDDDD","ULLLLUU","DLUUULUL","DULUULLL","DDDDDDDLDD","DLLULLLU","ULLLLULD","ULLDLLLD","DULLULUL","DLLDDDDL","LUUUUL","DUULD","DLUUUULL","DUUULLLU","LLLLLLLLLLLLLSLLLLL","LUUUU","UULLLDD","DDULLLLDD","DLLULL","UULLDD","DSULL","DLLLUULL","UULULUUU","ULUUL","DUUUULUU","DLULLULL","UDLLLLLD","DDLDLLLLL","UULUL","ULLLLLLULLL","LLLLLLDS","UDDDDDDDU","LLLLLLLLLDLLL","DLLUULLL","LLLDDDDDDDDDDDD","DLLLLLDDD","DDDDDDDDDDDDDDDL","ULUDDD","DULLUULL","LLLLLUD","ULLLLLLLLLLLLLL","LDDDLDLD","UUUUDUU","UDDDDDUD","DLULLLLU","LLLDLLDDD","LLLLLLLLLLLLLLLLLDDD","ULDDDDLL","DULLUULU","DUUUULUL","LDLLLLLLLD","LLDLLDDDD","DDLLDDLLDDLL","DLULULLL","DULUULUL","DULLLU","DLLLULUL","DUULLLUU","LULLUU","DUULLULL","DLDDDDLL","LLSLLLLLLL","DDDDDDULLLLL","ULLULLLLLL","DULUU","DULLULLU","LDDDDLLD","ULULLLDD","DLLLLLUL","DUDUDUDU","LLLLLLDLLLLLL","ULDDULDD","DULLUUUL","LLLLLDDDLLLL","ULDULL","LLLLLDDDLLLLL","DLLLUUUU","LUDDDDDD","ULDULD","UDLLLLDD","ULLLDLLLL","DUUULUUU","ULLD","UUUDUUUD","ULLLLLLS","DUULULUL","DUULUUUL","UDDUDDUD","DLDDDLDL","UUUUUUUUUDDD","LLDDDDDDLLL","DLDDLDDD","LLLLLLLLLLS","DDULLDD","DULULLUU","DUULULLU","UUDDUUUU","LLLLLLLLLLLDL","DDDDDDLLLLLLLLLLL","ULLLLUUD","DLDLLLLLD","UUUDDDU","DULUULUU","LLLLLLLLLLLLLDDDDDD","ULLLULLLD","DLLUULLU","LULUUL","DUUULUUL","UUUDDUU","LLLDLLLDLL","DUUUUUUL","DUULL","LDDLLLDDL","DDLLLLLLLLLLL","UUUUDDUU","DDDDDDDDLLLLLLLLL","ULLUU","LLLLULLD","UUUDDDDU","LLLLLLLLLSLL","DDSDDSDDDDS","DLLUUUUL","UULUU","DLUUULLL","LLLLLLLLDLLLLLLL","DULULUUU","DLLDDDLD","DLUUULUU","DDDDDDLLD","DULULU","ULL","ULUUU","ULLDDLL","DULUUULU","DUUUUULU","UUUUUDDU","LLLLULL","LLLLDDDDDDLLLL","UUDD","DUULUULL","UUUUL","DLLLDDLLL","LLLLLLLLLLLLLDDDDD","ULULLLD","ULLLLLDLL","DDDDDUDD","LLLLLLDDDDLLL","DLULLLLL","DLUULULL","ULLLLLLLLLLLDD","DULLLUUU","LLLDLDLLLL","LLLLLDLLDD","ULLLLLLDS","DULLLLD","LUUUUUUU","ULLLLLLLLLLDDD","ULLUDD","ULLLLLLLLLLLD","LLLLUULL","DLULUULU","DDDDSDDDD","DDDUUDDD","LLLLLLLLLLLLLSLLLL","DLLLLUUU","DLLULLUU","DUUUULLL","DUULUULU","LLDDDLLLLL","LLLDDDLLLLLLLL","DDDDDDLLLDD","DUUULULL","DLDULU","DLUUULLU","DULLUUUU","DUUDU","LLLLLLLLLLLLSLLLLLLL","LULULULU","LLLLLDDLD","DLUULLLL","DDDDUUDD","LLLLLLLLLLSLL","LULLU","DLLULLUL","DULUUUUL","DDSDDSDDS","ULLLLLULLLLLDDDD","ULULUDDD","ULLLLLUDD","LDLDDDL","DUULUUUU","LLLDDDDDDDLLL","LLLLLLLLLLLLDDDDDDDD","DLDDLDLD","LLLDDDDDLLL","DUULLUUU","UDUDDDDD","LUUUL","LLLLUDDD","DULUUUUU","ULUDDDD","LDLLDLLDL","UUULUUUL","DLDD","LULUULUL","LULUL","DUDUUUUU","DLLLLULL","LLLLLLDDLLLLLL","DDDUDDD","DLLLLLLDLL","LLLLLLLLLLLLDL","LUUULLUU","DDLLLLLLLLLLDD","LLLLLLLLLSLLLLLLL","UDDDDDUU","LLLLDLLDDDD","DULLULUU","LLLLLLSS","DULLLLUU","LLLLDDDLLLLL","DLUULUUU","LLLLLLLLLLLSLLLLLLL","UDLDLD","DUDDDDDD","UUUDDDLL","LDLLDLLLLL","LLLDDDLLLLLLL","LDLDLLLLLL","DLULLLUU","LLLLSS","LLLLLLLLSDDD","UUUUUUUUUUUUUUU","LLLLLLDDLLLLL","UUDUUUU","DLULLUUU","LLLDLLDDDD","SLLLLLS","ULULULUD","LLLLLLDDDDLL","DDDDLLLLDDD","LLLLUUU","UUUDULLL","DULULL","LLLLLLLDLLLLL","LLLUULLL","LLLLLLULLLLLLLLL","LLLLLLLLSLL","UUUUUUUUUUDD","LLLULLLD","LDLDDDDL","LLUUUULL","ULLDDDLL","LDLDLDLLL","LLLLLLLLLDLLLL","ULULDDD","LLLLLDLDLL","LLLLLLLLLLDLLLL","UDDUDDU","DLLUUL","ULLLULLLLLLL","DDDDDULL","LLLLLLLLLLLLLSDD","DLLLLUUL","LUULU","DLUUUUUL","DDDULLLLL","LLLLLLLLDDDL","DUUUUULL","DLUUL","LLLLLLUUUUUUUU","LLDDLLDDD","ULDDDDDDDDDD","LLLLLLDU","DLULUULL","DDDUL","SLLLLLLLL","LLUUUUUU","DLUULLUU","LLLLLLSLLLLLLLLL","LLSLLLLLLLL","UUUDDDLD","LLLSLLLLLLLL","LLLLSLLLLLLLLL","DDUDDDDD","DLLDLLLLLL","LULLLLLLDD","DDLLDDLLL","LDDLLLLDL","LLLLLLLDDDLL","DLLUUUUU","LLLDLLLLDL","ULLLLDLD","DLLLUULU","LLLLDDDU","LLLLLLLLLSD","DLUUUULU","DLLLLDDLL","LULLLLLU","DLLUULUL","UULLU","LLLLLLLLLLLSL","LDLDLDLDLDLDLDLD","DLLLUL","ULUUUD","DLDDDDDL","ULLLDLLD","LLLDLLLDLLLD","DLDLDDLD","LLLDDDDLLLLLLLL","LLLLLDDU","LLLLLLLLSDDDD","LLDDLLLLD","DLULLULU","LLLULLLU","LLLU","ULLLLLDS","LLLLLLLLDLLLLLLLL","UULLLLD","DLDUU","DLULUUUU","UUDDDDDU","LLULUD","LLLLLLULLLDD","LDLLLLLDLL","UUUULLLD","LLLLLLLLLLLLLLLLLLD","DDUDDU","DUUUUD","DLLULUUU","DDUDDDD","LSSL","UULDUU","LLDDDDLLDDDD","UDDDDUU","DDDDDDDDULLLL","UUUUDDDDDDD","LLULLLLU","DLULLUUL","USLLLLLDDDD","LLLLLLLDS","LLLLLLLLDLLLLL","LLLLLLLLLLDLL","ULLLLLLLDDDDD","LLLLLLLLLLSL","LDDDDLDL","UUUULLL","LLLSL","LLLLDDDDDDDDLLLL","ULLLLLS","ULLLLDUL","DDDUDDDU","LLUDLU","UUUDUDD","DDDDLLLLLLLLDDDD","DDLLLLLU","DLLLLLLLLLLLL","LUULLLUU","LLULLLL","UUULU","UUDDUUU","LLLDDDDLLLLLLL","DDDLLLLLLDD","LLLDLLLLDD","DULLD","DLULLL","DUUUDUUU","LLDLLLDDDD","LLLLLLLLLLLLLLLLLLLDD","LLLLLLLDDDDDDDDDD","LDLLLLLDD","LLUULLLL","UUULLLD","UUUUUDDDDDDDD","LDLDLDLDLL","DDDDDDUUUUU","DDDDDDDLD","UDLLL","UUDDLLLL","UUDDDDU","LULLLULL","DDDDDDDLU","DLULLU","LLLLLLLLDDLLL","LLLLULUU","DLULLLUL","LLLDDLLLLD","DLULL","DLDLDLDLL","LLLLLLLLLLLLLLLLLLLLLLLLLL","DULDL","ULLLUDDDD","ULLLDU","DDDLLLLDDDD","DULUUU","DDDUUUDD","ULLLLDDU","SDDDDDDS","LLLUD","DUULLU","DLLULUUL","LDDDDLLLL","LLLLLLLUUUUUU","LLLLLLLLLLDLLL","LDDDDDLD","LDLLLLLLDL","DULLUL","UDULLLLL","DDUDD","DLUULUUL","LLLLDDDDU","DUUUUDUU","LLLLDDDDLLLLL","LLLUUULL","LLLLLLLLULLLL","DUUDUUUU","LDDDLDDDD","LLLLLLLLLLLSLL","ULDLLLLU","DLUULULU","LDDDLDL","ULLLLLDU","LUUUUULL","LLDULL","LLLLULLLL"],L.blacklistedSubstrings=["12345678","password","23456789","11198","land","blue","04199","07199","02199","06199","08199","angel","10199","09199","12199","11199","01197","05197","07197","a199","04197","03197","10197","08197","123123","12197","06197","master","dragon","09197","fish","02197","black","11197","a200","2112","fire","mike","baby","pussy","line","test","mark","cher","wood","mama","bear","cool","ling","anne","fred","illa","a198","anti","alle","marc","monkey","life","man1","dick","ness","good","daniel","sexy","o123","time","assi","gold","shan","shadow","rain","ters","alli","ford","play","mont","anta","mine","qazwsx","ache","stra","erry","michael","dima","green","sher","nick","shar","wolf","ring","killer","suck","tina","robert","01196","even","elin","aris","2211","dark","bird","jordan","paul","1108","scar","ones","lock","123321","0909","arri","mustang","rose","shit","asta","money","121212","0505","arch","03196","football","stro","hill","01019","letmein","dman","chin","10219","04196","05196","amil","pant","baseball","porn","david","james","onic","eron","10419","mini","stal","ison","abc123","lover","ander","alen","30319","t123","erin","ina1","vers","0303","ings","martin","mega","olly","ante","hello","11119","0108","90519","00119","08196","21219","shka","10196","hunter","30119","40419","00319","30219","02196","yboy","666666","10619","1102","vlad","70719","pers","1211","nova","12196","10919","anni","sara","lian","010119","07196","30419","0707","elli","oker","50219","er123","atch","00519","00419","rest","06196","50319","side","na19","60619","1107","50419","1210","00619","50819","80319","11196","90919","1109","tran","arma","anton","30519","50719","andrew","l123","09196","50119","31019","enny","0808","40219","90619","01119","80219","34567890","fuckyou","70219","00719","40519","anch","sweet","30719","80519","51219","40619","80419","soccer","21119","2108","00819","70419","60319","1204","60519","80819","1205","1002","elly","race","00919","7777777","60219","stic","steve","40319","70519","west","41019","90419","30619","thomas","01219","51019","boob","tche","30819","less","assa","60719","allo","ital","poli","light","50919","lion","30919","50619","90319","70319","2109","80119","ment","70919","70119","60419","60119","40719","40819","81219","80719","0404","70819","1208","0112","31219","0107","asti","90119","harley","each","70619","40119","51119","0304","80619","90719","bone","well","41219","0606","80919","71019","10101","1206","phil","0105","brand","1209","61219","1202","90819","1105","696969","71119","lick","ista","11111111","91019","lisa","more","0110","1005","123qwe","91219","1106","alis","60819","0106","60919","1000","41119","stre","arry","1207","llin","1007","charlie","enko","40919","1203","1004","k123","1110","31119","71219","long","61019","buster","apple","1003","wing","91119","ivan","1123","reat","1103","81019","61119","tori","0506","batman","stri","2212","anov","sion","2107","leon","1104","81119","isha","2102","a197","power","summer","superman","anya","qwertyui","sing","3108","pepper","1312","2311","george","ence","nker","lore","2110","tech","alan","3112","87654321","1006","card","2106","1008","part","ryan","ross","123a","liver","amin","gran","1402","cock","aron","william","ssie","gene","2512","2301","01200","elan","ipper","ding","para","rish","maria","nson","dave","frank","sasha","1311","2103","moon","rill","buck","tigger","amel","mara","hand","2105","1812","ollo","2309","roni","kate","1512","happy","2525","2505","0405","1301","21985","redd","2202","arth","terr","iloveyou","hockey","2310","mper","2501","2210","3012","per1","2206","adam","3107","abri","tron","emen","0123","olli","11991","isto","game","cent","1009","3110","2305","achi","arta","emin","21990","1310","ladi","hawk","gfhjkm","moni","21989","gate","ines","ing1","lone","llen","ania","elis","mary","alina","2412","ardo","tall","itte","crea","mani","2204","indi","dogg","1478","shel","0502","0305","tree","ning","ation","peter","real","scott","miss","ucki","sant","slav","liza","erna","3010","olle","2510","oria","enne","meli","asca","0308","0708","chie","access","1510","reds","bass","justin","esse","sche","1305","0508","roll","1412","jxrf","2511","sman","2104","1504","0905","niko","hammer","arre","ender","2303","erto","0507","hall","1410","2207","2410","1502","1501","svet","sama","2203","1303","ingo","bitch","1308","2205","1503","esta","0501","1511","98765432","1404","222222","112233","2503","ress","m123","2504","0212","pres","2304","f123","ming","lucky","lass","fuckme","jessica","1307","1306","lash","1302","0211","an19","tlan","jennifer","1405","link","acker","2306","0306","ener","harr","0301","0503","0302","marl","1235","0509","0809","wild","1612","21984","lori","1411","2411","cola","ger1","andrea","1221","21992","0310","avis","0803","snow","came","3003","1507","illo","mist","sandr","cand","rate","1711","silver","hant","1508","daddy","3001","franc","unny","90219","taylor","1304","2401","ashi","3004","freedom","1704","3105","dead","2208","2509","0607","amanda","0307","joshua","11984","1805","arie","asse","1403","trin","2209","1705","yman","rett","kell","jeff","0609","inst","2502","stas","matthew","lanc","0608","2507","alia","1605","0406","alie","2404","tana","bble","ngle","21991","1801","2307","face","stone","1611","1309","1408","2606","hone","1401","mash","anas","mann","aren","wertyuio","son1","2508","8888888","00219","3006","0504","nicole","1712","1213","1707","poop","1407","asper","3103","dallas","erri","dream","denis","teri","2805","mina","ader","diamond","ride","eral","asshole","0912","ashley","team","cheese","bobb","2506","1406","1710","11983","thunder","ister","hero","roman","er19","2405","chen","3005","21983","n200","ginger","serge","0908","2707","kiss","1811","1604","2406","smoke","0309","lord","maggie","trustno1","2611","1509","mila","wall","2601","s200","pack","1802","arme","trac","1703","2909","0311","44444","orne","2812","1606","arne","i123","dude","2711","cookie","1702","2308","kara","0512","sere","1706","sunshine","holl","tell","1601","2403","101198","1803","ertyuiop","wind","2801","1610","2802","1603","2701","ers1","anny","2612","21982","ound","radi","1506","nman","0407","arro","0408","0510","stat","mail","11992","1804","0807","2808","1602","1810","east","2703","2811","nika","enda","astr","barb","victor","osto","abel","2710","2905","ember","0709","1806","ckle","0711","1409","2901","0312","1808","ker1","2605","rena","arke","olga","n199","colo","0410","ckie","rach","2904","2603","0403","dina","2704","2803","alon","corn","2712","ally","papa","0906","anthony","otte","icks","rona","0704","2804","audi","2810","0702","2602","iner","cart","2604","11982","reak","2702","russ","bron","tain","0605","0910","hbyf","1709","pimp","bond","03200","ristin","1608","0602","devil","2903","shot","phan","08200","etro","2610","05200","1230","lant","2402","house","aran","ana1","enter","mali","slan","2408","2407","01195","erse","ardi","159753","gust","cali","kova","azer","e200","1222","chil","andra","2705","0610","chelsea","princess","0902","1809","ermi","2607","ango","oose","0710","3007","hack","atan","0402","11980","0511","04200","adri","0401","on12","nokia","lady","0805","onde","0601","0412","z123","essa","0603","0810","plan","0411","michelle","maks","inde","2906","blow","nasty","0701","computer","aine","mira","ucks","core","2912","qwerty1","2409","1708","lson","aint","0812","0911","2709","1609","toni","iron","eave","1088","ture","oner","some","0705","tere","onta","skin","vent","3009","fast","merlin","4123","1807","0706","0802","0901","1607","2910","0806","0904","11981","atur","02200","09200","2911","tten","elena","0612","white","manu","zxcvbnm","yankees","0604","blin","ammy","2907","samm","0001","nica","acha","2609","starwars","oleg","1018","2807","0801","alls","water","12200","guitar","boom","tara","0409","0611","0804","mate","2809","nell","rton","boot","ffff","vill","2708","bles","maxim","ster1","3008","eeee","0907","flor","riel","rebe","maha","lton","2468","berg","0712","2806","chicken","tony","jackson","tick","cham","igma","avel","anut","ales","lane","ichi","2608","nche","welcome","0903","2706","ckers","lari","onne","inka","apri","kari","dann","07200","adis","10200","call","pion","london","pink","ddie","0703","erson","sport","eren","peac","1qaz2wsx","11200","1029","03195","beer","lala","sssss","metal","opper","ydog","brown","carol","buff","r200","amor","ennis","cros","brad","2424","init","anes","frog","esto","06200","igor","fant","21993","12011","13579","ncc1701","cast","eddy","rush","n198","rris","stel","05195","kins","11993","enta","0000000","magic","kman","vert","10195","2908","4789","ease","tera","arsenal","0811","them","erre","rter","1100","21980","5150","rome","6123","sham","1194","lman","bigdog","brian","uffy","jake","greg","poll","moto","aser","21981","rando","rash","8963","ooke","sparky","oger","jason","wwww","golfer","jane","arat","eagles","rado","ping","scooter","assword1","medi","lera","poke","nett","arge","sten","high","cont","ddog","user","ambo","anim","phoenix","3344","nity","mars","oren","ashe","octo","orma","work","stud","conn","2369","coll","der1","spider","7896","onte","y200","teen","elvi","sting","hanna","lips","rida","marina","yama","term","tigers","kenn","brit","10203","anad","ooper","08195","atte","bast","vika","billy","ferrari","ishi","kkkk","river","tttt","llar","lakers","rend","04195","11195","able","rita","trip","nice","ilan","barn","seve","usty","bbie","boss","dash","iris","itan","sana","cass","ka19","nina","feli","soni","anil","ussi","aram","ampi","ablo","olla","ton1","toma","gman","rama","02195","spri","isco","rack","mers","admi","lade","olan","333333","inal","tani","1089","1078","lana","temp","lly1","unner","09195","adin","12195","9090","rent","man2","honda","tany","na12","131313","4545","jami","nake","r1234","ples","acki","vova","back","ghbdtn","g123","hema","estr","onald","stia","5252","book","cccc","dale","secret","1515","anis","mana","anal","rell","rion","1415","corvette","emil","madd","tink","icky","h123","103198","tine","surf","ssan","bang","speed","1128","onnie","bubba","23232","best","iant","lter","hhhh","nathan","gent","gina","vera","eart","riss","apol","marine","llis","ager","9999999","spec","renc","q1w2e3r4","lley","llll","07195","arad","mous","iann","rola","iter","aper","fylh","slayer","anet","erpo","trav","carlo","rrrr","orange","lent","herm","spir","cana","1232","kola","adim","01010","alexand","1414","ass1","alic","mish","a196","mily","drum","ter2","smith","11979","tits","asia","acka","21994","dger","r199","moll","ores","egor","ishe","x123","tyle","rangers","osta","alpha","haha","jesus","wer1","herr","nders","020219","clar","buddy","olas","tian","lovem","vfvf","rney","ley1","mans","oopy","rami","orth","lice","ttie","mero","babe","o200","carr","barr","lder","brook","klas","nikita","acer","anic","2334","21978","open","er20","er11","ina2","cowboys","mano","an123","read","anit","bara","rsch","iber","ties","gian","field","obby","q123","outh","ilia","anci","anga","na20","32323","down","ravi","ktor","llan","ine1","bren","112198","amat","21979","beat","3141","ndia","11978","solo","road","alma","amma","steph","internet","nich","bbbbb","nite","vita","arde","form","rans","ndro","austin","enna","mall","bloo","ants","107198","endo","1087","valer","icia","mack","ommy","anana","erbo","simp","dent","arty","1191","mach","asha1","cris","appe","simon","nard","alker","lovel","arga","icker","06195","mela","music","teme","bigg","chik","ler1","bite","rocke","nkin","ver1","lica","domin","geni","105198","aska","izard","coco","banan","tomm","11994","tasha","gang","anka","pook","petr","101199","stya","oone","illie","inner","adma","icho","iman","donn","0100","5123","inky","etta","123654","gand","tewa","9632","slut","maverick","lama","amber","mala","ksan","mona","mino","ddddd","bart","8097","eres","lolo","qazxsw","arks","olina","scha","brie","8098","ugar","richard","here","ntan","hamp","ysta","marg","mmmmm","01020","crazy","oles","soft","wins","drey","ney1","pire","gera","3000","serv","eddi","mercedes","alte","1321","dust","020319","020419","spank","unda","1017","qweasd","erbe","yfcn","magn","shor","horse","aaaaaaa","bern","reme","lett","snoop","artem","egas","guar","plat","bandit","nsta","2580","rdon","s199","108198","dona","horny","asil","ordo","nny1","1472","hear","walk","abbi","otto","baba","8912","ickl","boog","inha","erica","ical","1028","10120","1098","kota","ican","dest","harm","raci","onco","rice","evel","789456","qwas","post","tard","atar","unch","aleks","arah","hers","whatever","amba","guin","ellow","mode","1q2w3e","doug","natas","ffin","8050","tele","winn","1593","202198","burn","a111","steelers","lvin","nada","veta","erti","nna1","madi","ulle","zzzzzz","ena1","duck","4242","indo","oron","matrix","fhby","11995","020819","9119","andal","hoot","eway","abcde","deli","chas","issi","pand","iden","orte","list","rost","laster","punk","nior","heri","polo","nand","kitty","butter","rini","cking","110198","yana","olive","start","linda","1090","pala","051987","21977","1717","chuc","rule","020519","nima","entr","ailey","ador","haro","turn","eder","atti","brea","koff","hans","vero","mati","julia","arce","izza","7891","fucker","011990","orri","erik","leas","mother","natali","thead","arco","rant","erta","b123","020119","gator","heel","ard1","grea","anat","mer1","vfrc","020619","olden","ick1","help","bbit","mera","akot","pool","erst","erni","8951","inch","lame","nchi","death","5555555","1058","kati","011987","aras","lexi","rrie","ierr","mili","dboy","ates","kristi","perf","case","bean","asto","randy","oris","iles","falcon","1516","5050","llio","nati","inni","91989","anki","rame","kevin","207198","a2010","lest","a123456","rega","friend","chevy","aval","andon","red1","verp","lava","omar","kiri","as12","cara","amir","olit","hani","annon","tive","okey","nther","1092","estin","ickey","204198","11977","unit","dance","031988","arba","trai","juan","d1234","rger","11975","1079","020719","dell","rabb","rmin","thor","rlan","jean","jone","scorpio","11976","p123","shal","erlo","nest","hele","5566","en12","want","ayne","est1","erem","issy","208198","ygir","burg","s1234","forever","ions","enka","flower","uren","sass","051990","ashk","theb","isse","scho","2119","camp","031987","201198","tima","0012","ophi","les1","rene","9874","late","oome","205198","chip","hica","ento","loves","2131","pace","21976","inke","ction","little","duke","206198","elic","onat","ancer","sala","doll","onik","eria","cord","eanu","chang","gord","kaka","diab","asdfghj","elia","1237","umpe","dies","alam","gala","fort","nine","11121","1118","rker","2128","071987","avan","soph","oshi","knight","bomb","arra","jimmy","1314","1285","mple","like","imbo","bigt","1324","dodge","rchi","fend","ikol","1129","ocky","r198","1022","lege","inat","llo1","bber","041988","rade","ebel","kass","robi","elec","hari","aldo","otti","stef","ssma","erda","luca","samu","leri","tati","ears","adel","frea","iano","ya19","offe","yell","ochka","geli","esha","15051","dmin","morgan","bella","onna","21995","8910","31991","ameri","annah","isla","truck","asmin","071986","020919","anthe","s198","compa","beth","041986","a777","121987","061986","raider","grac","atash","051988","stle","joke","041987","male","4455","driv","tita","051986","nato","amal","0010","3030","patrick","09876","jjjjj","charle","item","41984","edog","1290","121986","stop","demon","ious","lissa","cheste","5935","4725","chol","warr","atro","entin","umbe","ma19","22011","tata","asan","host","skip","on19","lipp","abra","nish","alib","erro","ench","mpir","1190","1077","10111","10121","dogs","lphin","nnet","ippy","berl","71990","llet","011988","junio","203198","41985","arit","71985","cons","ronc","craft","ongo","ingl","1086","ka12","iking","81990","ooooo","ergi","ritt","hester","10011","031986","cats","brav","011986","7258","2123","k199","lita","81985","011985","0990","johnny","terp","samsung","mang","city","71989","micke","huck","91986","etty","desi","aura","021019","oser","fall","key1","ssin","timo","joseph","viki","orgi","061987","world","anja","iabl","hjcn","mass","hank","5454","anky","comm","21975","051985","91988","81987","arsh","fami","q2w3e4r","051989","obra","twin","011989","gabr","rles","muff","elove","209198","61990","1127","071988","qqqqqq","imbe","erty12","baile","061988","ilip","rico","dward","rova","erde","ghjc","lect","eone","cky1","irina","0019","monster","9357","oster","lish","edwar","3698","shing","inho","idas","1245","01041","shak","1038","ppppp","girls","5656","45612","yste","5000","smar","amie","ners","raven","pean","meric","ulie","laure","look","n1234","210198","101987","2344","idge","ymrf","rpoo","31985","ffer","081988","viper","tton","thing","031990","choo","101986","41990","oodl","right","miller","31989","evan","onto","bian","eigh","manc","lace","lema","ggggg","heather","nnnn","tenn","orin","emar","ssio","hort","loui","camaro","squi","carm","31983","061985","8908","inga","2341","kath","7852","kbyf","stea","view","lldog","pson","ty123","ris1","ert1","1234q","eles","ouch","20011","hman","ova1","arik","dirt","1188","8904","name","ooby","christi","dria","ethe","plea","ra19","1080","boro","dako","pain","earl","rple","ocket","deep","livi","elon","01031","1068","61989","sabe","01021","tyrj","hark","ontr","rink","vfhb","amant","utch","in12","lean","01091","hara","nsto","rocks","e1234","20021","dolphi","asda","iell","anin","fghjk","icki","albert","rato","latin","bulldo","1082","505198","popo","ceman","eras","dog1","23021","mell","71983","mario","ber1","smile","rlos","hane","roke","1016","homer","ntai","xxxxxxx","winte","storm","lova","purpl","kare","41991","coob","091987","nita","count","021988","okin","2342","081989","diana","ione","ntha","pira","pear","dawg","beav","imal","obbi","aroli","71984","2333","081986","tdog","bigbo","rove","erba","blad","bett","usha","ndri"]}(Constants=exports.Constants||(exports.Constants={})); },{}],7:[function(require,module,exports){ "use strict";exports.__esModule=!0;var Dictionaries,PasswordMeter=require("./PasswordMeter"),PasswordLeaks=require("../js/hibp-js");!function(e){var s,i,a=function(){function e(e){var s=PasswordMeter.PasswordMeter.instance.getHelper();e.blacklist.checkSubstrings?this.blacklistRejects=function(s){return this.blacklistBloom.substringExists(s,e.blacklist.checkSubstringLength)}:this.blacklistRejects=function(e){return this.blacklistDict[e]},this.blacklistDict=s.compressedFileToDict(e.blacklist.blacklistFile),this.blacklistBloom=s.compressedFileToBloomFilter(e.blacklist.blacklistFile,e.blacklist.checkSubstringLength),this.leaks=new PasswordLeaks.PasswordLeaks,this.passwordsDict=s.compressedFileToDict("dictionary-passwords-compressed.txt"),this.namesDict=s.compressedFileToDict("dictionary-names-compressed.txt"),this.phrasesDict=s.compressedFileToDict("dictionary-phrases-compressed.txt"),this.englishwordsDict=s.compressedFileToDict("dictionary-englishwords-compressed.txt"),this.wikipediaDict=s.compressedFileToDict("dictionary-wikipedia-compressed.txt"),this.petnames={};for(var i=["abbey","abby","alex","allie","amber","angel","annie","ashley","baby","bailey","bandit","barney","baxter","bear","beau","bella","belle","bentley","blackie","blue","bonnie","boomer","boots","bosco","brady","brandy","bruno","brutus","bubba","buddy","buffy","buster","cali","callie","calvin","casey","casper","cassie","champ","chance","charlie","chase","chelsea","chester","chico","chloe","cleo","cleopatra","clyde","coco","cocoa","cody","cookie","cooper","cosmo","daisy","dakota","dexter","diesel","dixie","duke","duncan","dusty","ella","ellie","elvis","emily","emma","felix","fiona","fluffy","frankie","fred","gabriel","garfield","george","gigi","ginger","gizmo","grace","gracie","guinness","haley","hannah","harley","harry","heidi","henry","holly","honey","hunter","isabella","isis","jack","jackson","jade","jake","jasmine","jasper","jessie","joey","junior","katie","kiki","kitty","kobe","lacey","lady","lexi","lexie","libby","lilly","lily","loki","lola","louie","lucky","lucy","luke","lulu","luna","maddie","madison","maggie","mandy","marley","maximus","maxwell","maya","merlin","mickey","midnight","mikey","millie","milo","mimi","minnie","misskitty","missy","misty","mittens","mocha","molly","moose","morgan","muffin","murphy","nala","nikki","oliver","olivia","oreo","oscar","otis","patches","peaches","peanut","pebbles","penny","pepper","phoebe","piper","precious","prince","princess","pumpkin","rascal","riley","rocco","rocky","romeo","roscoe","rosie","roxie","roxy","ruby","rudy","rufus","rusty","sabrina","sadie","samantha","sammy","sampson","samson","sandy","sarah","sasha","sassy","scooter","scout","sebastian","shadow","sheba","shelby","sierra","simba","simon","smokey","snoopy","snowball","socks","sonny","sophia","sophie","sparky","spencer","spike","stalla","stella","sugar","sunny","sydney","sylvester","tabitha","tasha","teddy","thomas","tiger","tigger","tinkerbell","toby","tommy","trixie","tucker","tyson","willie","willow","winston","xena","yoda","zeus","ziggy","zoey"],a=0;a=r-1;i--)for(var o=0;i+o/g,">")},String.prototype.listSubstrings=function(r){for(var t,e=new Array,n=(t=(t=this.toLowerCase()).replace(/[^a-z]/g,"")).length,i=n;i>=r-1;i--)for(var o=0;i+o0?e*Constants.Constants.METER_STRINGENCY_SCALE_FACTOR:e},e.prototype.spawnRating=function(){var e="",t=PasswordMeter.PasswordMeter.instance.getNN();e=this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown?this.$("#pwboxModal").val():this.$("#pwbox").val();var s=this.$("#usernamebox").val(),i=0,o=t.getNeuralNetNum(e);void 0===o?(t.setNeuralNetNum(e,-1),t.queryGuessNumber(e,!1)):o>=0&&i++,void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!0):this.heuristicMapping[e]>=0&&i++,0!==e.length&&t.heardFromNn()&&2!==i||this.displayRating(e)},e.prototype.generateCandidateFixed=function(e,t,s){var i=[];if(void 0===this.deltaHighlighted[e])for(var o=0;o=65&&n.charCodeAt(r)<=90?(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)+32)),i[r]=1):n.charCodeAt(r)>=97&&n.charCodeAt(r)<=122&&(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)-32)),i[r]=1)}else if(2===h||3===h){var l=32+Math.floor(95*Math.random()),p=Math.floor(n.length*Math.random());n.charCodeAt(p)!==l&&(i[p]=1),n=n.replaceAt(p,String.fromCharCode(l))}else if(h>=4){l=32+Math.floor(95*Math.random()),p=Math.floor((n.length+1)*Math.random());n=n.slice(0,p)+String.fromCharCode(l)+n.slice(p),i=i.slice(0,p).concat(1,i.slice(p))}var d=PasswordMeter.PasswordMeter.instance.getNN();void 0===d.getNeuralNetNum(n)&&(d.setNeuralNetNum(n,-1),d.queryGuessNumber(n,!0));var u=this.$("#usernamebox").val();return RuleFunctions.RuleFunctions.verifyMinimumRequirements(n,u).compliant?(this.recommendedFixes[s]=n,this.deltaHighlighted[n]=i,this.verboseMode&&console.log("identified "+n+" as a potential fix for "+s),void 0===this.recommendedFixesTries[s]?this.recommendedFixesTries[s]=1:this.recommendedFixesTries[s]=this.recommendedFixesTries[s]+1,this.spawnFixedRating(n)):++t<8&&this.generateCandidateFixed(e,t,s),1},e.prototype.spawnFixedRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=this.$("#usernamebox").val();void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!1):t.getNeuralNetNum(e)>=0&&this.heuristicMapping[e]>=0&&this.synthesizeFixed(e)},e.prototype.synthesizeFixed=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0,o=!1;void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(i++,s=this.heuristicMapping[e]);var n=t.getNeuralNetNum(e),h=this.nnNumtoScoreAsPercent(n);if(void 0!==n&&h>=0&&isFinite(h)&&(i++,(0===s||s>0&&h=67){for(var a in this.verboseMode&&console.log(e+" is a plausible fix above the 2/3rds threshold"),this.recommendedFixes)if(this.recommendedFixes[a]===e&&void 0===this.fixedpwMapping[a]){var r=0;void 0!==this.heuristicMapping[a]&&this.heuristicMapping[a]>=0&&(r=this.heuristicMapping[a]);var l=t.getNeuralNetNum(a),p=this.nnNumtoScoreAsPercent(l);void 0!==l&&p>=0&&isFinite(p)&&(0===r||r>0&&pr+15?(this.fixedpwMapping[a]=e,this.verboseMode&&console.log("mapping "+a+" to "+e),o=!0):this.verboseMode&&console.log("not mapping "+a+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s)}return o&&this.spawnRating(),1}var d=this.$("#pwbox").val();return this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown&&(d=this.$("#pwboxModal").val()),this.recommendedFixes[d]===e&&2===i&&void 0===this.fixedpwMapping[d]&&void 0!==this.recommendedFixesTries[d]&&this.recommendedFixesTries[d]<8&&(this.verboseMode&&console.log("trying again on "+e+" as current password is "+d),this.generateCandidateFixed(e,0,d)),1},e.prototype.redundant=function(e,t){e=e.toLowerCase();for(var s=0;s0&&e.length>0&&(t[s].indexOf(e)>=0&&e.length>=.7*t[s].length||e.indexOf(t[s])>=0&&t[s].length>=.7*e.length))return!0;return!1},e.prototype.queryHeuristicGuessNumber=function(e,t,s){var i=e,o=[],n=[],h=[],a=[],r=RuleFunctions.RuleFunctions.contextual(e,[t]);void 0===(e=r.remaining)&&(e="");var l=RuleFunctions.RuleFunctions.blacklist(e);void 0===(e=l.remaining)&&(e="");for(var p=RuleFunctions.RuleFunctions.pwLength(e),d=RuleFunctions.RuleFunctions.characterClasses(e),u=RuleFunctions.RuleFunctions.duplicatedCharacters(e),c=RuleFunctions.RuleFunctions.repeats(e),m=RuleFunctions.RuleFunctions.keyboardPatterns(e),g=RuleFunctions.RuleFunctions.repeatedSections(e),x=RuleFunctions.RuleFunctions.structurePredictable(e),b=RuleFunctions.RuleFunctions.uppercasePredictable(e),w=RuleFunctions.RuleFunctions.digitsPredictable(e),$=RuleFunctions.RuleFunctions.symbolsPredictable(e),v=RuleFunctions.RuleFunctions.countUC(e),M=RuleFunctions.RuleFunctions.countLC(e),y=RuleFunctions.RuleFunctions.countDIGS(e),f=RuleFunctions.RuleFunctions.countSYMS(e),T=RuleFunctions.RuleFunctions.identifyDates(e),R=(RuleFunctions.RuleFunctions.verifyMinimumRequirements(e,t),RuleFunctions.RuleFunctions.alphabeticSequenceCheck(e)),F=RuleFunctions.RuleFunctions.commonSubstringCheck(e),C=RuleFunctions.RuleFunctions.combinedDictCheck(e),N=e.listSubstringsNoFilter(4),k=RuleFunctions.RuleFunctions.commonPwCheck(N),W=[1.53,.3129,.9912,.04637,-.03885,-.1172,-.2976,-8581e-7,-.3008,-.5566,0,.9108,.7369,.7578,0,-.1213,-.2402,-.1364,-.5534,1.927,.001496,-.3946],P=[1,p.length,d.count,u.count,c.count,m.score,g.count,x.score,b.score,w.score,$.score,v.count,M.count,y.count,f.count,T.count,R.count,F.count,C.length,C.dictionaryTokens,C.substitutionCommonness,k.length],H=W[0],S=1;S100&&(H=100),r.publicText.length>0&&(o.push(r.publicText),n.push(r.sensitiveText),h.push(r.reasonWhy),a.push(r.problemText)),l.publicText.length>0&&(o.push(l.publicText),n.push(l.sensitiveText),h.push(l.reasonWhy),a.push(l.problemText)),C.publicText.length>0&&!this.redundant(C.problemText,a)&&(o.push(C.publicText),n.push(C.sensitiveText),h.push(C.reasonWhy),a.push(C.problemText)),m.publicText.length>0&&(o.push(m.publicText),n.push(m.sensitiveText),h.push(m.reasonWhy),a.push(m.problemText)),c.publicText.length>0&&(o.push(c.publicText),n.push(c.sensitiveText),h.push(c.reasonWhy),a.push(c.problemText)),T.publicText.length>0&&(o.push(T.publicText),n.push(T.sensitiveText),h.push(T.reasonWhy),a.push(T.problemText)),g.publicText.length>0&&(o.push(g.publicText),n.push(g.sensitiveText),h.push(g.reasonWhy),a.push(g.problemText)),R.publicText.length>0&&(o.push(R.publicText),n.push(R.sensitiveText),h.push(R.reasonWhy),a.push(R.problemText)),k.publicText.length>0&&!this.redundant(k.problemText,a)&&(o.push(k.publicText),n.push(k.sensitiveText),h.push(k.reasonWhy),a.push(k.problemText)),b.publicText.length>0&&(o.push(b.publicText),n.push(b.sensitiveText),h.push(b.reasonWhy),a.push(b.problemText)),w.publicText.length>0&&(o.push(w.publicText),n.push(w.sensitiveText),h.push(w.reasonWhy),a.push(w.problemText)),$.publicText.length>0&&(o.push($.publicText),n.push($.sensitiveText),h.push($.reasonWhy),a.push($.problemText)),u.publicText.length>0&&(o.push(u.publicText),n.push(u.sensitiveText),h.push(u.reasonWhy),a.push(u.problemText)),p.publicText.length>0&&(o.push(p.publicText),n.push(p.sensitiveText),h.push(p.reasonWhy)),f.publicText.length>0&&(o.push(f.publicText),n.push(f.sensitiveText),h.push(f.reasonWhy)),v.publicText.length>0&&(o.push(v.publicText),n.push(v.sensitiveText),h.push(v.reasonWhy)),y.publicText.length>0&&(o.push(y.publicText),n.push(y.sensitiveText),h.push(y.reasonWhy)),M.publicText.length>0&&(o.push(M.publicText),n.push(M.sensitiveText),h.push(M.reasonWhy)),F.publicText.length>0&&!this.redundant(F.problemText,a)&&(o.push(F.publicText),n.push(F.sensitiveText),h.push(F.reasonWhy)),x.publicText.length>0&&(o.push(x.publicText),n.push(x.sensitiveText),h.push(x.reasonWhy)),this.heuristicMapping[i]=H,this.feedbackMapping[i]=JSON.stringify({publictips1:o[0],publictips2:o[1],publictips3:o[2],sensitivetips1:n[0],sensitivetips2:n[1],sensitivetips3:n[2],reasonWhy1:h[0],reasonWhy2:h[1],reasonWhy3:h[2]}),s?(this.displayRating(i),w.fixedPw.length>0?(this.previousCandidate[i]=w.fixedPw,this.deltaHighlighted[w.fixedPw]=w.deltas):$.fixedPw.length>0&&(this.previousCandidate[i]=$.fixedPw,this.deltaHighlighted[$.fixedPw]=$.deltas)):this.synthesizeFixed(i)},e.prototype.displayRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0;if(e.length>0){void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(s=this.heuristicMapping[e],i++);var o=t.getNeuralNetNum(e),n=this.nnNumtoScoreAsPercent(o);void 0!==o&&n>=0&&isFinite(n)&&(i++,(0==s||s>0&&n(Why?)
"),p+="

 

To make it even better:",this.$("#feedbackHeaderText").html(p),this.$("#feedbackHeaderTextModal").html(p)}else{var d="Your password appears strong.";a.remindAgainstReuse&&(d+=" Make sure you use it only for this account. (Why?)"),this.$("#feedbackHeaderText").html(d),this.$("#feedbackHeaderTextModal").html(d)}if(this.$(".nonmodalColorCell").show(),this.$(".modalColorCell").show(),this.$(".modalColorCellSpacer").show(),this.$(".recommended").show(),!0===this.$("#showHidePWNonModal").prop("checked")?(this.$(".fixedPWavailablePortal").hide(),this.$(".concreteSuggestionDiv").show(),this.$("#tipText1").html(h.sensitivetips1),this.$("#tipText2").html(h.sensitivetips2),this.$("#tipText3").html(h.sensitivetips3),this.$("#suggestion1").html(h.sensitivetips1),this.$("#suggestion2").html(h.sensitivetips2),this.$("#suggestion3").html(h.sensitivetips3),this.$("#sensText1").html(h.reasonWhy1),this.$("#sensText2").html(h.reasonWhy2),this.$("#sensText3").html(h.reasonWhy3)):(this.$(".fixedPWavailablePortal").show(),this.$(".concreteSuggestionDiv").hide(),this.$("#tipText1").html(h.publictips1),this.$("#tipText2").html(h.publictips2),this.$("#tipText3").html(h.publictips3),this.$("#suggestion1").html(h.publictips1),this.$("#suggestion2").html(h.publictips2),this.$("#suggestion3").html(h.publictips3),this.$("#sensText1").html(h.reasonWhy1),this.$("#sensText2").html(h.reasonWhy2),this.$("#sensText3").html(h.reasonWhy3)),void 0!==this.fixedpwMapping[e]){for(var u="",c=this.deltaHighlighted[this.fixedpwMapping[e]],m=this.fixedpwMapping[e],g=0;g"+m[g].escapeHTML()+"
":u+=m[g].escapeHTML();this.$(".fixedPW").html(u)}else this.$(".recommended").hide();s<=66?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show()):s<100?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show(),this.tookSuggestion&&(this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())):(this.$("#nonmodalFeedbackTable").hide(),this.$("#modalFeedbackTable").hide(),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())}else{this.inCompliance=!1,0!==e.length&&t.heardFromNn()&&2!==i||this.displayBar(s,!1),this.$("#confirmpw").hide(),this.$(".detailedFeedback").hide(),this.$(".portalToGenericAdviceModal").show(),this.$(".explainWhy").hide();var x="";(a=PasswordMeter.PasswordMeter.instance.getConfig()).remindAgainstReuse&&(x="Don't reuse a password from another account! (Why?)

 

");var b="Your password must:";this.$("#feedbackHeaderText").html(x+b),this.$("#feedbackHeaderTextModal").html(x+b),this.$("#nonmodalFeedbackTable").show(),this.$(".recommended").hide();var w=[],$=l.detail;for(var v in $.compliance)$.compliance[v]||w.push($.explanation[v]);this.$(".nonmodalColorCell").hide(),this.$(".modalColorCell").hide(),this.$(".modalColorCellSpacer").hide(),this.$(".nonmodalRow").hide(),this.$(".modalRow").hide();for(var M=0;M100&&(e=100);var s=e/100,i="rgb(160,160,160)";t&&s<.45?i="rgb("+Math.round(255)+","+Math.round(s/.45*140)+",0)":t&&s>=.45&&s<.65?i="rgb("+Math.round(255)+","+Math.round((s-.45)/.2*75+140)+",0)":t&&(i="rgb("+Math.round(255-(s-.65)/.35*205)+","+Math.round(215-(s-.65)/.035)+",0)"),this.$("#cups-passwordmeter-span").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span").css("background-color",i),this.$("#cups-passwordmeter-span-modal").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span-modal").css("background-color",i)},e.prototype.getMaxOfArray=function(e){return Math.max.apply(null,e)},e.prototype.expandHelpBut=function(){this.$("#expandHelpDiv").show(),this.$("#helpButton").hide()},e.prototype.modalShowCheck=function(){"text"==this.$("#pwbox").prop("type")?(this.$("#myModal").show(),this.storepw()):this.$("#expandHelpDiv").is(":visible")?(this.$("#myModal").show(),this.storepw()):this.expandHelpBut()},e.prototype.closeDiv=function(e){this.$(e).hide()},e.prototype.deselect=function(e){null==this.$.fn.slideFadeToggle&&(this.$.fn.slideFadeToggle=function(e,t){return this.animate({opacity:"toggle",height:"toggle"},"fast",e,t)}),this.$(".pop").slideFadeToggle(function(){e.removeClass("selected")})},e}();e.UIMisc=o,t=PasswordMeter.PasswordMeter.instance,s=t.getJquery(),i=new o(!1),t.setUI(i),s(document).ready(function(){s("#showpassword").prop("checked",!1),s("#showpassword").click(function(){document.getElementById("hide-show-label").textContent="Hide Password",s("#cbbutton").css("background-color","#f5f5f5"),"password"==s("#pwbox").prop("type")?s("#pwbox").prop("type","text"):(s("#pwbox").prop("type","password"),document.getElementById("hide-show-label").textContent="Show Password",s("#cbbutton").css("background-color","#f5f5f5"))})}),s(document).ready(function(){var e=s("#pwboxModal");s("#tip1, #sensText1").mouseover(function(){e.addClass("problemColor")}),s("#tip2, #sensText2").mouseover(function(){e.addClass("problemColor")}),s("#tip3, #sensText3").mouseover(function(){e.addClass("problemColor")})}),s(document).ready(function(){i.onReady()})}(UIMisc=exports.UIMisc||(exports.UIMisc={})); +"use strict";exports.__esModule=!0;var UIMisc,PasswordMeter=require("./PasswordMeter"),RuleFunctions=require("./rulefunctions"),Constants=require("./constants");!function(e){var t,s,i,o=function(){function e(e){this.pwWhenModalOpened="",this.tookSuggestion=!1,this.previouslyRated="",this.heuristicMapping={},this.feedbackMapping={},this.recommendedFixes={},this.recommendedFixesTries={},this.previousCandidate={},this.fixedpwMapping={},this.deltaHighlighted={},this.inCompliance=!1;var t=PasswordMeter.PasswordMeter.instance;this.helper=t.getHelper(),this.$=t.getJquery(),this.verboseMode=e}return e.prototype.onReady=function(){this.$(".pop").fadeIn(),this.$("#showHidePWNonModal").prop("checked",!1),this.toggleShowHideNonModal(),this.spawnRating()},e.prototype.toggleShowHideNonModal=function(){this.$("#showHidePWNonModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWModal").prop("checked",!1)),this.spawnRating()},e.prototype.toggleShowHideModal=function(){this.$("#showHidePWModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWNonModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWNonModal").prop("checked",!1)),this.spawnRating()},e.prototype.storepw=function(){var e=this.$("#pwbox").val();this.pwWhenModalOpened=e,this.$("#pwboxModal").val(e)},e.prototype.enableDiscard=function(){this.$("#pwboxModal").val()===this.pwWhenModalOpened?(this.$("#discardButton").hide(),this.$("#keepButton").html("OK")):(this.$("#discardButton").show(),this.$("#keepButton").html("Keep Changes"))},e.prototype.keeppw=function(){this.$("#pwbox").val(this.$("#pwboxModal").val())},e.prototype.discardpw=function(){this.$("#pwbox").val(this.pwWhenModalOpened)},e.prototype.fixPWNonModal=function(){this.tookSuggestion=!0;var e=this.$("#nonmodalFixedPW").text();this.$("#pwbox").val(e),this.spawnRating()},e.prototype.fixPWModal=function(){this.tookSuggestion=!0;var e=this.$("#modalFixedPW").text();this.$("#pwboxModal").val(e),this.spawnRating(),this.enableDiscard()},e.prototype.showModal=function(){this.storepw(),this.$("#discardButton").hide(),this.$("#keepButton").html("OK"),this.$("#myModal").modal("show")},e.prototype.mayberate=function(){this.$("#pwbox").val()!==this.previouslyRated&&(this.previouslyRated=this.$("#pwbox").val(),this.spawnRating())},e.prototype.continueCheck=function(e){var t=!0;e&&(this.$("#usernamebox").val().length<1?(this.$("#usernameTooShort").show(),t=!1):this.$("#usernameTooShort").hide());this.inCompliance?(this.$("#feedbackHeaderText").css({color:"","font-weight":""}),this.$("#passwordNonCompliant").hide()):(t=!1,this.$("#confirmDoesNotMatch").hide(),e&&(this.$("#feedbackHeaderText").css({color:"red","font-weight":"bold"}),this.$("#passwordNonCompliant").show())),this.$("#pwbox").val()!==this.$("#confirmbox").val()?(t=!1,e&&this.inCompliance&&this.$("#confirmDoesNotMatch").show()):this.$("#confirmDoesNotMatch").hide(),e&&t&&alert("this would be submitted")},e.prototype.scaleGuessNumByMeterStringencyFactor=function(e){return e>0?e*Constants.Constants.METER_STRINGENCY_SCALE_FACTOR:e},e.prototype.spawnRating=function(){var e="",t=PasswordMeter.PasswordMeter.instance.getNN();e=this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown?this.$("#pwboxModal").val():this.$("#pwbox").val();var s=this.$("#usernamebox").val(),i=0,o=t.getNeuralNetNum(e);void 0===o?(t.setNeuralNetNum(e,-1),t.queryGuessNumber(e,!1)):o>=0&&i++,void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!0):this.heuristicMapping[e]>=0&&i++,0!==e.length&&t.heardFromNn()&&2!==i||this.displayRating(e)},e.prototype.generateCandidateFixed=function(e,t,s){var i=[];if(void 0===this.deltaHighlighted[e])for(var o=0;o=65&&n.charCodeAt(r)<=90?(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)+32)),i[r]=1):n.charCodeAt(r)>=97&&n.charCodeAt(r)<=122&&(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)-32)),i[r]=1)}else if(2===h||3===h){var l=32+Math.floor(95*Math.random()),p=Math.floor(n.length*Math.random());n.charCodeAt(p)!==l&&(i[p]=1),n=n.replaceAt(p,String.fromCharCode(l))}else if(h>=4){l=32+Math.floor(95*Math.random()),p=Math.floor((n.length+1)*Math.random());n=n.slice(0,p)+String.fromCharCode(l)+n.slice(p),i=i.slice(0,p).concat(1,i.slice(p))}var d=PasswordMeter.PasswordMeter.instance.getNN();void 0===d.getNeuralNetNum(n)&&(d.setNeuralNetNum(n,-1),d.queryGuessNumber(n,!0));var u=this.$("#usernamebox").val();return RuleFunctions.RuleFunctions.verifyMinimumRequirements(n,u).compliant?(this.recommendedFixes[s]=n,this.deltaHighlighted[n]=i,this.verboseMode&&console.log("identified "+n+" as a potential fix for "+s),void 0===this.recommendedFixesTries[s]?this.recommendedFixesTries[s]=1:this.recommendedFixesTries[s]=this.recommendedFixesTries[s]+1,this.spawnFixedRating(n)):++t<8&&this.generateCandidateFixed(e,t,s),1},e.prototype.spawnFixedRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=this.$("#usernamebox").val();void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!1):t.getNeuralNetNum(e)>=0&&this.heuristicMapping[e]>=0&&this.synthesizeFixed(e)},e.prototype.synthesizeFixed=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0,o=!1;void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(i++,s=this.heuristicMapping[e]);var n=t.getNeuralNetNum(e),h=this.scaleGuessNumByMeterStringencyFactor(n);if(void 0!==n&&h>=0&&isFinite(h)&&(i++,(0===s||s>0&&h=67){for(var a in this.verboseMode&&console.log(e+" is a plausible fix above the 2/3rds threshold"),this.recommendedFixes)if(this.recommendedFixes[a]===e&&void 0===this.fixedpwMapping[a]){var r=0;void 0!==this.heuristicMapping[a]&&this.heuristicMapping[a]>=0&&(r=this.heuristicMapping[a]);var l=t.getNeuralNetNum(a),p=this.scaleGuessNumByMeterStringencyFactor(l);void 0!==l&&p>=0&&isFinite(p)&&(0===r||r>0&&pr+15?(this.fixedpwMapping[a]=e,this.verboseMode&&console.log("mapping "+a+" to "+e),o=!0):this.verboseMode&&console.log("not mapping "+a+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s)}return o&&this.spawnRating(),1}var d=this.$("#pwbox").val();return this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown&&(d=this.$("#pwboxModal").val()),this.recommendedFixes[d]===e&&2===i&&void 0===this.fixedpwMapping[d]&&void 0!==this.recommendedFixesTries[d]&&this.recommendedFixesTries[d]<8&&(this.verboseMode&&console.log("trying again on "+e+" as current password is "+d),this.generateCandidateFixed(e,0,d)),1},e.prototype.redundant=function(e,t){e=e.toLowerCase();for(var s=0;s0&&e.length>0&&(t[s].indexOf(e)>=0&&e.length>=.7*t[s].length||e.indexOf(t[s])>=0&&t[s].length>=.7*e.length))return!0;return!1},e.prototype.queryHeuristicGuessNumber=function(e,t,s){var i=e,o=[],n=[],h=[],a=[],r=RuleFunctions.RuleFunctions.contextual(e,[t]);void 0===(e=r.remaining)&&(e="");var l=RuleFunctions.RuleFunctions.blacklist(e);void 0===(e=l.remaining)&&(e="");for(var p=RuleFunctions.RuleFunctions.pwLength(e),d=RuleFunctions.RuleFunctions.characterClasses(e),u=RuleFunctions.RuleFunctions.duplicatedCharacters(e),c=RuleFunctions.RuleFunctions.repeats(e),m=RuleFunctions.RuleFunctions.keyboardPatterns(e),g=RuleFunctions.RuleFunctions.repeatedSections(e),x=RuleFunctions.RuleFunctions.structurePredictable(e),b=RuleFunctions.RuleFunctions.uppercasePredictable(e),w=RuleFunctions.RuleFunctions.digitsPredictable(e),$=RuleFunctions.RuleFunctions.symbolsPredictable(e),v=RuleFunctions.RuleFunctions.countUC(e),M=RuleFunctions.RuleFunctions.countLC(e),y=RuleFunctions.RuleFunctions.countDIGS(e),f=RuleFunctions.RuleFunctions.countSYMS(e),T=RuleFunctions.RuleFunctions.identifyDates(e),R=(RuleFunctions.RuleFunctions.verifyMinimumRequirements(e,t),RuleFunctions.RuleFunctions.alphabeticSequenceCheck(e)),F=RuleFunctions.RuleFunctions.commonSubstringCheck(e),C=RuleFunctions.RuleFunctions.combinedDictCheck(e),N=e.listSubstringsNoFilter(4),k=RuleFunctions.RuleFunctions.commonPwCheck(N),W=[1.53,.3129,.9912,.04637,-.03885,-.1172,-.2976,-8581e-7,-.3008,-.5566,0,.9108,.7369,.7578,0,-.1213,-.2402,-.1364,-.5534,1.927,.001496,-.3946],P=[1,p.length,d.count,u.count,c.count,m.score,g.count,x.score,b.score,w.score,$.score,v.count,M.count,y.count,f.count,T.count,R.count,F.count,C.length,C.dictionaryTokens,C.substitutionCommonness,k.length],H=W[0],S=1;S100&&(H=100),r.publicText.length>0&&(o.push(r.publicText),n.push(r.sensitiveText),h.push(r.reasonWhy),a.push(r.problemText)),l.publicText.length>0&&(o.push(l.publicText),n.push(l.sensitiveText),h.push(l.reasonWhy),a.push(l.problemText)),C.publicText.length>0&&!this.redundant(C.problemText,a)&&(o.push(C.publicText),n.push(C.sensitiveText),h.push(C.reasonWhy),a.push(C.problemText)),m.publicText.length>0&&(o.push(m.publicText),n.push(m.sensitiveText),h.push(m.reasonWhy),a.push(m.problemText)),c.publicText.length>0&&(o.push(c.publicText),n.push(c.sensitiveText),h.push(c.reasonWhy),a.push(c.problemText)),T.publicText.length>0&&(o.push(T.publicText),n.push(T.sensitiveText),h.push(T.reasonWhy),a.push(T.problemText)),g.publicText.length>0&&(o.push(g.publicText),n.push(g.sensitiveText),h.push(g.reasonWhy),a.push(g.problemText)),R.publicText.length>0&&(o.push(R.publicText),n.push(R.sensitiveText),h.push(R.reasonWhy),a.push(R.problemText)),k.publicText.length>0&&!this.redundant(k.problemText,a)&&(o.push(k.publicText),n.push(k.sensitiveText),h.push(k.reasonWhy),a.push(k.problemText)),b.publicText.length>0&&(o.push(b.publicText),n.push(b.sensitiveText),h.push(b.reasonWhy),a.push(b.problemText)),w.publicText.length>0&&(o.push(w.publicText),n.push(w.sensitiveText),h.push(w.reasonWhy),a.push(w.problemText)),$.publicText.length>0&&(o.push($.publicText),n.push($.sensitiveText),h.push($.reasonWhy),a.push($.problemText)),u.publicText.length>0&&(o.push(u.publicText),n.push(u.sensitiveText),h.push(u.reasonWhy),a.push(u.problemText)),p.publicText.length>0&&(o.push(p.publicText),n.push(p.sensitiveText),h.push(p.reasonWhy)),f.publicText.length>0&&(o.push(f.publicText),n.push(f.sensitiveText),h.push(f.reasonWhy)),v.publicText.length>0&&(o.push(v.publicText),n.push(v.sensitiveText),h.push(v.reasonWhy)),y.publicText.length>0&&(o.push(y.publicText),n.push(y.sensitiveText),h.push(y.reasonWhy)),M.publicText.length>0&&(o.push(M.publicText),n.push(M.sensitiveText),h.push(M.reasonWhy)),F.publicText.length>0&&!this.redundant(F.problemText,a)&&(o.push(F.publicText),n.push(F.sensitiveText),h.push(F.reasonWhy)),x.publicText.length>0&&(o.push(x.publicText),n.push(x.sensitiveText),h.push(x.reasonWhy)),this.heuristicMapping[i]=H,this.feedbackMapping[i]=JSON.stringify({publictips1:o[0],publictips2:o[1],publictips3:o[2],sensitivetips1:n[0],sensitivetips2:n[1],sensitivetips3:n[2],reasonWhy1:h[0],reasonWhy2:h[1],reasonWhy3:h[2]}),s?(this.displayRating(i),w.fixedPw.length>0?(this.previousCandidate[i]=w.fixedPw,this.deltaHighlighted[w.fixedPw]=w.deltas):$.fixedPw.length>0&&(this.previousCandidate[i]=$.fixedPw,this.deltaHighlighted[$.fixedPw]=$.deltas)):this.synthesizeFixed(i)},e.prototype.displayRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0;if(e.length>0){void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(s=this.heuristicMapping[e],i++);var o=t.getNeuralNetNum(e),n=this.scaleGuessNumByMeterStringencyFactor(o);void 0!==o&&n>=0&&isFinite(n)&&(i++,(0==s||s>0&&n(Why?)
"),p+="

 

To make it even better:",this.$("#feedbackHeaderText").html(p),this.$("#feedbackHeaderTextModal").html(p)}else{var d="Your password appears strong.";a.remindAgainstReuse&&(d+=" Make sure you use it only for this account. (Why?)"),this.$("#feedbackHeaderText").html(d),this.$("#feedbackHeaderTextModal").html(d)}if(this.$(".nonmodalColorCell").show(),this.$(".modalColorCell").show(),this.$(".modalColorCellSpacer").show(),this.$(".recommended").show(),!0===this.$("#showHidePWNonModal").prop("checked")?(this.$(".fixedPWavailablePortal").hide(),this.$(".concreteSuggestionDiv").show(),this.$("#tipText1").html(h.sensitivetips1),this.$("#tipText2").html(h.sensitivetips2),this.$("#tipText3").html(h.sensitivetips3),this.$("#suggestion1").html(h.sensitivetips1),this.$("#suggestion2").html(h.sensitivetips2),this.$("#suggestion3").html(h.sensitivetips3),this.$("#sensText1").html(h.reasonWhy1),this.$("#sensText2").html(h.reasonWhy2),this.$("#sensText3").html(h.reasonWhy3)):(this.$(".fixedPWavailablePortal").show(),this.$(".concreteSuggestionDiv").hide(),this.$("#tipText1").html(h.publictips1),this.$("#tipText2").html(h.publictips2),this.$("#tipText3").html(h.publictips3),this.$("#suggestion1").html(h.publictips1),this.$("#suggestion2").html(h.publictips2),this.$("#suggestion3").html(h.publictips3),this.$("#sensText1").html(h.reasonWhy1),this.$("#sensText2").html(h.reasonWhy2),this.$("#sensText3").html(h.reasonWhy3)),void 0!==this.fixedpwMapping[e]){for(var u="",c=this.deltaHighlighted[this.fixedpwMapping[e]],m=this.fixedpwMapping[e],g=0;g"+m[g].escapeHTML()+"":u+=m[g].escapeHTML();this.$(".fixedPW").html(u)}else this.$(".recommended").hide();s<=66?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show()):s<100?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show(),this.tookSuggestion&&(this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())):(this.$("#nonmodalFeedbackTable").hide(),this.$("#modalFeedbackTable").hide(),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())}else{this.inCompliance=!1,0!==e.length&&t.heardFromNn()&&2!==i||this.displayBar(s,!1),this.$("#confirmpw").hide(),this.$(".detailedFeedback").hide(),this.$(".portalToGenericAdviceModal").show(),this.$(".explainWhy").hide();var x="";(a=PasswordMeter.PasswordMeter.instance.getConfig()).remindAgainstReuse&&(x="Don't reuse a password from another account! (Why?)

 

");var b="Your password must:";this.$("#feedbackHeaderText").html(x+b),this.$("#feedbackHeaderTextModal").html(x+b),this.$("#nonmodalFeedbackTable").show(),this.$(".recommended").hide();var w=[],$=l.detail;for(var v in $.compliance)$.compliance[v]||w.push($.explanation[v]);this.$(".nonmodalColorCell").hide(),this.$(".modalColorCell").hide(),this.$(".modalColorCellSpacer").hide(),this.$(".nonmodalRow").hide(),this.$(".modalRow").hide();for(var M=0;M100&&(e=100);var s=e/100,i="rgb(160,160,160)";t&&s<.45?i="rgb("+Math.round(255)+","+Math.round(s/.45*140)+",0)":t&&s>=.45&&s<.65?i="rgb("+Math.round(255)+","+Math.round((s-.45)/.2*75+140)+",0)":t&&(i="rgb("+Math.round(255-(s-.65)/.35*205)+","+Math.round(215-(s-.65)/.035)+",0)"),this.$("#cups-passwordmeter-span").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span").css("background-color",i),this.$("#cups-passwordmeter-span-modal").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span-modal").css("background-color",i)},e.prototype.getMaxOfArray=function(e){return Math.max.apply(null,e)},e.prototype.expandHelpBut=function(){this.$("#expandHelpDiv").show(),this.$("#helpButton").hide()},e.prototype.modalShowCheck=function(){"text"==this.$("#pwbox").prop("type")?(this.$("#myModal").show(),this.storepw()):this.$("#expandHelpDiv").is(":visible")?(this.$("#myModal").show(),this.storepw()):this.expandHelpBut()},e.prototype.closeDiv=function(e){this.$(e).hide()},e.prototype.deselect=function(e){null==this.$.fn.slideFadeToggle&&(this.$.fn.slideFadeToggle=function(e,t){return this.animate({opacity:"toggle",height:"toggle"},"fast",e,t)}),this.$(".pop").slideFadeToggle(function(){e.removeClass("selected")})},e}();e.UIMisc=o,t=PasswordMeter.PasswordMeter.instance,s=t.getJquery(),i=new o(!1),t.setUI(i),s(document).ready(function(){s("#showpassword").prop("checked",!1),s("#showpassword").click(function(){document.getElementById("hide-show-label").textContent="Hide Password",s("#cbbutton").css("background-color","#f5f5f5"),"password"==s("#pwbox").prop("type")?s("#pwbox").prop("type","text"):(s("#pwbox").prop("type","password"),document.getElementById("hide-show-label").textContent="Show Password",s("#cbbutton").css("background-color","#f5f5f5"))})}),s(document).ready(function(){var e=s("#pwboxModal");s("#tip1, #sensText1").mouseover(function(){e.addClass("problemColor")}),s("#tip2, #sensText2").mouseover(function(){e.addClass("problemColor")}),s("#tip3, #sensText3").mouseover(function(){e.addClass("problemColor")})}),s(document).ready(function(){i.onReady()})}(UIMisc=exports.UIMisc||(exports.UIMisc={})); },{"./PasswordMeter":3,"./constants":6,"./rulefunctions":10}]},{},[3,4,5,6,7,8,9,10,11,12]); diff --git a/src/package.json b/src/package.json index 4a27e50..0b5c5a1 100644 --- a/src/package.json +++ b/src/package.json @@ -8,6 +8,7 @@ "@types/jquery": "latest", "@types/lz-string": "latest", "@types/node": "latest", + "@types/bootstrap": "latest", "babel-cli": "^6.26.0", "babel-preset-es2015": "^6.24.1", "babelify": "7.3.0", diff --git a/src/ts/ui-misc.ts b/src/ts/ui-misc.ts index 2557377..09b73f2 100644 --- a/src/ts/ui-misc.ts +++ b/src/ts/ui-misc.ts @@ -135,6 +135,12 @@ export module UIMisc { this.$("#pwbox").val(this.$("#pwboxModal").val()); } + // They chose to discard their modal-modified password, + // so transfer the original password back to the main window + discardpw(): void { + this.$("#pwbox").val(this.pwWhenModalOpened); + } + // If they click the concrete suggestion in the non-modal, put it in the password field fixPWNonModal(): void { // Note for later that they have taken a suggestion @@ -159,7 +165,7 @@ export module UIMisc { this.storepw(); this.$("#discardButton").hide(); this.$("#keepButton").html("OK"); - this.$("#myModal").show(); + this.$("#myModal").modal("show"); } // To save computation, only rate the password if it has changed From 3b875668e690b3163fb34e6c65ebb1c37a093593 Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Mon, 4 Mar 2019 16:13:15 -0500 Subject: [PATCH 12/45] Added config option for randomizing the order of character classes in meter feedback. Also added option for specifying whether concrete password suggestions are generated/provided by the meter. --- src/PasswordMeter.js | 6 +- src/ts/config.ts | 4 ++ src/ts/rulefunctions.ts | 64 +++++++++++--------- src/ts/ui-misc.ts | 126 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 167 insertions(+), 33 deletions(-) diff --git a/src/PasswordMeter.js b/src/PasswordMeter.js index 533b84c..f9cfc06 100644 --- a/src/PasswordMeter.js +++ b/src/PasswordMeter.js @@ -11,7 +11,7 @@ class PasswordLeaks{constructor(){this.hibpCache={},this.hibpTimings={}}sha1(e){ Array.prototype.toHumanString=function(){var t=this.length;if(0==t)return"(empty)";if(1==t)return this[0].toString();for(var r=this[0].toString(),i=1;i=t;e--)for(var s=0;s=e)for(var h=0;h+e<=this[s].length;h++)i.push(this[s].substring(h,h+e));return i}; },{}],5:[function(require,module,exports){ -"use strict";var Config;exports.__esModule=!0,function(e){e.passwordMeterDefaultConfig={colors:{compliant:"#006600",noncompliant:"#660000"},symbols:{compliant:"✔ ",noncompliant:"❑ "},remindAgainstReuse:!0,ignoredWords:["mechanical","amazon","mturk","turk","survey","bonus","qualtrics","study","carnegie","mellon","university"],length:{active:!0,minLength:8,maxLength:0},classCount:{active:!1,minCount:1,maxCount:4},classRequire:{active:!1,upperCase:!1,lowerCase:!0,digits:!0,symbols:!1},classAllow:{active:!1,upperCase:!0,lowerCase:!0,digits:!0,symbols:!0},forbidChars:{active:!1,list:[]},repeatChars:{active:!0,limit:3},sameChars:{active:!1,limit:3,lengthException:20},usernameDifference:{active:!0,limit:1},minLogNnGuessNum:{active:!1,threshold:7,rejectionFeedback:"Not be similar to extremely common passwords"},prohibitKnownLeaked:{active:!0,smallestLength:5},blacklist:{active:!1,blacklistFile:"blacklist-cmu-compressed.txt",caseSensitive:!1,stripDigitsSymbolsFromPassword:!1,checkSubstrings:!1,checkSubstringLength:5,lengthException:20},neuralNetworkConfig:{intermediate:"basic_3M.info_and_guess_numbers.no_bloomfilter.json",file:"basic_3M.weight_arch.quantized.fixed_point1000.zigzag.nospace.json",zigzag:!0,scaleFactor:300}}}(Config=exports.Config||(exports.Config={})); +"use strict";var Config;exports.__esModule=!0,function(e){e.passwordMeterDefaultConfig={provideConcretePasswordSuggestions:!0,randomizeOrderCharClassRequirement:!0,colors:{compliant:"#006600",noncompliant:"#660000"},symbols:{compliant:"✔ ",noncompliant:"❑ "},remindAgainstReuse:!0,ignoredWords:["mechanical","amazon","mturk","turk","survey","bonus","qualtrics","study","carnegie","mellon","university"],length:{active:!0,minLength:8,maxLength:0},classCount:{active:!1,minCount:1,maxCount:4},classRequire:{active:!1,upperCase:!1,lowerCase:!0,digits:!0,symbols:!1},classAllow:{active:!1,upperCase:!0,lowerCase:!0,digits:!0,symbols:!0},forbidChars:{active:!1,list:[]},repeatChars:{active:!0,limit:3},sameChars:{active:!1,limit:3,lengthException:20},usernameDifference:{active:!0,limit:1},minLogNnGuessNum:{active:!1,threshold:7,rejectionFeedback:"Not be similar to extremely common passwords"},prohibitKnownLeaked:{active:!0,smallestLength:5},blacklist:{active:!1,blacklistFile:"blacklist-cmu-compressed.txt",caseSensitive:!1,stripDigitsSymbolsFromPassword:!1,checkSubstrings:!1,checkSubstringLength:5,lengthException:20},neuralNetworkConfig:{intermediate:"basic_3M.info_and_guess_numbers.no_bloomfilter.json",file:"basic_3M.weight_arch.quantized.fixed_point1000.zigzag.nospace.json",zigzag:!0,scaleFactor:300}}}(Config=exports.Config||(exports.Config={})); },{}],6:[function(require,module,exports){ "use strict";var Constants;exports.__esModule=!0,function(L){L.LOWERCASE_LETTERS=new RegExp("[a-z]"),L.LOWERCASE_LETTERS_GLOBAL=new RegExp("[a-z]","g"),L.UPPERCASE_LETTERS=new RegExp("[A-Z]"),L.UPPERCASE_LETTERS_GLOBAL=new RegExp("[A-Z]","g"),L.NONALPHA=new RegExp("[^A-Za-z]"),L.DIGITS=new RegExp("[0-9]"),L.DIGITS_GLOBAL=new RegExp("[0-9]","g"),L.SYMBOLS=new RegExp("[^A-Za-z0-9]"),L.SYMBOLS_GLOBAL=new RegExp("[^A-Za-z0-9]","g"),L.startASCII=32,L.endASCII=126,L.METER_STRINGENCY_SCALE_FACTOR=67/12,L.commonStructures=["LLLLLL","LLLLLLLL","LLLLLLL","DDDDDDDD","DDDDDD","LLLLL","DDDDDDD","LLLLLLDD","LLLLLLLLL","LLLL","DDDD","LLLLLLLD","LLLLLD","LLLLLLLLLL","LLLLLDD","LLLLDDDD","LLLLLLD","LLLLDD","LLLLLDDD","DDDDD","LLLDDD","LLLDDDD","DDDDDDDDD","LLLLLLLLLLL","DDDDDDL","LLLLLDDDD","LLLLDDD","LLLLLLLDD","DDDDDDDDDD","LLLLLLLLLLLL","LLLLLLDDDD","DDDDDDDDL","UUUUUUUU","LLLLLLDDD","LLDDDD","DDDDDDDDDDD","ULLLLL","LLLLLLLLDD","LLLLLLLLD","ULLLLLLL","UUUUUU","ULLLLLLD","LLLLLLLLLLLLL","ULLLLLL","LLLLLLLDDDD","LLLLLLLDDD","ULLLLLD","DDDDLLLL","LLLLLLLLLLLLLL","LLLLD","LLDDDDDD","DLLLLLLL","UUUUUUU","LLLLLLLLLD","DDLLLLLL","DDDDLL","DDDDDDLL","LDDDDDD","LLLDDDDD","ULLLLLDD","LLLLLLLLDDDD","DDDLLL","LLLLLLLLLDD","DDDDDDDL","LLLLLLLLLLLLLLL","DDDDLLL","DULLLLL","DULLLLLL","LLLDDDDDD","ULLLLD","LLLLLLLLDDD","DLLLLL","DDDDDDLLL","LLLLDLLL","LLLLDDDDDD","ULLLL","LLLDD","LDDDDDDD","LLLDLLLL","LLLLLLLLLLLLLLLL","DDLLLL","LLLDDLLL","DDDDDDDDDDDD","DLLLLLL","DDLLLLL","LLLLLDLL","LLLLLLLLLLDD","LLDDDDD","LLLLLDDDDDD","DDDLLLLL","LDDDDDDDD","DDDDDDLLLL","UUUUU","LLLLLLDL","LDDDDD","ULLLDDDD","ULLLLDDD","ULLLLLLLL","LLLLLLLLLDDD","DDDDDL","LLLLLLDDDDDD","LLLLLLLLLLDDDD","DULLLL","ULLLLDD","LLLLDDDDD","LLLLDL","LDLLLLLL","LLDLLLLL","LLLDLL","LLDLLL","LLLLLLLLLLD","LLLDLLL","LLLLLDDDDD","DDDDLLLLL","LDLDLDLD","DDDDDDDDLL","DDDDDDDDLLL","LLLLLLLLLDDDD","DDDLLLL","DDDDDDDDLLLL","DLLLLLLD","LLDDD","LDLDLD","LLLD","DDDDDDDDDL","DLLLDLLL","LDLLLL","LLLLDDDDDDDD","LLLLDLL","UUUU","ULLLLDDDD","LLLLLDL","ULLLLLLDD","DDLLLLDD","LLLLLLDDDDD","LLDDLL","DDDDLLLLLL","DDDDDLLL","DDDDDDDDDDDL","DDDDDDDDDDL","LLLDDDDDDDD","LDDDDL","LLLLDDLL","ULLL","LLLLLLLLLLLDD","LLLLLLLLLLLLLLLLL","DDDDDDLLLLL","LLLLLLLLLLLLDD","LLLLLLLLLLLD","ULLLLLDDDD","LDDDLL","ULLLLLLLLL","ULLLDD","LLLDDDDDDD","LLDDDDDDD","LLLDLLLD","DDLLLDD","DDDDDDDLL","LLDDDDDDDD","ULLLLLLLD","LLLLLDDL","DLDLDLDL","LLDDDDLL","DDDDDDDLLL","DLDLDL","ULLLLLDDD","LLLLLDDDDDDDD","UUUUUUDD","LLDLLLL","LLLLLLLLLLDDD","LDDDDDDL","DDDDDLL","ULLLD","LLLLDDDDDDD","LLDDLLLL","LLLDDDLL","DDDDDDLLLLLL","DLLLLD","DLLLL","LLLLLLLLLLLLLLLLLL","LLLDDLL","ULLLLLLLDD","LLDDLLDD","UUUUUUUUU","LLLLLLLLLLLDDDD","DULLL","ULLLDDD","DDLLLLLLL","LLL","UUUUDDDD","DDLLDD","DDDLLLLLL","DDDDDDDDLLLLL","LLLDDL","DLLLLLD","DDDDDDDLLLL","LDLLLLL","UUUDDDD","LLLLLLLDDDDDD","DLLLLLLLL","LLLLLLLLLLLDDD","LLLLLLLLLLLLLDD","LLLLLLDDDDDDDD","UUUUUD","UUUUDD","LDDLLLLL","LLLLDLLLL","DDDDLLLLLLL","LLLLLDDDDDDD","DDDDL","UUUDDD","LLLLLLLLLLLLD","UUDDDD","UUUUUUUD","LLLLLLLLLLLLDDDD","LDLDLDLDLD","LDDD","LLDLLD","DDDDDDU","LLLLDDL","LLLDDDDL","UUUUUDD","LLLLLLLDDDDD","DDLLLLLDD","UDDDDDD","LLDD","LDDDD","LLDDDLL","ULLLULLL","DDDDLLLLLLLL","LDLLLDLL","DDDDDLLLL","LDDLLL","LLLLLDLD","ULLLLLLDDD","ULLLLU","DDLLL","LLDDLLL","ULLLLLLDDDD","LDDLDD","LDLLDL","ULLLLLLLLLL","LLDLLLDL","","LLLLDLLD","LLDLLDLL","LLLDL","LLDLLLLD","ULDDDDDD","ULLULL","LLLDDDLLL","UUUUUDDD","LLDLL","UUUUUUD","LLLLDDDL","LLLLLLLLLLLLLD","LLLLLLLLDDDDDD","UUUUUUUUUU","LDLLLLDL","LLLLDLDL","LDLLDLLL","LLLLLLLLLLLLLLLLLLL","DLDLLLLL","DDDLLLDDD","DDDDDLLLLL","LLLDDDL","DLLLLDLL","LLLDLLDL","LLLLLLLLLLLLDDD","LDDDDDDDDD","ULLLLLLLLD","LDLDLLLL","LLLLLLLLLLLLLLDD","DDLLLLLLLL","LLDLDLLL","DLLLLLDL","DDDDDDDDU","DDDDDDDDLLLLLL","LDDDDDDDDDD","LDLLLLLD","DDLLLLLLDD","LLDDDL","LLLDLDLL","DLLL","ULLDDDD","DDLLDLLL","DLLLLLLLLL","DLLDLLLL","DDDLL","LLLLLLDDDDDDD","DDD","LLLLLLLDDDDDDDD","LLLDLD","DDLLLLLD","DLLDLL","LLLLLLDLL","UUDDDDDD","DDDDDDDDDLLL","LLDDDLLL","ULLLLLLLLDD","ULULLL","DDLLDDLL","DLLLLLDD","LDLLL","DDDDDDDLLLLL","DDLDDLDDL","ULULUL","ULLLUL","LDLLLD","UDDDDDDDD","LLLLLDLLL","LDLDLL","ULLLLULL","DDDDDDDDDDDDD","ULLLLLLLDDDD","UUUUDDD","LLLLLLLLLLLLLLLLLLLL","DDDDDDDDDDDDDD","DDDLDDD","DDLDDL","DLLLDL","ULLLUU","DLDLDLDLDL","ULLLLLLLDDD","ULLDDD","LLLLLLDLLL","DDDLLLLLLL","DDDDDDDDDDLL","DDLLLDDDD","UDDDDDDD","ULUULL","ULULLU","ULLLLLLLLLD","ULUULU","DDDDDDDDDLL","LLLLLDLLLL","DDDDDDDDDDDLLLL","ULUUUL","ULUUUU","ULLUUU","ULLULU","ULLUUL","LLDLDL","LLLLLLLDL","LLLLLLLS","LLDL","LLLLLLLLLLLLLLD","LDDDDDDDDL","LDDDLLL","LLLLLLS","ULULUU","LDDDDDDDDDDD","LLLLLLLLLLLLLDDD","LLLLLLLLLDDDDDD","DDDDDDLLLLLLL","DDDDDDDDDDLLL","LLLDDLLD","DDDLLDDD","LDDLDDLDD","LLLDLLLLL","ULLLLLLLLLLL","LLLLDDLLL","DDLLLD","LLLDDDDLLL","DDDDDDDDDDDLLL","LDLDLDL","LLLLLLLLDDDDD","LLLLSLLL","LLLLLLLLDDDDDDDD","DLLLDD","LLLLDLD","DDDDDDDDDDDDDDDD","DLDLLL","UUUUUDDDD","DDDDDDDDDDLLLL","LLLLDLLLLL","DLLLD","DDDDDDDU","DDDDDDUU","DDDLLLDD","LLDDDDL","DLLLLLLLD","LLLSLLL","LDDLLLL","ULLLDDDDDD","LLLLLLLLLLLLLDDDD","DDLLLLD","ULLULLLL","LLLDDLLLL","LLLLDDLLLL","DDDLLLLDDD","LDLL","LDDDDDDDL","LLLDLLLLLL","DDDDDDDDDLLLL","LDDDLLDD","LDDDLLLL","LLDDLLLD","DDDDDDDDDDDLL","LLLDLLDD","DDLL","DDDDUU","DDLDDLDD","DDDDDDLLLLLLLL","DDLDDDD","DDDDLLDD","LLLLLS","ULLDDDDDD","LLDLLDL","LDLDLDLL","LLLLDLDD","LDLLLLLLL","DDDLLLD","LLDLLLDD","ULLDDDDD","ULLLLLLU","ULDDDD","LLLDDLLLDD","UUUUUUUDD","LLLLLLLDDDDDDD","UUUDDDDD","LLDLLLD","UUDDDDD","LDLDL","UUUUUUUUUUU","LDLLLLDD","LLDLLLLLL","LLLDDLDL","DLLLDLL","DLLLLDD","LLLLLSDD","DDDDULLL","DDLLDDDD","LLLLLLLDLL","DLLLLDL","LLLLLLLLDL","LDLLLDL","DLDLDLD","LLDLDD","LLLDDDDDDDDD","ULLLLDDDDDD","LDDDLDDD","DDDDDDDDDDDDDDD","DDDDDDDDDDDDL","ULLULLL","LDLDLDLDLDLD","LLLDLLD","DDDDDDDLLLLLL","LDDDDDL","DDDLLLLLLLLL","LLDDL","LLLLLLDDL","LDLLDLL","LDLLDLDL","LLLLLLLLLLLLLLLDD","UULLLLLL","ULLLLLLLLLDD","LDDDDLL","LDLLDLLD","DDDLDD","DDLLLLLLLDD","LLLLLLLLS","UUUUUUDDDD","LLLLDDLD","UDDDDD","LLDDLDLL","DDDDDDDDLLLLLLL","UUUDDDDDD","DDDDLDDDD","LLDDLD","LLLLLDDLLL","DDLLLDDD","UUUUUUDDD","LLLLLDDLL","LLLLDDDDDDDDDD","DDDLLLLLLLL","LLLLLLLLLDDDDD","LDLLDD","LLLLLLLLLLLLLLLLLLLLL","LLLLLLLLLLLLLLLD","LLLSLLLL","DDDDLD","DDLDDD","DDDDUUUU","DLDLL","LDLLLLD","DLDLLLDL","LLLLSLLLL","LDLDLLDL","DDLDLLLL","DDDDDDDDDDDLLLLL","LLLLLLLLLLDDDDDD","UUUUUUUUUUUU","LLLDLDL","LLLLDDDDDDDDD","DDDDDLLLLLL","DDULLLLL","ULLLULL","LLLLLLLLLLLLLLDDDD","DLLDLLDL","LLLDLDLD","LLLDDDDDDDDDD","DDDDLLLLDDDD","LLLLSL","LDLDLLL","DLLLLLLLLD","LDLLLDLD","DDDDLDD","ULDDDLL","LLDLLLLLLL","LLLLLLSDD","DLDLLLL","ULLLLLLLLDDD","LLDLDLL","DDDDDDS","DDLLLLLLLLL","LDLLLDDL","ULLLLDLL","DDLLLDLL","DDLLDL","LLLLLSLLL","DLLLDDLL","LDLDLDLDL","DLLLDLDL","DLLDLLL","DLLDL","DLDLDLLL","LLDDLLD","DDDLLLLLDDD","DDSDDSDDDD","LLDDLLDL","DLLDLLLD","DLLLDDD","LLDLLDDL","LLLLLU","DLLDLDLL","LDDLDL","LDDLLD","LLDLLDLD","DDLLDDD","DDDDLLLD","DLLDDL","ULLLLLDDDDDD","DDDLDDDL","DDLLD","LLLLLDLLLLL","LLLDDLDD","LLDLDLLD","LDDDDLLL","DLLDDLLL","LLLLDDDDDDDDDDD","DLDLLDLL","LLDDDDDDDDD","DDDDDDUUU","DLDDLLLL","DDDLLD","LDDLLLLD","LDLLLLLLLL","DDDDUUU","LLDLDLDL","DLLLLDLD","DDLLLLDDDD","ULLLLDDDDD","LUULDDL","ULLLDDDDD","LDDLLLDL","ULLLLLLLLDDDD","DDLLLLDL","DLLLLLLLLLL","ULLLLLU","LLLLLSLL","DLLLLDDL","LDLDLLLD","DLDLLLLD","UUUDD","LDLDDLLL","LLLLLLDLLLL","LDLLD","DDDDDDUL","LDLD","DLLLLDDD","LDLLDDLL","UUUUD","LDDLLDLL","LLLLLLLLDDDDDDD","LLLDLDDL","DLLLDLLD","DDDDDDDDDDLLLLL","LLLLLDDDDDDDDD","DDDDDDDDUU","LLLLLDDDDDDDDDD","ULDDDDDDDD","UUULLL","LLLLLSLLLLL","LLLLLSLLLL","DLDLLD","LLLSDDDD","LLDDDDDDLL","DLLLDDDD","DLDLD","ULLLLLLLLLLLL","LLLLLLULLLLL","LLDLDDLL","LLLLLLLLLLLLLLDDD","DDDDLLD","LLLDDDLD","ULLLLULLLL","LDDLL","DDLLLDDL","DDDLLLLD","DDDL","ULDDDDDDD","LLLLLLLU","DDDLLDD","LLLLLLLLLLDDDDD","DDLDD","LLLLLLLLLLLLLLLLLLLLLL","UDLLLLLL","LLLLSDD","LDDLDLLL","DLDDLL","LLLLSLLLLL","LLLLSLLLLLL","LLDDDDDDDDDD","DLDDDD","ULLLDLLL","LLLDDDDLL","DDDDLDDD","DLDLDLDLDLDL","ULLLLLUL","DDLDLL","UUULLLLL","UDDDDDDL","LLLLLLDDDDDDDDD","LLLLLLLLLS","LLSLLL","LLDLD","DDDLDDDD","LLLLLLLLLLLLLLLLDD","LLLDDLD","LLLLLLSD","UUUUUUUUDD","LDLDDD","LLDLLDD","DDDDLLLDDDD","DDLLLLLLLLDD","LLLLDDDDLLLL","DDDDDU","UUUDDDUU","DDDDDDDDLLLLLLLL","LLLLDLLLLD","UUUUUUUUD","LLLLSDDD","LLLLLDDDDDDDDDDD","DDDLLLLLLDDD","DLLDDD","DLLDLD","LLDDLLLLL","UDDDDDDU","LSLLLL","LLLLLLULLLLLL","DDDDDDDDDLLLLL","LLLLLLDDLL","DDDDDDDDS","LLLLLSDDD","LDDLLDDL","ULLULLDD","DLLLLLLDD","ULLLLULLL","LLDLLDDD","UULLLL","ULLLULLLL","LLLLLLSLLL","LLLDDLLLLL","UUDDDDDDDD","LLLLLLU","DDDDDDLLLLLLLLL","ULLLDDDDDDDD","DDLDL","DLLDD","LDLDDL","LDDLDDL","LLLLLLDDDDDDDDDD","LLLLLLSLLLLLL","DDDLD","DDDDDDLD","DDLLLLLDDDD","LDDLDDDD","UUDDDDDDD","DUUUUUUU","LDDL","DDDUUU","ULULLLLL","LDLDLDD","LLLDDDDDDDDDDD","DLLDDLLD","UUUUUUUDDD","LLLDLDD","DDDDLLLDD","LLLLLDDDL","ULLLLLDL","ULULULUL","LLLLLLLDDL","LDDLLLDD","ULLLLLLLLLLD","DDDULLLL","LLLSLL","LLLLLLSL","LLLDDDLLLDDD","LLLDDDLLLL","LLLLDDDLLL","LDLLLDDD","LLLSLLLLL","LLLLDDDDL","LLLLDDDLL","LDDDL","LLLLLLULLLLLLL","DDDDDDDDDDLLLLLL","LLLLLLLSDD","UDDDDU","LLLDLDDD","LLLLLSLLLLLL","LLDDLDD","DLDDL","LDLLLDD","LLLLLLDDLLL","DDLDLLL","DDDDDDDDDDDU","LLDDLDL","DLLDLLD","LDDDDLDDDD","LLLLLLSLLLLL","DDDDDDDDDLLLLLL","UUUUUUUDDDD","ULDDDDD","LLLDLLLDDD","DDLLDDL","ULLLLLDDDDD","LLDDDLLD","UUUULLLL","ULLLLLUU","DDDDDDDLLLLLLL","LLLLDDDLLLL","DLDDLD","DDDDLLDDDD","DDSDDSDD","ULLDLLLL","LDDLDDLD","DDDDDDDDUUU","DLLDDLL","DDDDDDDDDDDDDDDDDD","LLLLLLLLLLLLLLLDDD","ULLLU","LLLLLLDLD","UUDDDDUU","LLLLLDDDDL","LLLLLLLLLLLLLLLDDDD","LLLSDD","LLLLLLSLLLL","LLLLLLLLLDDDDDDD","LSLLLLL","LDDDLD","ULLLLDDDDDDDD","DDDDLLLLLDDDD","DDDDDDDDDU","LLLLSDDDD","LDDLDDLL","ULLLLUDD","LDLLDDDD","ULLULLLD","LLLDDDDDDLLL","LLDDDDDL","ULLDDLLL","DDDLDL","LLLLLSL","LDLLDLD","LDLLDLDD","LDLDLLD","DLDLDD","DDDDLLLLLLLLL","LLLLDDDDLL","LLLDLLLLD","DDLLDLL","DDLLLLLLDDDD","ULLDD","UUUDDDDDDDD","ULULLLL","DDLDDLLL","LDLDLLDD","ULLLULLD","DLLDLLDLL","DDUUUUUU","LDDLLDD","ULULDDDD","LLLLLLLLDLL","LLLLSLL","LLLLDLLLLLL","DDLLLLLLLLLL","LLDLLDLLD","LLLLLSDDDD","LLLLLLLLLDL","DLDLDLDLD","LLLLLSD","LLLLLDDLLLL","DDDDDDDDDDDDLLL","DLDL","LLLLDDLLLLL","LLLLLLLDLLL","LLSLLLLL","DDLLLLLLD","DDLDDDDD","LDDLLLLLL","LLDDDDLLL","DLDDDL","LLLLLDDLLLLL","LLLLLLLLLLLLLLLLLDD","LLLLLLLLLLLDDDDD","LLLLLLLSLLLLLL","LDDLLDL","LLLLLLUU","DULLLLLD","UUUUDDDDDD","DLLD","UUDDD","LLLLLLLDLLLL","LLLLLLLLLDDDDDDDD","LDLLDDL","DDULLLL","ULLLDL","DLLLDLLLDLLL","LLLLDDDDLLL","LDLDLDDD","LLDLDDDD","DLDDD","DDDDDDDDDDU","LLUULL","LLLLLLSDDD","UULLDDDD","LLLLUU","LDLDDLDL","DDDLLLDL","LLLLLLLLSDD","DDDLDLLL","UULLLLL","ULLLLLLLLLLDDDD","DDDDDDDDUL","ULLLDDDLLLL","LLLSDDD","DDLDDLL","DDDSDDD","LLLULL","DDDDUL","DDDDDLLLLLLL","UUUUDUUU","DLDLDLL","LDLDDLDD","LLLLLLLLLLLDDDDDD","DDDDULLLL","ULDLLLLL","DDLDLD","DDDDDDLLLLLLLLLL","DDDDDLDD","DDDLLLLLDD","LDLDLDDL","ULDLDD","LLLLLLDDDL","DLLLLDLLL","LLLUUU","LLLLLDDDLL","DDLLDLLD","DLLLDDDL","DDDDDDDDDDDDLLLL","DLLLDDL","LLDDLDDL","ULLLULLLLL","DLDLLLD","ULLDLL","DLDLLLDD","LSLLLLLL","DLLDDDLL","DLLLLDLLLL","DDDLLDLL","ULLDDDDDDD","LLLLLLLSD","LLLLUL","DLLDLLDD","LLLSLLLLLL","UDLLLL","LLLLLLSLLLLLLL","UUULLLDD","DDLDDLD","LLLLLLLLLLLLLLLLD","DDDDDDDS","LULLLL","LLLLLLSDDDD","DDUUUUU","UDDDDDDDDD","LLSLLLL","DDDDLLLLDD","LLLLLLLSLLLLL","DDDLLLLDD","LDDLLLD","LLLLDLLLD","LLLLULLL","DDULLL","DDSULL","LDDDLLLD","LDDDDLDD","DDDDDDDDDDDDLL","LLLLLLLULLLLL","ULLLLLLLLLDDDD","UUUUUDUU","DDDDDLD","ULLDDDDDDDD","LLLLLLLDDDDDDDDD","ULLLLULLLLL","DDLLLDL","LLLLLSLLLLLLL","UUUDUUUU","DDUUUU","DLLLLLLLLLLL","LDDLD","LLLLLLULLLL","LLDLDLDD","UULLLLDD","ULUL","ULLLLUUU","ULLLDDDDDDD","LDDDLDLL","DLDDLDLL","LDLDDDDD","LLDDDDDDL","ULLLLLUD","DDDDLLLLLLDDDD","UULLLDDD","ULLLLLDDDDDDDD","DLLLDLLLL","LDDLLDLD","DLLLLLLDL","LLDDLLLLLL","DLDDDLLL","LLLLLULL","DDDDDDDUU","DDDLLLDDDLLL","UUDDDUU","LDDLDLDL","LDDDDDLL","DDDDDDDDDDDDDDDDDDDD","UULLUU","LLDDDLDD","UUU","LULULU","UUUDLLLL","UDDDUU","DLLLDDLD","DDLLDLDL","DDDUUUUU","LDLLDDDL","DLDDDDDD","SLLLLL","LLLDLLLLLLL","UDDDDDDDDL","LDLLDDLD","UULLL","LLDDDLDL","LLLLLDLLD","ULLLDLL","DDLDDLDDDDL","LLLLU","UUUUUUDU","ULLLLLULLLL","DDLDDDDL","ULLLLLULLLLL","DLLDDLDL","DLLLLLLLLLD","LLLLLLLSLLLL","UDDDDDDDDDD","ULLLLLULLL","LDDLLDDD","DLLLDLD","DDDDDUU","DDLDDLDDDD","UUUUUUUUUD","DLDLLDL","LLDDDDDDDDLL","LLDLLLLDL","LLLLLLLLLLLLLLLLLLLLLLL","DLLDDLD","DLDDLLL","DLDLDDLL","DDDDULL","LDDDLLDDD","LLDDLDLD","LLLLLLLLLLLLLLLLDDDD","DDLLLLDDD","LDLDDDLL","LLLDDDDLLLL","DLLDLDL","DLDLDLLD","LDLLLLDLL","LLULLLLL","UUUUULLL","UUUUUUUUDDDD","ULLLLDDDDDDD","LDDDDDDDDDL","UDUDUD","DUUUUU","LLLLSLLLLLLL","UDDDD","DLDDLLDL","DDLDLDLL","ULLULULL","DDDLDDL","DLLDLDLD","LLDLDDL","LLULLL","UDLDLDLD","UUULLLL","LLLLLLLULLLLLL","DLDDLLLD","ULLLLDL","LLDDDDDDDDDDD","LLDLDDLD","LLLLLLSLL","DDLDLLDL","DDLLLDLD","DDL","LLDLDLD","LDDDDDDDDDDL","LDDLDLLD","DLLDDDD","DDLDLLLD","ULLDLLL","DLLLDLDD","LDLDD","UDDDDDDDL","LLLLLLDDLLLL","DDDDDUUU","LDDLLLLLLL","UDUDUDUD","DDDLDLL","DLDLLDDL","LLLLLLSLLLLLLLL","DLLDLDDL","ULLULLD","LLLLDLLDD","LDDLDLDD","ULLLLLLLLLLDD","ULLLLLLDDDDDD","ULLLLLLLLLLLLL","ULLSDD","LDDDLDD","UDLLLLL","DLDDDDD","LLLLLLLLLLDDDDDDDD","LUUUUU","DDU","LULULL","LLLLLLLLLLLLLLLLLLLLLLLL","LLLLLLLSLLLLLLL","LDLDDLLD","LLLLLLLSLL","DLDLLDLD","DLDLLLLLL","UUUUUUUUUDD","LDDDLLDL","UUUUUUUUUUUUU","DDUUU","LDLLLLLLD","LDLDDDD","DDDDLLDL","DSDSDDD","DLDDLLD","LLLDDDLLLD","LDDLDDD","LLLLLLLDLD","LLULUL","LLDDLDDD","ULLLLLULL","LLLLDDLLLLDD","LDLDDLL","LLLDDLLDD","DLDLDLDD","LLLLLLLLLSDD","LLDDDDDLL","DDDDDLLD","LLLLLDLDL","LLLLLLDLLLLL","UUDUUUUU","LLLLLLLLSLLLLLL","LLLLLLUUUUUU","SSSSSS","LLLLLLLLLLLLDDDDDD","DDULL","LLLLLLLLLLSLLLLL","DDDDDS","LLDLDDD","DLLLLLDLL","ULLLLUD","DUUUU","LLLLLLLLSL","DLDDLDDL","LLLLLLLLLLLSLLLL","LLLLLDDDLLL","ULDLLL","ULLLLLLULLLL","UUUDDDDDDD","ULLLULLU","UULLLU","ULLLULUL","LDDLDLL","DUUUUUU","DDDDLDDDDL","LLLLLLLLSLLLLL","DDDLLDL","LLLLLLLLLDLL","ULLLLLLDDDDD","LLLLLLLSLLL","LLLLLLLLLSLLL","UDUUUUUU","LDLDLLLLL","DDDDDDUUUU","DULLLULL","DDDDDDULLL","LLDLLLLLLLL","ULLULLUL","LLDDLLLDD","LLLLUD","UUUD","ULLDDULL","ULLLLLLLLLDDD","LLLLLLDDDDL","DDDDDDDLLLLLLLL","UULLLLLD","LDLLDLLLL","LLLULLLL","LLDLLLLDLL","DDLDDLDDLDDL","LLLLLSLLLLLLLL","LDLLDDD","ULULU","LULLUL","LLLULU","LLLLLLLLLLLSLLLLL","DDDDDDLU","UULUUL","LLDDLLDDLLDD","LLLLLLLSL","DDLDDLDL","LLLLLLUD","UUUUUULL","UDDDUDDD","LLLDDDLLLLLL","ULLLUD","ULLLDDLL","LDDDDDDDDDDDD","UDDDDDDDDDDD","ULULL","ULLLLDDL","DDLLDDDL","DDDDLDDL","SLLLLLL","LLLLLLLDDLL","DDDDLLLLLDD","ULULULU","SLLLLLLL","LLLLDLLDL","UUDDUU","DDLLLLLLLLLDD","UUUULU","UUUDDUUU","UUULUU","LLUULU","DLLDLLLLL","LLUUUU","ULLULULU","ULUUUULL","DDLDDDLL","LLDLLLLLD","ULLLDULL","DDDDLLLLLLLLLL","ULLULLLU","LLLLLLLLLLSLLLL","DULLLLLLL","ULLUDDDD","LLLLLDDDDLLLLL","LLLLDDDDDDDDDDDD","DDDDU","DDDULL","DDULLLDD","LLLLLLLLSLLLL","LLDLDDDL","LLLDLDLLL","LLLLLLLSDDDD","LLDDDLD","UUUUDDDDD","DSDSDSDDD","DDDDULLLLL","DDLDDLLD","LLLLLLLULLLLLLL","ULLULLLLL","ULULLLUL","LDLLLLLLLLL","UUUULL","LLLDLLDLL","LDLLLLLDL","ULULULLL","DDDLLLLLLLDDD","DDUUUDD","LLLLLLLLULLLLL","LDDLDDLDDLDD","ULLUULLU","DLLLLLLU","ULULLLLU","LDDLDLD","LLLUDD","UULULL","LLLLLLLLLLLLLLLLDDD","UUUUUDDDDDD","LLDLLLDLL","DDDLDDLL","DDDUUUU","LDDDLLD","LLLLLLULLLLLLLL","DDDDDDULL","LLLLLLLLSLLL","UUUUUUUUDDD","LDLDDLD","ULLLUULL","ULULLULL","LLLLLLLLDLLL","LLLLLLLLLLSLLL","LLLLLLLDDLLL","DDDDDDDDDDS","LLLLLLLLLLLLDDDDD","UDDDDDDDDU","LLLLLLLLLLDL","ULLLLULU","LLUUUL","DUUUUUUD","LUULUU","LLLLLLLLLLLSLLL","ULULUUUL","LLLLLLLLLLLLSLLL","LDDDDDDLL","UUULLLDDD","ULLLULLLLLL","DDLLDDLD","ULULLULU","LLLLLLLSDDD","LLLLLLLLLSLLLL","DDLLDLD","ULLUL","LLLLLLLLLLLLLLLLLLDD","LLLLLLLLLSLLLLLL","DUDLUDUL","DLLLLDDDD","DDLDLLDD","UUULUL","LLLLLLLLDDL","LLLLLLLLLSLLLLL","ULLUUUUU","SSSSS","UULLLULL","DLDLLDDD","ULLULLUU","ULULUULU","LULUUU","LLLLLLLLSLLLLLLL","LLLLLLLSLLLLLLLL","LLLLLUUU","LLLDDLLLLLL","ULLLLUL","DDUUUUDD","DDLDDDL","LDDLDDLDDDD","LLLLUUUU","UULLLLLU","LLLULLL","ULULLLUU","ULLUULLL","DDDDDDDDDDDDDDL","LUULLU","LLLDLLLLLD","LLDDLLDDLL","LDDLDDLDDL","LLDDDLLLL","LLLDLLLDL","LUUULL","LUULLL","DLLDLDD","UULLUUUL","ULULLUUL","LDLDLDLDLDL","DDLDLDDL","ULUUULLL","UULLULLL","ULLLUUUU","DDUU","LLLDDDLLLLL","LLLLLLUUUUUUU","UUUDUUU","LLULUU","LLLLLLLLLLLSDD","ULLLLUUL","ULUULULU","LLLUUL","LLLLLDLLLLLL","LULLLLLL","UUDUUU","DDDDLDLL","LLSLLLLLL","LLLLDDDLLLLDDD","UUUULULL","UUULLUUL","LLLLLLLLLLLLSLLLLL","LULLL","DDDLLLDDDD","DDDDDDDDUUUU","LLLLDLDLL","LSLLL","DLDLDDDL","LDDDLLLLL","LDDDDDDDDDDDL","UULLLLUL","UULUUU","UUULLLLU","UULULU","ULUULULL","UUUUULUU","UUUDU","ULUULUUL","UUULLULL","ULLUUULU","ULULULLU","UULLLLUU","UUDUU","DULULLLL","UULLLUUU","DDDDLDL","ULLLULUU","UUULLLLD","LLLLLLLDLLLLLL","LLLLLLLLDLLLLLL","DDDLDLLD","DDLLLLLLLD","LLLLLLLLSLLLLLLLL","LLDLLDLLL","UUULULLL","LLLLLLDDDLLL","LLLDLLLDD","UUULUULL","ULLUULUL","UULUUULL","UULLULLU","LSLLLLLLL","LLLLSLLLLLLLL","DLLLLLDLLL","LDDDLLDDLLL","LLLSLLLLLLL","LDLLLDLLL","DLLLDLLLLL","LLLLSD","LLLLLDDDDLL","LLDDDLLDDD","LLLLLLDLDL","ULDDLLLL","LLLLDDLLLLLL","LLDLLLLLDL","UDDUDD","DDLLDLDD","LLLLLLDDS","UUUDDLLL","ULUULUUU","DLLDDDDD","DDUUDD","UULLULUU","DDLUL","DDDDDDDDDDDLLLLLL","LUUULU","DULLU","DULUL","LLLLLLLLDLLLL","LLLDDLLLD","DDDDDDDDULLL","DDDULLL","DDDDDDUD","UULULLLL","ULLLLLLLU","ULLULUUL","ULLUUULL","LLLUUD","LLLLLLDLLD","LLLLLLDDDLL","UUUUUUUUUUUUUU","LDDDLDDL","UDDLLLLL","UULLLUUL","DDDLLDDDD","DDUUL","ULULDD","UULULULU","UDUUU","DDLLLLLLLDDDD","ULUUUUUL","DLDDLLDD","LSLLDDDD","DDDDDDDDDDDDDDDDD","LLULL","DULLULLL","LULLLU","LLLLLLLLLLLSLLLLLL","LLLLLLLULLLL","UUUUUL","ULDDLL","DLLLLLLLDD","UULLUULU","UDDDUUDD","LLLLLLLLULLLLLL","DLDDLDL","UUUUUUDDDDDD","DDLLU","DDDLLLLLLLLLL","ULLLLSDD","LLLLLLLLU","LLLLLLLLLLLLLLLLLD","DDDDDDDDDDDS","UUULLULU","LLLLDLLLLLLL","DDDLLDDL","DDDDDDULLLL","LLDLLLDLLL","DLDLDDD","LLLLLLLLSD","UUUUUUUL","DDDDDLDL","LLLUL","UUUUUULU","DULLLLUL","LLLLLUDD","LSLLLLLLLL","DLDLLDD","ULLLLLDDDDDDD","UUULULUL","LLUUL","UULULLUL","LLUUUD","UUUULUUL","ULLDULLL","ULDDDDDDDDD","DDLLDDLLDD","ULLUULUU","ULUULLUL","ULUUULLU","UUULUUUU","UUUUDU","DDDDLLLLD","UULUUUUU","ULULULUU","DLDLDDL","LLLLLLULLLLDD","ULULULDD","DDDLLLLLLLLDDD","DDUULLLL","ULLLULLLDD","LLLLLDLLLLLD","ULLLUUUL","DDLDLDD","ULUULLUU","DLLUL","UUULLLUU","DDDDSDD","DDLLDDDDDD","DDDDDDLLLLDD","LLLLLLLLLLSLLLLLL","UUULLLUL","DDDDDDDUL","UUULULUU","LLLLLDDDDLLL","DLLUU","DLLLLLLLLLLD","ULLLLLSD","LLLLLLLLLLLLSLLLL","UDDDDUDD","LLLLLLLLULLLLLLL","DDLDLLD","DDDDLLLDDD","UUUDUU","ULULUULL","DDDUU","LLLLLLLDLLLLLLL","LUULUL","UULLUUUU","DDDDDDLLLLLDD","DLLULLLL","DDLDLDLD","DDDLDDLD","ULLLULDD","ULDLLLL","DDDDUDDD","LDDLDDDL","DDLDLDL","ULLLLLSDD","UDDDDDU","ULULLUUU","LDLDLDLDLDLDLD","LLLLLLLLLLLLSDD","DLLLDLLLD","DLDDDLDD","ULUUUULU","UUUUDDDDDDDD","UUUUUDDDDD","DUUULLLL","ULLULUUU","LDLLLLDLLL","LLLLLLLLLLLDDDDDDDD","ULLLLULLLLLL","LLULU","DLUULLUL","LLLLLLULLLLLDD","UUUUULUL","ULLLUDDD","LLLLDLDLLL","DDUDDUDD","DULLLULU","DLLLLLDDDD","LLLLLDDDDLLLL","UUULL","DLLDDLDD","UUULUULU","DDDDDDDDDDDDDL","ULLLUULU","UULUULLU","DUULLUUL","ULLLLLLLDDDDDD","ULUULLLU","DLLULULL","LUULL","DLDDDLLD","LLLLLLLLLLSDD","DDLU","DULULUUL","DLDDLDD","UULLULUL","DDLDDDLD","LLLLDDDDUU","DLULU","ULUUUUUU","LLLLLLLLDDLL","LLLLDLLLDL","DDUL","ULULUUUU","ULUULLLL","UDDUDDUDD","LLDDDDLD","LLULLU","UDUUUU","UUUULLUU","LLLLLLDDDDLLLLLL","DDDLDLDL","ULUUULUL","UUULULLU","UUDDUUDD","ULLLLLDDS","DLLDDDL","DDDDDDLLLLLLDD","UULUULLL","UULULULL","DLLLULLU","ULULLLLD","DULLLLLU","LLDLDLLLL","DLDDDDL","ULULUD","UUUULLLU","UUUULLUL","UUULLUUU","DUUULLUL","DUUULULU","UULLUULL","DDDDDDLDD","DDDDUUUUU","DDDLLLLLD","LLLLLLUL","DLLLLLLLDL","LLDLLLLDD","DULULLLU","DDDDLLDDD","UULUUUUL","DULULULU","DDDDLLLLLLLDDDD","LLDLLLLLLD","LLLLLDLDD","UULULLLU","LLLDDDDLLLLLL","LLLLLLDDDDDDDDDDD","DLDLDDDD","LLLLLLLLLLLLLLLLLDDDD","DDDDLDLD","LLDDDDLLLL","LLLLLLLDDDL","DDLD","LLLUU","DDDLDLD","DDULU","DUULLLUL","UUUUULLU","DLLDLDDD","DDLDLDDD","ULLUUUUL","DLLUUULU","ULLU","DUULLLLL","UULUULUL","UULULLUU","LLLLDU","DLLUULUU","DDDDDDDDDLLLLLLL","DLLLLLUU","ULUUULUU","DDDDDDDUUU","ULDDD","LLUUU","DLDLDLDLDLD","DDLLLDDLL","LLDDDDDDDLL","DDDLLDLD","ULLDULLD","DLLLULLL","UULLLULU","DULULULL","UULUULUU","DDLLLLLDDD","DULULLUL","UDDUDDDD","UUUULULU","DDDDLLLLLLDD","DUULU","DLLLLULU","DDULLLLLL","DLLLULUU","DDDUDDDD","LLLLLDLLDL","UUDDDDLL","DLDLLLLLLL","DDLLLDDLLL","LLLLLSLLLLLLLLL","LLLLLLLLLLLLSLLLLLL","ULLLUDD","LLLDULLL","DUUUL","DDDDDDSS","UULULUUL","LLLDDDDDDDDLLL","DUULLLLU","LLDLLDLLLL","DUULLULU","LLLLLUU","DDLDDDDDD","DUUULLUU","DDLUU","LLLLDLLDLL","DLDDDLL","UUUULUUU","LLDLDLLLLL","DLLLU","LLLLLLLDLLLLLLLL","LLLLLDLLLD","LLULLD","LDLLLLDDL","DDDLDLDD","UUULLU","DDDDDDDDDS","DUULULUU","UDDUDDD","ULLLUUU","DLULUUUL","UDDDDL","DUUUULLU","LLLLLLLLLDDL","LLLLLLLLLLSLLLLLLL","LLLUUUDD","LDLLLDLLLL","DLDDDLD","LDDDDLD","DULUUULL","DLLUUULL","DULUULLU","UULUUULU","LLLLLDDS","ULLLLLDDDLLLL","ULLDL","UULLLD","LLLDDDDLLLLL","DULLLUUL","LLLDLLDLLL","DUULULLL","UULLUL","DDDDLLLLLLLLLLL","ULLLLLLDDDDDDDD","ULLLLUU","DLUUULUL","DULUULLL","DDDDDDDLDD","DLLULLLU","ULLLLULD","ULLDLLLD","DULLULUL","DLLDDDDL","LUUUUL","DUULD","DLUUUULL","DUUULLLU","LLLLLLLLLLLLLSLLLLL","LUUUU","UULLLDD","DDULLLLDD","DLLULL","UULLDD","DSULL","DLLLUULL","UULULUUU","ULUUL","DUUUULUU","DLULLULL","UDLLLLLD","DDLDLLLLL","UULUL","ULLLLLLULLL","LLLLLLDS","UDDDDDDDU","LLLLLLLLLDLLL","DLLUULLL","LLLDDDDDDDDDDDD","DLLLLLDDD","DDDDDDDDDDDDDDDL","ULUDDD","DULLUULL","LLLLLUD","ULLLLLLLLLLLLLL","LDDDLDLD","UUUUDUU","UDDDDDUD","DLULLLLU","LLLDLLDDD","LLLLLLLLLLLLLLLLLDDD","ULDDDDLL","DULLUULU","DUUUULUL","LDLLLLLLLD","LLDLLDDDD","DDLLDDLLDDLL","DLULULLL","DULUULUL","DULLLU","DLLLULUL","DUULLLUU","LULLUU","DUULLULL","DLDDDDLL","LLSLLLLLLL","DDDDDDULLLLL","ULLULLLLLL","DULUU","DULLULLU","LDDDDLLD","ULULLLDD","DLLLLLUL","DUDUDUDU","LLLLLLDLLLLLL","ULDDULDD","DULLUUUL","LLLLLDDDLLLL","ULDULL","LLLLLDDDLLLLL","DLLLUUUU","LUDDDDDD","ULDULD","UDLLLLDD","ULLLDLLLL","DUUULUUU","ULLD","UUUDUUUD","ULLLLLLS","DUULULUL","DUULUUUL","UDDUDDUD","DLDDDLDL","UUUUUUUUUDDD","LLDDDDDDLLL","DLDDLDDD","LLLLLLLLLLS","DDULLDD","DULULLUU","DUULULLU","UUDDUUUU","LLLLLLLLLLLDL","DDDDDDLLLLLLLLLLL","ULLLLUUD","DLDLLLLLD","UUUDDDU","DULUULUU","LLLLLLLLLLLLLDDDDDD","ULLLULLLD","DLLUULLU","LULUUL","DUUULUUL","UUUDDUU","LLLDLLLDLL","DUUUUUUL","DUULL","LDDLLLDDL","DDLLLLLLLLLLL","UUUUDDUU","DDDDDDDDLLLLLLLLL","ULLUU","LLLLULLD","UUUDDDDU","LLLLLLLLLSLL","DDSDDSDDDDS","DLLUUUUL","UULUU","DLUUULLL","LLLLLLLLDLLLLLLL","DULULUUU","DLLDDDLD","DLUUULUU","DDDDDDLLD","DULULU","ULL","ULUUU","ULLDDLL","DULUUULU","DUUUUULU","UUUUUDDU","LLLLULL","LLLLDDDDDDLLLL","UUDD","DUULUULL","UUUUL","DLLLDDLLL","LLLLLLLLLLLLLDDDDD","ULULLLD","ULLLLLDLL","DDDDDUDD","LLLLLLDDDDLLL","DLULLLLL","DLUULULL","ULLLLLLLLLLLDD","DULLLUUU","LLLDLDLLLL","LLLLLDLLDD","ULLLLLLDS","DULLLLD","LUUUUUUU","ULLLLLLLLLLDDD","ULLUDD","ULLLLLLLLLLLD","LLLLUULL","DLULUULU","DDDDSDDDD","DDDUUDDD","LLLLLLLLLLLLLSLLLL","DLLLLUUU","DLLULLUU","DUUUULLL","DUULUULU","LLDDDLLLLL","LLLDDDLLLLLLLL","DDDDDDLLLDD","DUUULULL","DLDULU","DLUUULLU","DULLUUUU","DUUDU","LLLLLLLLLLLLSLLLLLLL","LULULULU","LLLLLDDLD","DLUULLLL","DDDDUUDD","LLLLLLLLLLSLL","LULLU","DLLULLUL","DULUUUUL","DDSDDSDDS","ULLLLLULLLLLDDDD","ULULUDDD","ULLLLLUDD","LDLDDDL","DUULUUUU","LLLDDDDDDDLLL","LLLLLLLLLLLLDDDDDDDD","DLDDLDLD","LLLDDDDDLLL","DUULLUUU","UDUDDDDD","LUUUL","LLLLUDDD","DULUUUUU","ULUDDDD","LDLLDLLDL","UUULUUUL","DLDD","LULUULUL","LULUL","DUDUUUUU","DLLLLULL","LLLLLLDDLLLLLL","DDDUDDD","DLLLLLLDLL","LLLLLLLLLLLLDL","LUUULLUU","DDLLLLLLLLLLDD","LLLLLLLLLSLLLLLLL","UDDDDDUU","LLLLDLLDDDD","DULLULUU","LLLLLLSS","DULLLLUU","LLLLDDDLLLLL","DLUULUUU","LLLLLLLLLLLSLLLLLLL","UDLDLD","DUDDDDDD","UUUDDDLL","LDLLDLLLLL","LLLDDDLLLLLLL","LDLDLLLLLL","DLULLLUU","LLLLSS","LLLLLLLLSDDD","UUUUUUUUUUUUUUU","LLLLLLDDLLLLL","UUDUUUU","DLULLUUU","LLLDLLDDDD","SLLLLLS","ULULULUD","LLLLLLDDDDLL","DDDDLLLLDDD","LLLLUUU","UUUDULLL","DULULL","LLLLLLLDLLLLL","LLLUULLL","LLLLLLULLLLLLLLL","LLLLLLLLSLL","UUUUUUUUUUDD","LLLULLLD","LDLDDDDL","LLUUUULL","ULLDDDLL","LDLDLDLLL","LLLLLLLLLDLLLL","ULULDDD","LLLLLDLDLL","LLLLLLLLLLDLLLL","UDDUDDU","DLLUUL","ULLLULLLLLLL","DDDDDULL","LLLLLLLLLLLLLSDD","DLLLLUUL","LUULU","DLUUUUUL","DDDULLLLL","LLLLLLLLDDDL","DUUUUULL","DLUUL","LLLLLLUUUUUUUU","LLDDLLDDD","ULDDDDDDDDDD","LLLLLLDU","DLULUULL","DDDUL","SLLLLLLLL","LLUUUUUU","DLUULLUU","LLLLLLSLLLLLLLLL","LLSLLLLLLLL","UUUDDDLD","LLLSLLLLLLLL","LLLLSLLLLLLLLL","DDUDDDDD","DLLDLLLLLL","LULLLLLLDD","DDLLDDLLL","LDDLLLLDL","LLLLLLLDDDLL","DLLUUUUU","LLLDLLLLDL","ULLLLDLD","DLLLUULU","LLLLDDDU","LLLLLLLLLSD","DLUUUULU","DLLLLDDLL","LULLLLLU","DLLUULUL","UULLU","LLLLLLLLLLLSL","LDLDLDLDLDLDLDLD","DLLLUL","ULUUUD","DLDDDDDL","ULLLDLLD","LLLDLLLDLLLD","DLDLDDLD","LLLDDDDLLLLLLLL","LLLLLDDU","LLLLLLLLSDDDD","LLDDLLLLD","DLULLULU","LLLULLLU","LLLU","ULLLLLDS","LLLLLLLLDLLLLLLLL","UULLLLD","DLDUU","DLULUUUU","UUDDDDDU","LLULUD","LLLLLLULLLDD","LDLLLLLDLL","UUUULLLD","LLLLLLLLLLLLLLLLLLD","DDUDDU","DUUUUD","DLLULUUU","DDUDDDD","LSSL","UULDUU","LLDDDDLLDDDD","UDDDDUU","DDDDDDDDULLLL","UUUUDDDDDDD","LLULLLLU","DLULLUUL","USLLLLLDDDD","LLLLLLLDS","LLLLLLLLDLLLLL","LLLLLLLLLLDLL","ULLLLLLLDDDDD","LLLLLLLLLLSL","LDDDDLDL","UUUULLL","LLLSL","LLLLDDDDDDDDLLLL","ULLLLLS","ULLLLDUL","DDDUDDDU","LLUDLU","UUUDUDD","DDDDLLLLLLLLDDDD","DDLLLLLU","DLLLLLLLLLLLL","LUULLLUU","LLULLLL","UUULU","UUDDUUU","LLLDDDDLLLLLLL","DDDLLLLLLDD","LLLDLLLLDD","DULLD","DLULLL","DUUUDUUU","LLDLLLDDDD","LLLLLLLLLLLLLLLLLLLDD","LLLLLLLDDDDDDDDDD","LDLLLLLDD","LLUULLLL","UUULLLD","UUUUUDDDDDDDD","LDLDLDLDLL","DDDDDDUUUUU","DDDDDDDLD","UDLLL","UUDDLLLL","UUDDDDU","LULLLULL","DDDDDDDLU","DLULLU","LLLLLLLLDDLLL","LLLLULUU","DLULLLUL","LLLDDLLLLD","DLULL","DLDLDLDLL","LLLLLLLLLLLLLLLLLLLLLLLLLL","DULDL","ULLLUDDDD","ULLLDU","DDDLLLLDDDD","DULUUU","DDDUUUDD","ULLLLDDU","SDDDDDDS","LLLUD","DUULLU","DLLULUUL","LDDDDLLLL","LLLLLLLUUUUUU","LLLLLLLLLLDLLL","LDDDDDLD","LDLLLLLLDL","DULLUL","UDULLLLL","DDUDD","DLUULUUL","LLLLDDDDU","DUUUUDUU","LLLLDDDDLLLLL","LLLUUULL","LLLLLLLLULLLL","DUUDUUUU","LDDDLDDDD","LLLLLLLLLLLSLL","ULDLLLLU","DLUULULU","LDDDLDL","ULLLLLDU","LUUUUULL","LLDULL","LLLLULLLL"],L.blacklistedSubstrings=["12345678","password","23456789","11198","land","blue","04199","07199","02199","06199","08199","angel","10199","09199","12199","11199","01197","05197","07197","a199","04197","03197","10197","08197","123123","12197","06197","master","dragon","09197","fish","02197","black","11197","a200","2112","fire","mike","baby","pussy","line","test","mark","cher","wood","mama","bear","cool","ling","anne","fred","illa","a198","anti","alle","marc","monkey","life","man1","dick","ness","good","daniel","sexy","o123","time","assi","gold","shan","shadow","rain","ters","alli","ford","play","mont","anta","mine","qazwsx","ache","stra","erry","michael","dima","green","sher","nick","shar","wolf","ring","killer","suck","tina","robert","01196","even","elin","aris","2211","dark","bird","jordan","paul","1108","scar","ones","lock","123321","0909","arri","mustang","rose","shit","asta","money","121212","0505","arch","03196","football","stro","hill","01019","letmein","dman","chin","10219","04196","05196","amil","pant","baseball","porn","david","james","onic","eron","10419","mini","stal","ison","abc123","lover","ander","alen","30319","t123","erin","ina1","vers","0303","ings","martin","mega","olly","ante","hello","11119","0108","90519","00119","08196","21219","shka","10196","hunter","30119","40419","00319","30219","02196","yboy","666666","10619","1102","vlad","70719","pers","1211","nova","12196","10919","anni","sara","lian","010119","07196","30419","0707","elli","oker","50219","er123","atch","00519","00419","rest","06196","50319","side","na19","60619","1107","50419","1210","00619","50819","80319","11196","90919","1109","tran","arma","anton","30519","50719","andrew","l123","09196","50119","31019","enny","0808","40219","90619","01119","80219","34567890","fuckyou","70219","00719","40519","anch","sweet","30719","80519","51219","40619","80419","soccer","21119","2108","00819","70419","60319","1204","60519","80819","1205","1002","elly","race","00919","7777777","60219","stic","steve","40319","70519","west","41019","90419","30619","thomas","01219","51019","boob","tche","30819","less","assa","60719","allo","ital","poli","light","50919","lion","30919","50619","90319","70319","2109","80119","ment","70919","70119","60419","60119","40719","40819","81219","80719","0404","70819","1208","0112","31219","0107","asti","90119","harley","each","70619","40119","51119","0304","80619","90719","bone","well","41219","0606","80919","71019","10101","1206","phil","0105","brand","1209","61219","1202","90819","1105","696969","71119","lick","ista","11111111","91019","lisa","more","0110","1005","123qwe","91219","1106","alis","60819","0106","60919","1000","41119","stre","arry","1207","llin","1007","charlie","enko","40919","1203","1004","k123","1110","31119","71219","long","61019","buster","apple","1003","wing","91119","ivan","1123","reat","1103","81019","61119","tori","0506","batman","stri","2212","anov","sion","2107","leon","1104","81119","isha","2102","a197","power","summer","superman","anya","qwertyui","sing","3108","pepper","1312","2311","george","ence","nker","lore","2110","tech","alan","3112","87654321","1006","card","2106","1008","part","ryan","ross","123a","liver","amin","gran","1402","cock","aron","william","ssie","gene","2512","2301","01200","elan","ipper","ding","para","rish","maria","nson","dave","frank","sasha","1311","2103","moon","rill","buck","tigger","amel","mara","hand","2105","1812","ollo","2309","roni","kate","1512","happy","2525","2505","0405","1301","21985","redd","2202","arth","terr","iloveyou","hockey","2310","mper","2501","2210","3012","per1","2206","adam","3107","abri","tron","emen","0123","olli","11991","isto","game","cent","1009","3110","2305","achi","arta","emin","21990","1310","ladi","hawk","gfhjkm","moni","21989","gate","ines","ing1","lone","llen","ania","elis","mary","alina","2412","ardo","tall","itte","crea","mani","2204","indi","dogg","1478","shel","0502","0305","tree","ning","ation","peter","real","scott","miss","ucki","sant","slav","liza","erna","3010","olle","2510","oria","enne","meli","asca","0308","0708","chie","access","1510","reds","bass","justin","esse","sche","1305","0508","roll","1412","jxrf","2511","sman","2104","1504","0905","niko","hammer","arre","ender","2303","erto","0507","hall","1410","2207","2410","1502","1501","svet","sama","2203","1303","ingo","bitch","1308","2205","1503","esta","0501","1511","98765432","1404","222222","112233","2503","ress","m123","2504","0212","pres","2304","f123","ming","lucky","lass","fuckme","jessica","1307","1306","lash","1302","0211","an19","tlan","jennifer","1405","link","acker","2306","0306","ener","harr","0301","0503","0302","marl","1235","0509","0809","wild","1612","21984","lori","1411","2411","cola","ger1","andrea","1221","21992","0310","avis","0803","snow","came","3003","1507","illo","mist","sandr","cand","rate","1711","silver","hant","1508","daddy","3001","franc","unny","90219","taylor","1304","2401","ashi","3004","freedom","1704","3105","dead","2208","2509","0607","amanda","0307","joshua","11984","1805","arie","asse","1403","trin","2209","1705","yman","rett","kell","jeff","0609","inst","2502","stas","matthew","lanc","0608","2507","alia","1605","0406","alie","2404","tana","bble","ngle","21991","1801","2307","face","stone","1611","1309","1408","2606","hone","1401","mash","anas","mann","aren","wertyuio","son1","2508","8888888","00219","3006","0504","nicole","1712","1213","1707","poop","1407","asper","3103","dallas","erri","dream","denis","teri","2805","mina","ader","diamond","ride","eral","asshole","0912","ashley","team","cheese","bobb","2506","1406","1710","11983","thunder","ister","hero","roman","er19","2405","chen","3005","21983","n200","ginger","serge","0908","2707","kiss","1811","1604","2406","smoke","0309","lord","maggie","trustno1","2611","1509","mila","wall","2601","s200","pack","1802","arme","trac","1703","2909","0311","44444","orne","2812","1606","arne","i123","dude","2711","cookie","1702","2308","kara","0512","sere","1706","sunshine","holl","tell","1601","2403","101198","1803","ertyuiop","wind","2801","1610","2802","1603","2701","ers1","anny","2612","21982","ound","radi","1506","nman","0407","arro","0408","0510","stat","mail","11992","1804","0807","2808","1602","1810","east","2703","2811","nika","enda","astr","barb","victor","osto","abel","2710","2905","ember","0709","1806","ckle","0711","1409","2901","0312","1808","ker1","2605","rena","arke","olga","n199","colo","0410","ckie","rach","2904","2603","0403","dina","2704","2803","alon","corn","2712","ally","papa","0906","anthony","otte","icks","rona","0704","2804","audi","2810","0702","2602","iner","cart","2604","11982","reak","2702","russ","bron","tain","0605","0910","hbyf","1709","pimp","bond","03200","ristin","1608","0602","devil","2903","shot","phan","08200","etro","2610","05200","1230","lant","2402","house","aran","ana1","enter","mali","slan","2408","2407","01195","erse","ardi","159753","gust","cali","kova","azer","e200","1222","chil","andra","2705","0610","chelsea","princess","0902","1809","ermi","2607","ango","oose","0710","3007","hack","atan","0402","11980","0511","04200","adri","0401","on12","nokia","lady","0805","onde","0601","0412","z123","essa","0603","0810","plan","0411","michelle","maks","inde","2906","blow","nasty","0701","computer","aine","mira","ucks","core","2912","qwerty1","2409","1708","lson","aint","0812","0911","2709","1609","toni","iron","eave","1088","ture","oner","some","0705","tere","onta","skin","vent","3009","fast","merlin","4123","1807","0706","0802","0901","1607","2910","0806","0904","11981","atur","02200","09200","2911","tten","elena","0612","white","manu","zxcvbnm","yankees","0604","blin","ammy","2907","samm","0001","nica","acha","2609","starwars","oleg","1018","2807","0801","alls","water","12200","guitar","boom","tara","0409","0611","0804","mate","2809","nell","rton","boot","ffff","vill","2708","bles","maxim","ster1","3008","eeee","0907","flor","riel","rebe","maha","lton","2468","berg","0712","2806","chicken","tony","jackson","tick","cham","igma","avel","anut","ales","lane","ichi","2608","nche","welcome","0903","2706","ckers","lari","onne","inka","apri","kari","dann","07200","adis","10200","call","pion","london","pink","ddie","0703","erson","sport","eren","peac","1qaz2wsx","11200","1029","03195","beer","lala","sssss","metal","opper","ydog","brown","carol","buff","r200","amor","ennis","cros","brad","2424","init","anes","frog","esto","06200","igor","fant","21993","12011","13579","ncc1701","cast","eddy","rush","n198","rris","stel","05195","kins","11993","enta","0000000","magic","kman","vert","10195","2908","4789","ease","tera","arsenal","0811","them","erre","rter","1100","21980","5150","rome","6123","sham","1194","lman","bigdog","brian","uffy","jake","greg","poll","moto","aser","21981","rando","rash","8963","ooke","sparky","oger","jason","wwww","golfer","jane","arat","eagles","rado","ping","scooter","assword1","medi","lera","poke","nett","arge","sten","high","cont","ddog","user","ambo","anim","phoenix","3344","nity","mars","oren","ashe","octo","orma","work","stud","conn","2369","coll","der1","spider","7896","onte","y200","teen","elvi","sting","hanna","lips","rida","marina","yama","term","tigers","kenn","brit","10203","anad","ooper","08195","atte","bast","vika","billy","ferrari","ishi","kkkk","river","tttt","llar","lakers","rend","04195","11195","able","rita","trip","nice","ilan","barn","seve","usty","bbie","boss","dash","iris","itan","sana","cass","ka19","nina","feli","soni","anil","ussi","aram","ampi","ablo","olla","ton1","toma","gman","rama","02195","spri","isco","rack","mers","admi","lade","olan","333333","inal","tani","1089","1078","lana","temp","lly1","unner","09195","adin","12195","9090","rent","man2","honda","tany","na12","131313","4545","jami","nake","r1234","ples","acki","vova","back","ghbdtn","g123","hema","estr","onald","stia","5252","book","cccc","dale","secret","1515","anis","mana","anal","rell","rion","1415","corvette","emil","madd","tink","icky","h123","103198","tine","surf","ssan","bang","speed","1128","onnie","bubba","23232","best","iant","lter","hhhh","nathan","gent","gina","vera","eart","riss","apol","marine","llis","ager","9999999","spec","renc","q1w2e3r4","lley","llll","07195","arad","mous","iann","rola","iter","aper","fylh","slayer","anet","erpo","trav","carlo","rrrr","orange","lent","herm","spir","cana","1232","kola","adim","01010","alexand","1414","ass1","alic","mish","a196","mily","drum","ter2","smith","11979","tits","asia","acka","21994","dger","r199","moll","ores","egor","ishe","x123","tyle","rangers","osta","alpha","haha","jesus","wer1","herr","nders","020219","clar","buddy","olas","tian","lovem","vfvf","rney","ley1","mans","oopy","rami","orth","lice","ttie","mero","babe","o200","carr","barr","lder","brook","klas","nikita","acer","anic","2334","21978","open","er20","er11","ina2","cowboys","mano","an123","read","anit","bara","rsch","iber","ties","gian","field","obby","q123","outh","ilia","anci","anga","na20","32323","down","ravi","ktor","llan","ine1","bren","112198","amat","21979","beat","3141","ndia","11978","solo","road","alma","amma","steph","internet","nich","bbbbb","nite","vita","arde","form","rans","ndro","austin","enna","mall","bloo","ants","107198","endo","1087","valer","icia","mack","ommy","anana","erbo","simp","dent","arty","1191","mach","asha1","cris","appe","simon","nard","alker","lovel","arga","icker","06195","mela","music","teme","bigg","chik","ler1","bite","rocke","nkin","ver1","lica","domin","geni","105198","aska","izard","coco","banan","tomm","11994","tasha","gang","anka","pook","petr","101199","stya","oone","illie","inner","adma","icho","iman","donn","0100","5123","inky","etta","123654","gand","tewa","9632","slut","maverick","lama","amber","mala","ksan","mona","mino","ddddd","bart","8097","eres","lolo","qazxsw","arks","olina","scha","brie","8098","ugar","richard","here","ntan","hamp","ysta","marg","mmmmm","01020","crazy","oles","soft","wins","drey","ney1","pire","gera","3000","serv","eddi","mercedes","alte","1321","dust","020319","020419","spank","unda","1017","qweasd","erbe","yfcn","magn","shor","horse","aaaaaaa","bern","reme","lett","snoop","artem","egas","guar","plat","bandit","nsta","2580","rdon","s199","108198","dona","horny","asil","ordo","nny1","1472","hear","walk","abbi","otto","baba","8912","ickl","boog","inha","erica","ical","1028","10120","1098","kota","ican","dest","harm","raci","onco","rice","evel","789456","qwas","post","tard","atar","unch","aleks","arah","hers","whatever","amba","guin","ellow","mode","1q2w3e","doug","natas","ffin","8050","tele","winn","1593","202198","burn","a111","steelers","lvin","nada","veta","erti","nna1","madi","ulle","zzzzzz","ena1","duck","4242","indo","oron","matrix","fhby","11995","020819","9119","andal","hoot","eway","abcde","deli","chas","issi","pand","iden","orte","list","rost","laster","punk","nior","heri","polo","nand","kitty","butter","rini","cking","110198","yana","olive","start","linda","1090","pala","051987","21977","1717","chuc","rule","020519","nima","entr","ailey","ador","haro","turn","eder","atti","brea","koff","hans","vero","mati","julia","arce","izza","7891","fucker","011990","orri","erik","leas","mother","natali","thead","arco","rant","erta","b123","020119","gator","heel","ard1","grea","anat","mer1","vfrc","020619","olden","ick1","help","bbit","mera","akot","pool","erst","erni","8951","inch","lame","nchi","death","5555555","1058","kati","011987","aras","lexi","rrie","ierr","mili","dboy","ates","kristi","perf","case","bean","asto","randy","oris","iles","falcon","1516","5050","llio","nati","inni","91989","anki","rame","kevin","207198","a2010","lest","a123456","rega","friend","chevy","aval","andon","red1","verp","lava","omar","kiri","as12","cara","amir","olit","hani","annon","tive","okey","nther","1092","estin","ickey","204198","11977","unit","dance","031988","arba","trai","juan","d1234","rger","11975","1079","020719","dell","rabb","rmin","thor","rlan","jean","jone","scorpio","11976","p123","shal","erlo","nest","hele","5566","en12","want","ayne","est1","erem","issy","208198","ygir","burg","s1234","forever","ions","enka","flower","uren","sass","051990","ashk","theb","isse","scho","2119","camp","031987","201198","tima","0012","ophi","les1","rene","9874","late","oome","205198","chip","hica","ento","loves","2131","pace","21976","inke","ction","little","duke","206198","elic","onat","ancer","sala","doll","onik","eria","cord","eanu","chang","gord","kaka","diab","asdfghj","elia","1237","umpe","dies","alam","gala","fort","nine","11121","1118","rker","2128","071987","avan","soph","oshi","knight","bomb","arra","jimmy","1314","1285","mple","like","imbo","bigt","1324","dodge","rchi","fend","ikol","1129","ocky","r198","1022","lege","inat","llo1","bber","041988","rade","ebel","kass","robi","elec","hari","aldo","otti","stef","ssma","erda","luca","samu","leri","tati","ears","adel","frea","iano","ya19","offe","yell","ochka","geli","esha","15051","dmin","morgan","bella","onna","21995","8910","31991","ameri","annah","isla","truck","asmin","071986","020919","anthe","s198","compa","beth","041986","a777","121987","061986","raider","grac","atash","051988","stle","joke","041987","male","4455","driv","tita","051986","nato","amal","0010","3030","patrick","09876","jjjjj","charle","item","41984","edog","1290","121986","stop","demon","ious","lissa","cheste","5935","4725","chol","warr","atro","entin","umbe","ma19","22011","tata","asan","host","skip","on19","lipp","abra","nish","alib","erro","ench","mpir","1190","1077","10111","10121","dogs","lphin","nnet","ippy","berl","71990","llet","011988","junio","203198","41985","arit","71985","cons","ronc","craft","ongo","ingl","1086","ka12","iking","81990","ooooo","ergi","ritt","hester","10011","031986","cats","brav","011986","7258","2123","k199","lita","81985","011985","0990","johnny","terp","samsung","mang","city","71989","micke","huck","91986","etty","desi","aura","021019","oser","fall","key1","ssin","timo","joseph","viki","orgi","061987","world","anja","iabl","hjcn","mass","hank","5454","anky","comm","21975","051985","91988","81987","arsh","fami","q2w3e4r","051989","obra","twin","011989","gabr","rles","muff","elove","209198","61990","1127","071988","qqqqqq","imbe","erty12","baile","061988","ilip","rico","dward","rova","erde","ghjc","lect","eone","cky1","irina","0019","monster","9357","oster","lish","edwar","3698","shing","inho","idas","1245","01041","shak","1038","ppppp","girls","5656","45612","yste","5000","smar","amie","ners","raven","pean","meric","ulie","laure","look","n1234","210198","101987","2344","idge","ymrf","rpoo","31985","ffer","081988","viper","tton","thing","031990","choo","101986","41990","oodl","right","miller","31989","evan","onto","bian","eigh","manc","lace","lema","ggggg","heather","nnnn","tenn","orin","emar","ssio","hort","loui","camaro","squi","carm","31983","061985","8908","inga","2341","kath","7852","kbyf","stea","view","lldog","pson","ty123","ris1","ert1","1234q","eles","ouch","20011","hman","ova1","arik","dirt","1188","8904","name","ooby","christi","dria","ethe","plea","ra19","1080","boro","dako","pain","earl","rple","ocket","deep","livi","elon","01031","1068","61989","sabe","01021","tyrj","hark","ontr","rink","vfhb","amant","utch","in12","lean","01091","hara","nsto","rocks","e1234","20021","dolphi","asda","iell","anin","fghjk","icki","albert","rato","latin","bulldo","1082","505198","popo","ceman","eras","dog1","23021","mell","71983","mario","ber1","smile","rlos","hane","roke","1016","homer","ntai","xxxxxxx","winte","storm","lova","purpl","kare","41991","coob","091987","nita","count","021988","okin","2342","081989","diana","ione","ntha","pira","pear","dawg","beav","imal","obbi","aroli","71984","2333","081986","tdog","bigbo","rove","erba","blad","bett","usha","ndri"]}(Constants=exports.Constants||(exports.Constants={})); @@ -26,12 +26,12 @@ Array.prototype.toHumanString=function(){var t=this.length;if(0==t)return"(empty "use strict";exports.__esModule=!0;var NeuralNetwork,PasswordMeter=require("./PasswordMeter"),Constants=require("./constants");!function(e){var t=!0,r={};function n(e){return Math.log(e)/Math.LN10}function s(e,r){e*=function(e){var t=1,r=e.substr(1);if(e.charAt(0)===e.charAt(0).toUpperCase()&&e.charAt(0)!==e.charAt(0).toLowerCase()&&r===r.toLowerCase())t=1.5;else if(-1==e.search(/[a-z]/)){var n=e.replace(Constants.Constants.UPPERCASE_LETTERS_GLOBAL,"");e.length>=n.length+3&&(t=2)}else e!==e.toLowerCase()&&(t=10);return t}(r),t=!1;var s=n(e);e<=1&&(s=n(1.1)),r.length>0&&e==Number.POSITIVE_INFINITY&&(s=100),isNaN(e)&&(s=-1),PasswordMeter.PasswordMeter.instance.getNN().setNeuralNetNum(r,s)}function o(e,t){s(e,t),PasswordMeter.PasswordMeter.instance.getUI().displayRating(t)}function a(e,t){s(e,t),PasswordMeter.PasswordMeter.instance.getUI().synthesizeFixed(t)}e.log10=n,e.nnFixedCallback=a;var u,i,N,c,l,w=function(){function e(e,t){this.nn=e,this.nnfixed=t}return e.prototype.heardFromNn=function(){return!t},e.prototype.setNeuralNetNum=function(e,t){r[e]=t},e.prototype.getNeuralNetNum=function(e){return r[e]},e.prototype.queryGuessNumber=function(e,t){t?this.nnfixed.query_guess_number(e):this.nn.query_guess_number(e)},e}();e.NeuralNetworkInterface=w,u=PasswordMeter.PasswordMeter.instance,i=u.getConfig().neuralNetworkConfig,N=new NeuralNetworkClient(a,i),c=new NeuralNetworkClient(o,i),l=new w(c,N),u.setNN(l)}(NeuralNetwork=exports.NeuralNetwork||(exports.NeuralNetwork={})); },{"./PasswordMeter":3,"./constants":6}],10:[function(require,module,exports){ -"use strict";exports.__esModule=!0;var RuleFunctions,PasswordMeter=require("./PasswordMeter"),Helper=require("./helper"),Constants=require("./constants"),NeuralNetwork=require("./nn-misc");!function(e){e.verifyMinimumRequirements=function(e,t){var s=PasswordMeter.PasswordMeter.instance,r=s.getConfig(),a=s.getDictionaries(),n=r.colors.compliant,o=r.colors.noncompliant,i=r.symbols.compliant,l=r.symbols.noncompliant,c={},h={};if(r.length.active){var u=r.length.minLength,g=r.length.maxLength,d=!1,p="";p=g>0?"Contain "+u.toString()+"-"+g.toString()+" characters":"Contain "+u.toString()+"+ characters",e.length>=u&&(e.length<=g||0===g)&&(d=!0),p=d?""+i+p:""+l+p,p+="",c.length=p,h.length=d}var m=!1,f=!1,w=!1,b=!1,v=0;if(e.match(Constants.Constants.LOWERCASE_LETTERS_GLOBAL)&&(v++,m=!0),e.match(Constants.Constants.UPPERCASE_LETTERS_GLOBAL)&&(v++,f=!0),e.match(Constants.Constants.DIGITS_GLOBAL)&&(v++,w=!0),e.match(Constants.Constants.SYMBOLS_GLOBAL)&&(v++,b=!0),r.classCount.active){var y=r.classCount.minCount,C=r.classCount.maxCount;p="",d=!1,p=4===C?"Use "+y.toString()+"+ of the following: ":"Use "+y.toString()+"-"+C.toString()+" of the following: ",p+="uppercase letters; lowercase letters; digits; symbols",v>=y&&v<=C&&(d=!0),p=d?""+i+p:""+l+p,p=p+="",c.classCount=p,h.classCount=d}if(r.classRequire.active){var A=r.classRequire.upperCase,x=r.classRequire.lowerCase,M=r.classRequire.digits,T=r.classRequire.symbols;p="",d=!1,x&&(p.length>0?p+=" and a lowercase letter":p="Contain a lowercase letter"),A&&(p.length>0?p+=" and an uppercase letter":p="Contain an uppercase letter"),M&&(p.length>0?p+=" and a digit":p="Contain a digit"),T&&(p.length>0?p+=" and a symbol":p="Contain a symbol"),x&&!m||A&&!f||M&&!w||T&&!b||(d=!0),p=d?""+i+p:""+l+p,p=p+="",c.classRequire=p,h.classRequire=d}if(r.classAllow.active){var k=r.classAllow.upperCase,S=r.classAllow.lowerCase,L=r.classAllow.digits,E=r.classAllow.symbols;if(p="",d=!1,S||(p.length>0?p+=" or lowercase letters":p="Not include lowercase letters"),k||(p.length>0?p+=" or uppercase letters":p="Not include uppercase letters"),L||(p.length>0?p+=" or digits":p="Not include digits"),E||(p.length>0?p+=" or symbols":p="Not include symbols"),!S&&m||!k&&f||!L&&w||!E&&b||(d=!0),d)p=""+i+p;else{var P=[];!S&&m&&(P=P.concat(e.match(Constants.Constants.LOWERCASE_LETTERS))),!k&&f&&(P=P.concat(e.match(Constants.Constants.UPPERCASE_LETTERS))),!L&&w&&(P=P.concat(e.match(Constants.Constants.DIGITS))),!E&&b&&(P=P.concat(e.match(Constants.Constants.SYMBOLS)));var R=(P=P.removeDuplicates()).indexOf(" ");R>-1&&(P[R]="[space]"),p=""+l+(p+=" (You used "+P.join(", ")+")")}p=p+="",c.classAllow=p,h.classAllow=d}if(r.blacklist.active){p="",d=!1,p="Not be an extremely common password";var H=!1;if(e.length>0){var N=e;r.blacklist.stripDigitsSymbolsFromPassword&&(N=N.replace(/[^a-zA-Z]/gi,"")),r.blacklist.caseSensitive||(N=N.toLowerCase()),H=a.blacklistRejects(N)}(d=!H||0===e.length||-1!=r.blacklist.lengthException&&e.length>=r.blacklist.lengthException)||(p=""+l+p+""),d||(c.blacklist=p),h.blacklist=d}if(r.forbidChars.active){var D=r.forbidChars.list;p="",d=!1,p="Not include the following characters: "+W;for(var O=e.removeDuplicateChars(),W="",z=0;zConstants.Constants.endASCII||D.indexOf(O.charAt(z))>=0)&&(W+=O.charAt(z));0===W.length&&(d=!0),d||(p=""+l+p+""),d||(c.forbidChars=p),h.forbidChars=d}if(r.repeatChars.active){var q=r.repeatChars.limit;p="",d=!1,p="Not repeat the same character "+q.toString()+"+ times in a row";for(var I=[],_=q-1;_"+i+p:""+l+(p+=" ("+I.removeDuplicates().join(", ")+")"),p+="",c.repeatChars=p,h.repeatChars=d}if(r.usernameDifference.active){var G=r.usernameDifference.limit;p="",d=!1,p="Not base your password around your username";for(var B=e.toLowerCase(),U=t.toLowerCase();U.length>0&&B.indexOf(U)>-1;)B=B.substr(0,B.indexOf(U))+B.substr(B.indexOf(U)+U.length);(0==U.length||0==e.length||B.length>=G)&&(d=!0),d||(p=""+l+p+""),d||(c.usernameDifference=p),h.usernameDifference=d}if(r.minLogNnGuessNum.active){d=!1,p="";var Z=r.minLogNnGuessNum.threshold,Y=PasswordMeter.PasswordMeter.instance.getNN().getNeuralNetNum(e),$=Y+NeuralNetwork.NeuralNetwork.log10(r.neuralNetworkConfig.scaleFactor);Y<0?console.log("looking up NN guess number: "+e):Y>Z?(d=!0,console.log("high enough NN guess number: "+e+" ("+Y+" > "+Z+") [unconservative NN guess number: "+$+"]")):(console.log("too low NN guess number: "+e+" ("+Y+" < "+Z+") [unconservative NN guess number: "+$+"]"),p=""+l+r.minLogNnGuessNum.rejectionFeedback),d||(c.minLogNnGuessNum=p),h.minLogNnGuessNum=d}if(r.sameChars.active){var F=r.sameChars.limit;p="",d=!1,e.length>=r.sameChars.lengthException||function(e,t){for(var s={},r=0;rt)return!1}else s[a]=1}return!0}(e,F)?d=!0:p="Not contain the same character more than "+F.toString()+"+ times",d||(p=""+l+p+"",c.sameChars=p),h.sameChars=d}r.prohibitKnownLeaked.active&&(d=!1,p="",e.length"+l+"Not use a password found in previous security leaks",c.prohibitKnownLeaked=p),h.prohibitKnownLeaked=d);var K=!0;for(var J in h)if(!(K=K&&h[J]))break;return{compliant:K,detail:{compliance:h,explanation:c}}},e.pwLength=function(e){var t=e.length,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().length.maxLength;return t<16&&(0===n||t=65&&e.charCodeAt(i)<=90&&t++;if(t<.15*e.length&&o){s="Consider using more uppercase letters",r="Consider using ",r+=(t+1).toString()+" or more uppercase letters",a="Uppercase letters are surprisingly uncommon in passwords, which makes them hard to guess";var l=65+Math.floor(26*Math.random()),c=Math.floor(1+Math.random()*(e.length-1));n=e.slice(0,c)+String.fromCharCode(l)+e.slice(c)}return{count:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:n}},e.countLC=function(e){for(var t=0,s="",r="",a="",n="",o=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.lowerCase,i=0;i=97&&e.charCodeAt(i)<=122&&t++;if(t<.15*e.length&&o){a="Having variety in the types of characters you use makes your password harder to guess",s="Consider using more lowercase letters",r="Consider using ",r+=t+1+" or more lowercase letters";var l=97+Math.floor(26*Math.random()),c=Math.floor(1+Math.random()*(e.length-1));n=e.slice(0,c)+String.fromCharCode(l)+e.slice(c)}return{count:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:n}},e.countDIGS=function(e){for(var t=0,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.digits,o=0;o=48&&e.charCodeAt(o)<=57&&t++;return t<.15*e.length&&n&&(s="Consider using more digits",a="Most passwords contain no digits or digits in predictable places; doing otherwise makes your password harder to guess",r="Consider using ",r+=t+1+" or more digits"),{count:t,reasonWhy:a,publicText:s,sensitiveText:r}},e.countSYMS=function(e){var t=e.replace(/[A-Za-z0-9]/g,"").length,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.symbols;return t<.15*e.length&&n&&(s="Consider using more symbols",a="Few passwords contain symbols, which makes passwords with symbols harder to guess",r="Consider using ",r+=t+1+" or more symbols"),{count:t,reasonWhy:a,publicText:s,sensitiveText:r}},e.characterClasses=function(e){var t=0;e.match(Constants.Constants.LOWERCASE_LETTERS)&&t++,e.match(Constants.Constants.UPPERCASE_LETTERS)&&t++,e.match(Constants.Constants.DIGITS)&&t++,e.match(Constants.Constants.SYMBOLS)&&t++;var s=t,r="",a="",n="",o=PasswordMeter.PasswordMeter.instance.getConfig().classAllow;if(e.match(Constants.Constants.UPPERCASE_LETTERS)||e.match(Constants.Constants.DIGITS)||e.match(Constants.Constants.SYMBOLS))if(e.match(Constants.Constants.DIGITS)||e.match(Constants.Constants.SYMBOLS))e.match(Constants.Constants.UPPERCASE_LETTERS)||e.match(Constants.Constants.SYMBOLS)?e.match(Constants.Constants.SYMBOLS)||o.symbols&&(r="Add symbols in unpredictable locations",a="Add symbols in unpredictable locations",n="Because only 1% of passwords use symbols, adding them unpredictably strengthens your password"):(i=[],l="",o.symbols&&i.push("symbols"),o.upperCase&&i.push("uppercase letters"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="42% of passwords contain only lowercase letters and number, making them easy for attackers to guess");else{var i=[],l="";o.symbols&&i.push("symbols"),o.digits&&i.push("digits"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="42% of passwords contain only letters, making them easy for attackers to guess"}else{var i=[],l="";o.symbols&&i.push("symbols"),o.digits&&i.push("digits"),o.upperCase&&i.push("uppercase letters"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="38% of passwords contain only lowercase letters, making them easy for attackers to guess"}return{count:s,reasonWhy:n,publicText:r,sensitiveText:a}},e.uppercasePredictable=function(e){var t=0,s="",r="",a="",n="",o="";if(e.charAt(0)===e.charAt(0).toUpperCase()&&e.charAt(0)!==e.charAt(0).toLowerCase()){var i=e.substr(1);if(i===i.toLowerCase()){t=1,s="Capitalize a letter in the middle",r="Capitalize a letter in the middle, rather than the first character",n=e.charAt(0).escapeHTML(),a="30% of people also capitalize only the first character";for(var l=new Array,c=0;c=97&&e.charCodeAt(c)<=122&&l.push(c);var h=Math.floor(Math.random()*l.length);o=e.substring(0,l[h]),o+=e.charAt(l[h]).toUpperCase(),o+=e.substring(l[h]+1)}}if(-1==e.search(/[a-z]/)){var u=e.replace(/[A-Z]/g,"");if(e.length>=u.length+3){t=1,s="Mix up your capitalization",r="Mix up your capitalization, rather than capitalizing everything",a="21% of passwords also contain only uppercase letters";var g=new Array;for(c=0;c=65&&e.charCodeAt(c)<=90&&g.push(c);var d=Math.floor(Math.random()*g.length);o=e.substring(0,g[d]),o+=e.charAt(g[d]).toLowerCase(),o+=e.substring(g[d]+1)}}return{score:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:o,problemText:n}},e.digitsPredictable=function(e){var t=0,s="",r="",a="",n="",o="",i=[],l=new RegExp("[^0-9]"),c=new RegExp("^[0-9]+[^0-9]+$"),h=new RegExp("^[^0-9]+[0-9]+$");if(e.length>=4&&!e.match(l)){t=1,s="Add more letters and symbols to your password",r="Add characters other than digits to your password",a=e.escapeHTML(),n="35% of people also use only digits";var u=58+Math.floor(68*Math.random()),g=Math.floor(1+Math.random()*(e.length-1));o=e.slice(0,g)+String.fromCharCode(u)+e.slice(g);for(var d=0;d=4&&e.match(c)){t=1,r="Consider inserting digits into the middle, not just at the beginning",s="Consider inserting digits into the middle",n="10% of people also put digits at the beginning of the password";for(var p=1;e.charCodeAt(p)>=48&&e.charCodeAt(p)<=57;)p++;for(a=e.slice(0,p).escapeHTML(),g=Math.floor(p+1+Math.random()*(e.length-p-1)),o=e.slice(p,g)+e.slice(0,p)+e.slice(g),d=0;d=4&&e.match(h)){t=1,r="Consider inserting digits into the middle, not just at the end",s="Consider inserting digits into the middle",n="38% of people also put digits at the end of the password";for(var m=e.length-2;e.charCodeAt(m)>=48&&e.charCodeAt(m)<=57;)m--;for(a=e.slice(m+1).escapeHTML(),g=Math.floor(1+Math.random()*(e.length-m-1)),o=e.slice(0,g)+e.slice(m+1)+e.slice(g,m+1),d=0;d=4&&e.match(l)){t=1,r="Move symbols and digits earlier, rather than just at the end",s="Move symbols and digits elsewhere in your password",a=e.match(h)[0].escapeHTML(),n="14% of people also use letters, followed by symbols, followed by digits";var u=e.search(h);a=e.slice(u).escapeHTML();var g=Math.floor(1+Math.random()*(u-1));o=e.slice(0,g)+e.slice(u)+e.slice(g,u);for(var d=0;d=4&&e.match(c)){for(t=1,r="Move your symbols earlier, rather than just at the end",s="Move symbols and digits elsewhere in your password",n="16% of people also put symbols only at the end of the password",u=e.search(h),a=e.slice(u).escapeHTML(),g=Math.floor(1+Math.random()*(u-1)),o=e.slice(0,g)+e.slice(u)+e.slice(g,u),d=0;d":[3,9],"/":[3,10],"?":[3,10]," ":[4,5]},s="",r=0;rl&&"0,0"!==h&&(i=c,l=r-c),c=r)}var u=l+1,g="",d="",p="",m="";return u>=4&&(g="Avoid using a pattern on your keyboard",d="Avoid using a pattern on your keyboard like "+(p=s.substring(i,i+l+1).escapeHTML())+"",m="Because keyboard patterns are very common in passwords, attackers know to guess them"),u<3&&(u=0),{score:u,reasonWhy:m,publicText:g,sensitiveText:d,problemText:p}},e.duplicatedCharacters=function(e){var t=e.split("").removeDuplicates(),s=e.length-t.length,r="",a="",n="",o="";if(t.length<=.5*e.length&&t.length<=5){o="",r="Have more variety in the characters you choose";var i="";t.length>1&&(i="s"),a="Have more variety than repeating the same "+t.length+" character"+i+" ("+Helper.Helper.boldAll(t.sort()).toHumanString()+")",n="Passwords that use only a few different characters are easy for attackers to guess"}return{count:s,reasonWhy:n,publicText:r,sensitiveText:a,problemText:o}},e.repeatedSections=function(e){for(var t=0,s="",r="",a="",n="",o=!1,i=(e=e.toLowerCase()).length,l=Math.floor(i/2);l>=3;l--){for(var c=0;c<=i-l;c++){for(var h=e.substring(c,c+l),u=h.split("").reverse().join(""),g=0;g+l<=c;g++)e.substring(g,g+l)===h?(t+=l,a=h.escapeHTML()):e.substring(g,g+l)===u&&(t+=l,a=h.escapeHTML(),o=!0);for(g=c+l;g+l<=i;g++)e.substring(g,g+l)===h?(t+=l,a=h.escapeHTML()):e.substring(g,g+l)===u&&(t+=l,a=h.escapeHTML(),o=!0);if(t>=3){t>=4?(s="Avoid repeating sections",r="Avoid repeating sections ("+a+")",n="In their guessing, attackers know to try duplicating parts of the password",o&&(s+=", forwards or backwards",r+=", forwards or backwards")):a="";break}}if(t>0)break}return{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.repeats=function(e){for(var t=e.length,s=1,r=1,a="",n="",o="",i="",l="",c=1;cs&&(s=r,a=e[c]):r=1;var h=s;if(s>=3){n="Don't repeat the same character many times in a row";for(var u=0;u"+(i=i.escapeHTML())+") many times in a row",l="Hitting the same key over and over adds little to your password's strength"}return 1===h&&(h=0),{count:h,reasonWhy:l,publicText:n,sensitiveText:o,problemText:i}},e.contextual=function(e,t){for(var s=0,r="",a="",n="",o="",i=e,l=0;l=5){s=u.length,r="Don't use your account information in your password",a="Don't use your account information ("+(n=u.escapeHTML())+") in your password",o="Attackers know to guess your username and email address as part of your password";var g=e.indexOf(u);g>-1&&(i=e.substr(0,g)+e.substr(g+u.length))}return{count:s,reasonWhy:o,publicText:r,sensitiveText:a,problemText:n,remaining:i}},e.commonSubstringCheck=function(e){var t=0,s="",r="",a="",n="",o=new Array;e=e.toLowerCase();for(var i=Constants.Constants.blacklistedSubstrings,l=0;l0){s="Avoid strings of characters commonly found in passwords",r="Avoid strings of characters commonly found in passwords like "+o.join(" and ")+"",n="Even if they don't make sense, these strings of characters show up in many passwords, which makes them bad to use in yours.",a=o[0].escapeHTML();for(var c=0;c as part of your own password",n=e[r].escapeHTML();return{length:e[r].length,reasonWhy:s,publicText:"Avoid using very common passwords as part of your own password",sensitiveText:a,problemText:n}}return{length:0,reasonWhy:s,publicText:"",sensitiveText:"",problemText:""}},e.blacklist=function(e){for(var t=PasswordMeter.PasswordMeter.instance.getConfig(),s=PasswordMeter.PasswordMeter.instance.getHelper(),r=t.ignoredWords,a="",n="",o="",i="",l=e,c=[],h=new RegExp("[^A-Za-z]"),u=(e=(e=e.toLowerCase()).replace(/[-_ ]/g,"")).split(/[^a-z01345@$]+/),g=(u=u.filter(function(e){return e})).listSubstringsMinMax(1,void 0),d=0;d-1&&(c.push(g[d]),p=g[d])}if(p.length>0){for(0==o.length&&(o=g[d].escapeHTML()),f=0;f-1){u.splice(f,1,u[f].substring(0,b),u[f].substring(b+p.length)),u=u.filter(function(e){return e});break}}g=u.listSubstringsMinMax(1,p.length),p="",d=0}else d++}var v=0;if(c.length>0){for(a="Don't use site-specific terms in your password",d=0;d-1&&(l=l.substr(0,y)+l.substr(y+c[d].length))}n="Don't use site-specific terms ("+Helper.Helper.boldAll(c.removeDuplicates()).toHumanString()+")",i="Attackers target their attacks to words used on a particular service"}return{length:v,reasonWhy:i,publicText:a,sensitiveText:n,problemText:o,remaining:l}},e.combinedDictCheck=function(e){for(var t="",s="",r="",a="",n=100,o=new Array,i=new Array,l=new Array,c=new Array,h=new Array,u=PasswordMeter.PasswordMeter.instance,g=u.getDictionaries(),d=u.getHelper(),p=new Array,m=new Array,f=(e=e.replace(/[-_ ]/g,"")).split(/[^A-Za-z012345!&@$]+/),w=(f=f.filter(function(e){return e})).listSubstringsMinMax(4,void 0),b=0;b0){for(0==r.length&&(r=w[b].escapeHTML()),A=0;A-1){f.splice(A,1,f[A].substring(0,T),f[A].substring(T+v.length)),f=f.filter(function(e){return e});break}}w=f.listSubstringsMinMax(4,v.length),v="",b=0}else b++}var k=new Array,S=new Array,L=0,E=0,P=function(e,t){if(e.length>0){k.push(t);for(var s=0;s0&&(a="Attackers use software that automatically guesses millions of words commonly found in dictionaries, wordlists, or other people's passwords",t="Don't use ",s="Don't use ",n<100&&(a+=", including simple transformations of those words/phrases where they substitute digits and symbols for letters"),t+=k.join(" or "),s+=S.join(" or ")),{length:L,reasonWhy:a,publicText:t,sensitiveText:s,problemText:r,dictionaryTokens:E,substitutionCommonness:n=100-n}},e.identifyDates=function(e){var t=0,s="",r="",a="",n="",o=[],i=PasswordMeter.PasswordMeter.instance.getHelper(),l=[e],c=function(e){var s=i.matchHelper(l,e);s.score>0&&(t+=s.score,o=o.concat(s.matched.toString()),l=s.revisedParts)},h="([ .-/])",u="((0\\d|1[012])|\\d)",g="(january|february|march|april|may|june|july|august|september|october|november|december)",d="([012]\\d|3[01])",p="(\\d\\d)",m="(19\\d\\d|20[01234]\\d)";return c(new RegExp(u+h+d+h+m,"g")),c(new RegExp(d+h+u+h+m,"g")),c(new RegExp(u+h+d+h+p,"g")),c(new RegExp(d+h+u+h+p,"g")),c(new RegExp(u+d+m,"g")),c(new RegExp(d+u+m,"g")),c(new RegExp(g+m,"ig")),c(new RegExp(g+p,"ig")),c(new RegExp(u+h+d,"g")),c(new RegExp(d+h+u,"g")),c(new RegExp(m,"g")),t>0&&(s="Avoid using dates",r="Avoid using dates like "+Helper.Helper.boldAll(o).toHumanString(),n="Dates and years in any format are quite common in passwords",a=o[0].escapeHTML()),{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.alphabeticSequenceCheck=function(e){var t=0,s="",r="",a="",n="",o=[],i=[];o[0]=e.charCodeAt(0);for(var l=1;lh&&0!==g&&(c=u,h=l-u),u=l),1===(t=h)&&(t=0),t>=2&&t++,t>=4){var d=e.substr(c,c+h+1);a=d.escapeHTML();var p=new RegExp("^[0-9]+$");d.match(p)?(s="Avoid numerical patterns",r="Avoid numerical patterns like "+a+""):(s="Avoid patterns from the alphabet",r="Avoid patterns from the alphabet like "+a+""),n="Attackers know to guess sequences following the alphabet, in addition to repeated characters or patterns on your keyboard"}}return{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.structurePredictable=function(e){var t="",s="",r="",a=0,n=(e=(e=(e=(e=e.replace(/[A-Z]/g,"U")).replace(/[a-z]/g,"L")).replace(/[0-9]/g,"D")).replace(/[^A-Za-z0-9]/g,"S"),Constants.Constants.commonStructures.indexOf(e));if(n>=0){a=2124-n,r="One technique attackers use is to try all possible passwords within common structures, or arrangements of character classes (e.g., where lowercase letters and digits are located)",s=(t="The way you structure your password is predictable")+" (";for(var o=!0,i=0;i1&&(s+="s"),i+=l}s+=")"}return{score:a,reasonWhy:r,publicText:t,sensitiveText:s}}}(RuleFunctions=exports.RuleFunctions||(exports.RuleFunctions={})); +"use strict";exports.__esModule=!0;var RuleFunctions,PasswordMeter=require("./PasswordMeter"),Helper=require("./helper"),Constants=require("./constants"),NeuralNetwork=require("./nn-misc");!function(e){e.verifyMinimumRequirements=function(e,t){var s=PasswordMeter.PasswordMeter.instance,r=s.getConfig(),a=s.getDictionaries(),n=r.colors.compliant,o=r.colors.noncompliant,i=r.symbols.compliant,l=r.symbols.noncompliant,c={},h={};if(r.length.active){var u=r.length.minLength,g=r.length.maxLength,d=!1,p="";p=g>0?"Contain "+u.toString()+"-"+g.toString()+" characters":"Contain "+u.toString()+"+ characters",e.length>=u&&(e.length<=g||0===g)&&(d=!0),p=d?""+i+p:""+l+p,p+="",c.length=p,h.length=d}var m=!1,f=!1,w=!1,b=!1,v=0;if(e.match(Constants.Constants.LOWERCASE_LETTERS_GLOBAL)&&(v++,m=!0),e.match(Constants.Constants.UPPERCASE_LETTERS_GLOBAL)&&(v++,f=!0),e.match(Constants.Constants.DIGITS_GLOBAL)&&(v++,w=!0),e.match(Constants.Constants.SYMBOLS_GLOBAL)&&(v++,b=!0),r.classCount.active){var y=r.classCount.minCount,C=r.classCount.maxCount;p="",d=!1,p=4===C?"Use "+y.toString()+"+ of the following: ":"Use "+y.toString()+"-"+C.toString()+" of the following: ",r.randomizeOrderCharClassRequirement?p+=PasswordMeter.PasswordMeter.instance.getUI().getCharClassStringForCharClassCountReq():p+="uppercase letters; lowercase letters; digits; symbols",v>=y&&v<=C&&(d=!0),p=d?""+i+p:""+l+p,p=p+="",c.classCount=p,h.classCount=d}if(r.classRequire.active){var A=r.classRequire.upperCase,x=r.classRequire.lowerCase,M=r.classRequire.digits,T=r.classRequire.symbols;p="",d=!1,r.randomizeOrderCharClassRequirement?p+=PasswordMeter.PasswordMeter.instance.getUI().getCharClassStringForMandatoryCharClassReq():(x&&(p.length>0?p+=" and a lowercase letter":p="Contain a lowercase letter"),A&&(p.length>0?p+=" and an uppercase letter":p="Contain an uppercase letter"),M&&(p.length>0?p+=" and a digit":p="Contain a digit"),T&&(p.length>0?p+=" and a symbol":p="Contain a symbol")),x&&!m||A&&!f||M&&!w||T&&!b||(d=!0),p=d?""+i+p:""+l+p,p=p+="",c.classRequire=p,h.classRequire=d}if(r.classAllow.active){var k=r.classAllow.upperCase,S=r.classAllow.lowerCase,L=r.classAllow.digits,P=r.classAllow.symbols;if(p="",d=!1,S||(p.length>0?p+=" or lowercase letters":p="Not include lowercase letters"),k||(p.length>0?p+=" or uppercase letters":p="Not include uppercase letters"),L||(p.length>0?p+=" or digits":p="Not include digits"),P||(p.length>0?p+=" or symbols":p="Not include symbols"),!S&&m||!k&&f||!L&&w||!P&&b||(d=!0),d)p=""+i+p;else{var E=[];!S&&m&&(E=E.concat(e.match(Constants.Constants.LOWERCASE_LETTERS))),!k&&f&&(E=E.concat(e.match(Constants.Constants.UPPERCASE_LETTERS))),!L&&w&&(E=E.concat(e.match(Constants.Constants.DIGITS))),!P&&b&&(E=E.concat(e.match(Constants.Constants.SYMBOLS)));var R=(E=E.removeDuplicates()).indexOf(" ");R>-1&&(E[R]="[space]"),p=""+l+(p+=" (You used "+E.join(", ")+")")}p=p+="",c.classAllow=p,h.classAllow=d}if(r.blacklist.active){p="",d=!1,p="Not be an extremely common password";var H=!1;if(e.length>0){var N=e;r.blacklist.stripDigitsSymbolsFromPassword&&(N=N.replace(/[^a-zA-Z]/gi,"")),r.blacklist.caseSensitive||(N=N.toLowerCase()),H=a.blacklistRejects(N)}(d=!H||0===e.length||-1!=r.blacklist.lengthException&&e.length>=r.blacklist.lengthException)||(p=""+l+p+""),d||(c.blacklist=p),h.blacklist=d}if(r.forbidChars.active){var D=r.forbidChars.list;p="",d=!1,p="Not include the following characters: "+W;for(var O=e.removeDuplicateChars(),W="",q=0;qConstants.Constants.endASCII||D.indexOf(O.charAt(q))>=0)&&(W+=O.charAt(q));0===W.length&&(d=!0),d||(p=""+l+p+""),d||(c.forbidChars=p),h.forbidChars=d}if(r.repeatChars.active){var z=r.repeatChars.limit;p="",d=!1,p="Not repeat the same character "+z.toString()+"+ times in a row";for(var I=[],_=z-1;_"+i+p:""+l+(p+=" ("+I.removeDuplicates().join(", ")+")"),p+="",c.repeatChars=p,h.repeatChars=d}if(r.usernameDifference.active){var G=r.usernameDifference.limit;p="",d=!1,p="Not base your password around your username";for(var U=e.toLowerCase(),B=t.toLowerCase();B.length>0&&U.indexOf(B)>-1;)U=U.substr(0,U.indexOf(B))+U.substr(U.indexOf(B)+B.length);(0==B.length||0==e.length||U.length>=G)&&(d=!0),d||(p=""+l+p+""),d||(c.usernameDifference=p),h.usernameDifference=d}if(r.minLogNnGuessNum.active){d=!1,p="";var Z=r.minLogNnGuessNum.threshold,F=PasswordMeter.PasswordMeter.instance.getNN().getNeuralNetNum(e),Y=F+NeuralNetwork.NeuralNetwork.log10(r.neuralNetworkConfig.scaleFactor);F<0?console.log("(still) looking up NN guess number: "+e):F>Z?(d=!0,console.log("high enough NN guess number: "+e+" ("+F+" > "+Z+") [unconservative NN guess number: "+Y+"]")):(console.log("too low NN guess number: "+e+" ("+F+" < "+Z+") [unconservative NN guess number: "+Y+"]"),p=""+l+r.minLogNnGuessNum.rejectionFeedback),d||(c.minLogNnGuessNum=p),h.minLogNnGuessNum=d}if(r.sameChars.active){var $=r.sameChars.limit;p="",d=!1,e.length>=r.sameChars.lengthException||function(e,t){for(var s={},r=0;rt)return!1}else s[a]=1}return!0}(e,$)?d=!0:p="Not contain the same character more than "+$.toString()+"+ times",d||(p=""+l+p+"",c.sameChars=p),h.sameChars=d}r.prohibitKnownLeaked.active&&(d=!1,p="",e.length"+l+"Not use a password found in previous security leaks",c.prohibitKnownLeaked=p),h.prohibitKnownLeaked=d);var K=!0;for(var J in h)if(!(K=K&&h[J]))break;return{compliant:K,detail:{compliance:h,explanation:c}}},e.pwLength=function(e){var t=e.length,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().length.maxLength;return t<16&&(0===n||t=65&&e.charCodeAt(i)<=90&&t++;if(t<.15*e.length&&o){s="Consider using more uppercase letters",r="Consider using ",r+=(t+1).toString()+" or more uppercase letters",a="Uppercase letters are surprisingly uncommon in passwords, which makes them hard to guess";var l=65+Math.floor(26*Math.random()),c=Math.floor(1+Math.random()*(e.length-1));n=e.slice(0,c)+String.fromCharCode(l)+e.slice(c)}return{count:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:n}},e.countLC=function(e){for(var t=0,s="",r="",a="",n="",o=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.lowerCase,i=0;i=97&&e.charCodeAt(i)<=122&&t++;if(t<.15*e.length&&o){a="Having variety in the types of characters you use makes your password harder to guess",s="Consider using more lowercase letters",r="Consider using ",r+=t+1+" or more lowercase letters";var l=97+Math.floor(26*Math.random()),c=Math.floor(1+Math.random()*(e.length-1));n=e.slice(0,c)+String.fromCharCode(l)+e.slice(c)}return{count:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:n}},e.countDIGS=function(e){for(var t=0,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.digits,o=0;o=48&&e.charCodeAt(o)<=57&&t++;return t<.15*e.length&&n&&(s="Consider using more digits",a="Most passwords contain no digits or digits in predictable places; doing otherwise makes your password harder to guess",r="Consider using ",r+=t+1+" or more digits"),{count:t,reasonWhy:a,publicText:s,sensitiveText:r}},e.countSYMS=function(e){var t=e.replace(/[A-Za-z0-9]/g,"").length,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.symbols;return t<.15*e.length&&n&&(s="Consider using more symbols",a="Few passwords contain symbols, which makes passwords with symbols harder to guess",r="Consider using ",r+=t+1+" or more symbols"),{count:t,reasonWhy:a,publicText:s,sensitiveText:r}},e.characterClasses=function(e){var t=0;e.match(Constants.Constants.LOWERCASE_LETTERS)&&t++,e.match(Constants.Constants.UPPERCASE_LETTERS)&&t++,e.match(Constants.Constants.DIGITS)&&t++,e.match(Constants.Constants.SYMBOLS)&&t++;var s=t,r="",a="",n="",o=PasswordMeter.PasswordMeter.instance.getConfig().classAllow;if(e.match(Constants.Constants.UPPERCASE_LETTERS)||e.match(Constants.Constants.DIGITS)||e.match(Constants.Constants.SYMBOLS))if(e.match(Constants.Constants.DIGITS)||e.match(Constants.Constants.SYMBOLS))e.match(Constants.Constants.UPPERCASE_LETTERS)||e.match(Constants.Constants.SYMBOLS)?e.match(Constants.Constants.SYMBOLS)||o.symbols&&(r="Add symbols in unpredictable locations",a="Add symbols in unpredictable locations",n="Because only 1% of passwords use symbols, adding them unpredictably strengthens your password"):(i=[],l="",o.symbols&&i.push("symbols"),o.upperCase&&i.push("uppercase letters"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="42% of passwords contain only lowercase letters and number, making them easy for attackers to guess");else{var i=[],l="";o.symbols&&i.push("symbols"),o.digits&&i.push("digits"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="42% of passwords contain only letters, making them easy for attackers to guess"}else{var i=[],l="";o.symbols&&i.push("symbols"),o.digits&&i.push("digits"),o.upperCase&&i.push("uppercase letters"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="38% of passwords contain only lowercase letters, making them easy for attackers to guess"}return{count:s,reasonWhy:n,publicText:r,sensitiveText:a}},e.uppercasePredictable=function(e){var t=0,s="",r="",a="",n="",o="";if(e.charAt(0)===e.charAt(0).toUpperCase()&&e.charAt(0)!==e.charAt(0).toLowerCase()){var i=e.substr(1);if(i===i.toLowerCase()){t=1,s="Capitalize a letter in the middle",r="Capitalize a letter in the middle, rather than the first character",n=e.charAt(0).escapeHTML(),a="30% of people also capitalize only the first character";for(var l=new Array,c=0;c=97&&e.charCodeAt(c)<=122&&l.push(c);var h=Math.floor(Math.random()*l.length);o=e.substring(0,l[h]),o+=e.charAt(l[h]).toUpperCase(),o+=e.substring(l[h]+1)}}if(-1==e.search(/[a-z]/)){var u=e.replace(/[A-Z]/g,"");if(e.length>=u.length+3){t=1,s="Mix up your capitalization",r="Mix up your capitalization, rather than capitalizing everything",a="21% of passwords also contain only uppercase letters";var g=new Array;for(c=0;c=65&&e.charCodeAt(c)<=90&&g.push(c);var d=Math.floor(Math.random()*g.length);o=e.substring(0,g[d]),o+=e.charAt(g[d]).toLowerCase(),o+=e.substring(g[d]+1)}}return{score:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:o,problemText:n}},e.digitsPredictable=function(e){var t=0,s="",r="",a="",n="",o="",i=[],l=new RegExp("[^0-9]"),c=new RegExp("^[0-9]+[^0-9]+$"),h=new RegExp("^[^0-9]+[0-9]+$");if(e.length>=4&&!e.match(l)){t=1,s="Add more letters and symbols to your password",r="Add characters other than digits to your password",a=e.escapeHTML(),n="35% of people also use only digits";var u=58+Math.floor(68*Math.random()),g=Math.floor(1+Math.random()*(e.length-1));o=e.slice(0,g)+String.fromCharCode(u)+e.slice(g);for(var d=0;d=4&&e.match(c)){t=1,r="Consider inserting digits into the middle, not just at the beginning",s="Consider inserting digits into the middle",n="10% of people also put digits at the beginning of the password";for(var p=1;e.charCodeAt(p)>=48&&e.charCodeAt(p)<=57;)p++;for(a=e.slice(0,p).escapeHTML(),g=Math.floor(p+1+Math.random()*(e.length-p-1)),o=e.slice(p,g)+e.slice(0,p)+e.slice(g),d=0;d=4&&e.match(h)){t=1,r="Consider inserting digits into the middle, not just at the end",s="Consider inserting digits into the middle",n="38% of people also put digits at the end of the password";for(var m=e.length-2;e.charCodeAt(m)>=48&&e.charCodeAt(m)<=57;)m--;for(a=e.slice(m+1).escapeHTML(),g=Math.floor(1+Math.random()*(e.length-m-1)),o=e.slice(0,g)+e.slice(m+1)+e.slice(g,m+1),d=0;d=4&&e.match(l)){t=1,r="Move symbols and digits earlier, rather than just at the end",s="Move symbols and digits elsewhere in your password",a=e.match(h)[0].escapeHTML(),n="14% of people also use letters, followed by symbols, followed by digits";var u=e.search(h);a=e.slice(u).escapeHTML();var g=Math.floor(1+Math.random()*(u-1));o=e.slice(0,g)+e.slice(u)+e.slice(g,u);for(var d=0;d=4&&e.match(c)){for(t=1,r="Move your symbols earlier, rather than just at the end",s="Move symbols and digits elsewhere in your password",n="16% of people also put symbols only at the end of the password",u=e.search(h),a=e.slice(u).escapeHTML(),g=Math.floor(1+Math.random()*(u-1)),o=e.slice(0,g)+e.slice(u)+e.slice(g,u),d=0;d":[3,9],"/":[3,10],"?":[3,10]," ":[4,5]},s="",r=0;rl&&"0,0"!==h&&(i=c,l=r-c),c=r)}var u=l+1,g="",d="",p="",m="";return u>=4&&(g="Avoid using a pattern on your keyboard",d="Avoid using a pattern on your keyboard like "+(p=s.substring(i,i+l+1).escapeHTML())+"",m="Because keyboard patterns are very common in passwords, attackers know to guess them"),u<3&&(u=0),{score:u,reasonWhy:m,publicText:g,sensitiveText:d,problemText:p}},e.duplicatedCharacters=function(e){var t=e.split("").removeDuplicates(),s=e.length-t.length,r="",a="",n="",o="";if(t.length<=.5*e.length&&t.length<=5){o="",r="Have more variety in the characters you choose";var i="";t.length>1&&(i="s"),a="Have more variety than repeating the same "+t.length+" character"+i+" ("+Helper.Helper.boldAll(t.sort()).toHumanString()+")",n="Passwords that use only a few different characters are easy for attackers to guess"}return{count:s,reasonWhy:n,publicText:r,sensitiveText:a,problemText:o}},e.repeatedSections=function(e){for(var t=0,s="",r="",a="",n="",o=!1,i=(e=e.toLowerCase()).length,l=Math.floor(i/2);l>=3;l--){for(var c=0;c<=i-l;c++){for(var h=e.substring(c,c+l),u=h.split("").reverse().join(""),g=0;g+l<=c;g++)e.substring(g,g+l)===h?(t+=l,a=h.escapeHTML()):e.substring(g,g+l)===u&&(t+=l,a=h.escapeHTML(),o=!0);for(g=c+l;g+l<=i;g++)e.substring(g,g+l)===h?(t+=l,a=h.escapeHTML()):e.substring(g,g+l)===u&&(t+=l,a=h.escapeHTML(),o=!0);if(t>=3){t>=4?(s="Avoid repeating sections",r="Avoid repeating sections ("+a+")",n="In their guessing, attackers know to try duplicating parts of the password",o&&(s+=", forwards or backwards",r+=", forwards or backwards")):a="";break}}if(t>0)break}return{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.repeats=function(e){for(var t=e.length,s=1,r=1,a="",n="",o="",i="",l="",c=1;cs&&(s=r,a=e[c]):r=1;var h=s;if(s>=3){n="Don't repeat the same character many times in a row";for(var u=0;u"+(i=i.escapeHTML())+") many times in a row",l="Hitting the same key over and over adds little to your password's strength"}return 1===h&&(h=0),{count:h,reasonWhy:l,publicText:n,sensitiveText:o,problemText:i}},e.contextual=function(e,t){for(var s=0,r="",a="",n="",o="",i=e,l=0;l=5){s=u.length,r="Don't use your account information in your password",a="Don't use your account information ("+(n=u.escapeHTML())+") in your password",o="Attackers know to guess your username and email address as part of your password";var g=e.indexOf(u);g>-1&&(i=e.substr(0,g)+e.substr(g+u.length))}return{count:s,reasonWhy:o,publicText:r,sensitiveText:a,problemText:n,remaining:i}},e.commonSubstringCheck=function(e){var t=0,s="",r="",a="",n="",o=new Array;e=e.toLowerCase();for(var i=Constants.Constants.blacklistedSubstrings,l=0;l0){s="Avoid strings of characters commonly found in passwords",r="Avoid strings of characters commonly found in passwords like "+o.join(" and ")+"",n="Even if they don't make sense, these strings of characters show up in many passwords, which makes them bad to use in yours.",a=o[0].escapeHTML();for(var c=0;c as part of your own password",n=e[r].escapeHTML();return{length:e[r].length,reasonWhy:s,publicText:"Avoid using very common passwords as part of your own password",sensitiveText:a,problemText:n}}return{length:0,reasonWhy:s,publicText:"",sensitiveText:"",problemText:""}},e.blacklist=function(e){for(var t=PasswordMeter.PasswordMeter.instance.getConfig(),s=PasswordMeter.PasswordMeter.instance.getHelper(),r=t.ignoredWords,a="",n="",o="",i="",l=e,c=[],h=new RegExp("[^A-Za-z]"),u=(e=(e=e.toLowerCase()).replace(/[-_ ]/g,"")).split(/[^a-z01345@$]+/),g=(u=u.filter(function(e){return e})).listSubstringsMinMax(1,void 0),d=0;d-1&&(c.push(g[d]),p=g[d])}if(p.length>0){for(0==o.length&&(o=g[d].escapeHTML()),f=0;f-1){u.splice(f,1,u[f].substring(0,b),u[f].substring(b+p.length)),u=u.filter(function(e){return e});break}}g=u.listSubstringsMinMax(1,p.length),p="",d=0}else d++}var v=0;if(c.length>0){for(a="Don't use site-specific terms in your password",d=0;d-1&&(l=l.substr(0,y)+l.substr(y+c[d].length))}n="Don't use site-specific terms ("+Helper.Helper.boldAll(c.removeDuplicates()).toHumanString()+")",i="Attackers target their attacks to words used on a particular service"}return{length:v,reasonWhy:i,publicText:a,sensitiveText:n,problemText:o,remaining:l}},e.combinedDictCheck=function(e){for(var t="",s="",r="",a="",n=100,o=new Array,i=new Array,l=new Array,c=new Array,h=new Array,u=PasswordMeter.PasswordMeter.instance,g=u.getDictionaries(),d=u.getHelper(),p=new Array,m=new Array,f=(e=e.replace(/[-_ ]/g,"")).split(/[^A-Za-z012345!&@$]+/),w=(f=f.filter(function(e){return e})).listSubstringsMinMax(4,void 0),b=0;b0){for(0==r.length&&(r=w[b].escapeHTML()),A=0;A-1){f.splice(A,1,f[A].substring(0,T),f[A].substring(T+v.length)),f=f.filter(function(e){return e});break}}w=f.listSubstringsMinMax(4,v.length),v="",b=0}else b++}var k=new Array,S=new Array,L=0,P=0,E=function(e,t){if(e.length>0){k.push(t);for(var s=0;s0&&(a="Attackers use software that automatically guesses millions of words commonly found in dictionaries, wordlists, or other people's passwords",t="Don't use ",s="Don't use ",n<100&&(a+=", including simple transformations of those words/phrases where they substitute digits and symbols for letters"),t+=k.join(" or "),s+=S.join(" or ")),{length:L,reasonWhy:a,publicText:t,sensitiveText:s,problemText:r,dictionaryTokens:P,substitutionCommonness:n=100-n}},e.identifyDates=function(e){var t=0,s="",r="",a="",n="",o=[],i=PasswordMeter.PasswordMeter.instance.getHelper(),l=[e],c=function(e){var s=i.matchHelper(l,e);s.score>0&&(t+=s.score,o=o.concat(s.matched.toString()),l=s.revisedParts)},h="([ .-/])",u="((0\\d|1[012])|\\d)",g="(january|february|march|april|may|june|july|august|september|october|november|december)",d="([012]\\d|3[01])",p="(\\d\\d)",m="(19\\d\\d|20[01234]\\d)";return c(new RegExp(u+h+d+h+m,"g")),c(new RegExp(d+h+u+h+m,"g")),c(new RegExp(u+h+d+h+p,"g")),c(new RegExp(d+h+u+h+p,"g")),c(new RegExp(u+d+m,"g")),c(new RegExp(d+u+m,"g")),c(new RegExp(g+m,"ig")),c(new RegExp(g+p,"ig")),c(new RegExp(u+h+d,"g")),c(new RegExp(d+h+u,"g")),c(new RegExp(m,"g")),t>0&&(s="Avoid using dates",r="Avoid using dates like "+Helper.Helper.boldAll(o).toHumanString(),n="Dates and years in any format are quite common in passwords",a=o[0].escapeHTML()),{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.alphabeticSequenceCheck=function(e){var t=0,s="",r="",a="",n="",o=[],i=[];o[0]=e.charCodeAt(0);for(var l=1;lh&&0!==g&&(c=u,h=l-u),u=l),1===(t=h)&&(t=0),t>=2&&t++,t>=4){var d=e.substr(c,c+h+1);a=d.escapeHTML();var p=new RegExp("^[0-9]+$");d.match(p)?(s="Avoid numerical patterns",r="Avoid numerical patterns like "+a+""):(s="Avoid patterns from the alphabet",r="Avoid patterns from the alphabet like "+a+""),n="Attackers know to guess sequences following the alphabet, in addition to repeated characters or patterns on your keyboard"}}return{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.structurePredictable=function(e){var t="",s="",r="",a=0,n=(e=(e=(e=(e=e.replace(/[A-Z]/g,"U")).replace(/[a-z]/g,"L")).replace(/[0-9]/g,"D")).replace(/[^A-Za-z0-9]/g,"S"),Constants.Constants.commonStructures.indexOf(e));if(n>=0){a=2124-n,r="One technique attackers use is to try all possible passwords within common structures, or arrangements of character classes (e.g., where lowercase letters and digits are located)",s=(t="The way you structure your password is predictable")+" (";for(var o=!0,i=0;i1&&(s+="s"),i+=l}s+=")"}return{score:a,reasonWhy:r,publicText:t,sensitiveText:s}}}(RuleFunctions=exports.RuleFunctions||(exports.RuleFunctions={})); },{"./PasswordMeter":3,"./constants":6,"./helper":8,"./nn-misc":9}],11:[function(require,module,exports){ String.prototype.replaceAt=function(r,t){return this.substr(0,r)+t+this.substr(r+1)},String.prototype.listSubstringsNoFilter=function(r){for(var t=new Array,e=this.toLowerCase(),n=e.length,i=n;i>=r-1;i--)for(var o=0;i+o/g,">")},String.prototype.listSubstrings=function(r){for(var t,e=new Array,n=(t=(t=this.toLowerCase()).replace(/[^a-z]/g,"")).length,i=n;i>=r-1;i--)for(var o=0;i+o0?e*Constants.Constants.METER_STRINGENCY_SCALE_FACTOR:e},e.prototype.spawnRating=function(){var e="",t=PasswordMeter.PasswordMeter.instance.getNN();e=this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown?this.$("#pwboxModal").val():this.$("#pwbox").val();var s=this.$("#usernamebox").val(),i=0,o=t.getNeuralNetNum(e);void 0===o?(t.setNeuralNetNum(e,-1),t.queryGuessNumber(e,!1)):o>=0&&i++,void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!0):this.heuristicMapping[e]>=0&&i++,0!==e.length&&t.heardFromNn()&&2!==i||this.displayRating(e)},e.prototype.generateCandidateFixed=function(e,t,s){var i=[];if(void 0===this.deltaHighlighted[e])for(var o=0;o=65&&n.charCodeAt(r)<=90?(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)+32)),i[r]=1):n.charCodeAt(r)>=97&&n.charCodeAt(r)<=122&&(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)-32)),i[r]=1)}else if(2===h||3===h){var l=32+Math.floor(95*Math.random()),p=Math.floor(n.length*Math.random());n.charCodeAt(p)!==l&&(i[p]=1),n=n.replaceAt(p,String.fromCharCode(l))}else if(h>=4){l=32+Math.floor(95*Math.random()),p=Math.floor((n.length+1)*Math.random());n=n.slice(0,p)+String.fromCharCode(l)+n.slice(p),i=i.slice(0,p).concat(1,i.slice(p))}var d=PasswordMeter.PasswordMeter.instance.getNN();void 0===d.getNeuralNetNum(n)&&(d.setNeuralNetNum(n,-1),d.queryGuessNumber(n,!0));var u=this.$("#usernamebox").val();return RuleFunctions.RuleFunctions.verifyMinimumRequirements(n,u).compliant?(this.recommendedFixes[s]=n,this.deltaHighlighted[n]=i,this.verboseMode&&console.log("identified "+n+" as a potential fix for "+s),void 0===this.recommendedFixesTries[s]?this.recommendedFixesTries[s]=1:this.recommendedFixesTries[s]=this.recommendedFixesTries[s]+1,this.spawnFixedRating(n)):++t<8&&this.generateCandidateFixed(e,t,s),1},e.prototype.spawnFixedRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=this.$("#usernamebox").val();void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!1):t.getNeuralNetNum(e)>=0&&this.heuristicMapping[e]>=0&&this.synthesizeFixed(e)},e.prototype.synthesizeFixed=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0,o=!1;void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(i++,s=this.heuristicMapping[e]);var n=t.getNeuralNetNum(e),h=this.scaleGuessNumByMeterStringencyFactor(n);if(void 0!==n&&h>=0&&isFinite(h)&&(i++,(0===s||s>0&&h=67){for(var a in this.verboseMode&&console.log(e+" is a plausible fix above the 2/3rds threshold"),this.recommendedFixes)if(this.recommendedFixes[a]===e&&void 0===this.fixedpwMapping[a]){var r=0;void 0!==this.heuristicMapping[a]&&this.heuristicMapping[a]>=0&&(r=this.heuristicMapping[a]);var l=t.getNeuralNetNum(a),p=this.scaleGuessNumByMeterStringencyFactor(l);void 0!==l&&p>=0&&isFinite(p)&&(0===r||r>0&&pr+15?(this.fixedpwMapping[a]=e,this.verboseMode&&console.log("mapping "+a+" to "+e),o=!0):this.verboseMode&&console.log("not mapping "+a+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s)}return o&&this.spawnRating(),1}var d=this.$("#pwbox").val();return this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown&&(d=this.$("#pwboxModal").val()),this.recommendedFixes[d]===e&&2===i&&void 0===this.fixedpwMapping[d]&&void 0!==this.recommendedFixesTries[d]&&this.recommendedFixesTries[d]<8&&(this.verboseMode&&console.log("trying again on "+e+" as current password is "+d),this.generateCandidateFixed(e,0,d)),1},e.prototype.redundant=function(e,t){e=e.toLowerCase();for(var s=0;s0&&e.length>0&&(t[s].indexOf(e)>=0&&e.length>=.7*t[s].length||e.indexOf(t[s])>=0&&t[s].length>=.7*e.length))return!0;return!1},e.prototype.queryHeuristicGuessNumber=function(e,t,s){var i=e,o=[],n=[],h=[],a=[],r=RuleFunctions.RuleFunctions.contextual(e,[t]);void 0===(e=r.remaining)&&(e="");var l=RuleFunctions.RuleFunctions.blacklist(e);void 0===(e=l.remaining)&&(e="");for(var p=RuleFunctions.RuleFunctions.pwLength(e),d=RuleFunctions.RuleFunctions.characterClasses(e),u=RuleFunctions.RuleFunctions.duplicatedCharacters(e),c=RuleFunctions.RuleFunctions.repeats(e),m=RuleFunctions.RuleFunctions.keyboardPatterns(e),g=RuleFunctions.RuleFunctions.repeatedSections(e),x=RuleFunctions.RuleFunctions.structurePredictable(e),b=RuleFunctions.RuleFunctions.uppercasePredictable(e),w=RuleFunctions.RuleFunctions.digitsPredictable(e),$=RuleFunctions.RuleFunctions.symbolsPredictable(e),v=RuleFunctions.RuleFunctions.countUC(e),M=RuleFunctions.RuleFunctions.countLC(e),y=RuleFunctions.RuleFunctions.countDIGS(e),f=RuleFunctions.RuleFunctions.countSYMS(e),T=RuleFunctions.RuleFunctions.identifyDates(e),R=(RuleFunctions.RuleFunctions.verifyMinimumRequirements(e,t),RuleFunctions.RuleFunctions.alphabeticSequenceCheck(e)),F=RuleFunctions.RuleFunctions.commonSubstringCheck(e),C=RuleFunctions.RuleFunctions.combinedDictCheck(e),N=e.listSubstringsNoFilter(4),k=RuleFunctions.RuleFunctions.commonPwCheck(N),W=[1.53,.3129,.9912,.04637,-.03885,-.1172,-.2976,-8581e-7,-.3008,-.5566,0,.9108,.7369,.7578,0,-.1213,-.2402,-.1364,-.5534,1.927,.001496,-.3946],P=[1,p.length,d.count,u.count,c.count,m.score,g.count,x.score,b.score,w.score,$.score,v.count,M.count,y.count,f.count,T.count,R.count,F.count,C.length,C.dictionaryTokens,C.substitutionCommonness,k.length],H=W[0],S=1;S100&&(H=100),r.publicText.length>0&&(o.push(r.publicText),n.push(r.sensitiveText),h.push(r.reasonWhy),a.push(r.problemText)),l.publicText.length>0&&(o.push(l.publicText),n.push(l.sensitiveText),h.push(l.reasonWhy),a.push(l.problemText)),C.publicText.length>0&&!this.redundant(C.problemText,a)&&(o.push(C.publicText),n.push(C.sensitiveText),h.push(C.reasonWhy),a.push(C.problemText)),m.publicText.length>0&&(o.push(m.publicText),n.push(m.sensitiveText),h.push(m.reasonWhy),a.push(m.problemText)),c.publicText.length>0&&(o.push(c.publicText),n.push(c.sensitiveText),h.push(c.reasonWhy),a.push(c.problemText)),T.publicText.length>0&&(o.push(T.publicText),n.push(T.sensitiveText),h.push(T.reasonWhy),a.push(T.problemText)),g.publicText.length>0&&(o.push(g.publicText),n.push(g.sensitiveText),h.push(g.reasonWhy),a.push(g.problemText)),R.publicText.length>0&&(o.push(R.publicText),n.push(R.sensitiveText),h.push(R.reasonWhy),a.push(R.problemText)),k.publicText.length>0&&!this.redundant(k.problemText,a)&&(o.push(k.publicText),n.push(k.sensitiveText),h.push(k.reasonWhy),a.push(k.problemText)),b.publicText.length>0&&(o.push(b.publicText),n.push(b.sensitiveText),h.push(b.reasonWhy),a.push(b.problemText)),w.publicText.length>0&&(o.push(w.publicText),n.push(w.sensitiveText),h.push(w.reasonWhy),a.push(w.problemText)),$.publicText.length>0&&(o.push($.publicText),n.push($.sensitiveText),h.push($.reasonWhy),a.push($.problemText)),u.publicText.length>0&&(o.push(u.publicText),n.push(u.sensitiveText),h.push(u.reasonWhy),a.push(u.problemText)),p.publicText.length>0&&(o.push(p.publicText),n.push(p.sensitiveText),h.push(p.reasonWhy)),f.publicText.length>0&&(o.push(f.publicText),n.push(f.sensitiveText),h.push(f.reasonWhy)),v.publicText.length>0&&(o.push(v.publicText),n.push(v.sensitiveText),h.push(v.reasonWhy)),y.publicText.length>0&&(o.push(y.publicText),n.push(y.sensitiveText),h.push(y.reasonWhy)),M.publicText.length>0&&(o.push(M.publicText),n.push(M.sensitiveText),h.push(M.reasonWhy)),F.publicText.length>0&&!this.redundant(F.problemText,a)&&(o.push(F.publicText),n.push(F.sensitiveText),h.push(F.reasonWhy)),x.publicText.length>0&&(o.push(x.publicText),n.push(x.sensitiveText),h.push(x.reasonWhy)),this.heuristicMapping[i]=H,this.feedbackMapping[i]=JSON.stringify({publictips1:o[0],publictips2:o[1],publictips3:o[2],sensitivetips1:n[0],sensitivetips2:n[1],sensitivetips3:n[2],reasonWhy1:h[0],reasonWhy2:h[1],reasonWhy3:h[2]}),s?(this.displayRating(i),w.fixedPw.length>0?(this.previousCandidate[i]=w.fixedPw,this.deltaHighlighted[w.fixedPw]=w.deltas):$.fixedPw.length>0&&(this.previousCandidate[i]=$.fixedPw,this.deltaHighlighted[$.fixedPw]=$.deltas)):this.synthesizeFixed(i)},e.prototype.displayRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0;if(e.length>0){void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(s=this.heuristicMapping[e],i++);var o=t.getNeuralNetNum(e),n=this.scaleGuessNumByMeterStringencyFactor(o);void 0!==o&&n>=0&&isFinite(n)&&(i++,(0==s||s>0&&n(Why?)"),p+="

 

To make it even better:",this.$("#feedbackHeaderText").html(p),this.$("#feedbackHeaderTextModal").html(p)}else{var d="Your password appears strong.";a.remindAgainstReuse&&(d+=" Make sure you use it only for this account. (Why?)"),this.$("#feedbackHeaderText").html(d),this.$("#feedbackHeaderTextModal").html(d)}if(this.$(".nonmodalColorCell").show(),this.$(".modalColorCell").show(),this.$(".modalColorCellSpacer").show(),this.$(".recommended").show(),!0===this.$("#showHidePWNonModal").prop("checked")?(this.$(".fixedPWavailablePortal").hide(),this.$(".concreteSuggestionDiv").show(),this.$("#tipText1").html(h.sensitivetips1),this.$("#tipText2").html(h.sensitivetips2),this.$("#tipText3").html(h.sensitivetips3),this.$("#suggestion1").html(h.sensitivetips1),this.$("#suggestion2").html(h.sensitivetips2),this.$("#suggestion3").html(h.sensitivetips3),this.$("#sensText1").html(h.reasonWhy1),this.$("#sensText2").html(h.reasonWhy2),this.$("#sensText3").html(h.reasonWhy3)):(this.$(".fixedPWavailablePortal").show(),this.$(".concreteSuggestionDiv").hide(),this.$("#tipText1").html(h.publictips1),this.$("#tipText2").html(h.publictips2),this.$("#tipText3").html(h.publictips3),this.$("#suggestion1").html(h.publictips1),this.$("#suggestion2").html(h.publictips2),this.$("#suggestion3").html(h.publictips3),this.$("#sensText1").html(h.reasonWhy1),this.$("#sensText2").html(h.reasonWhy2),this.$("#sensText3").html(h.reasonWhy3)),void 0!==this.fixedpwMapping[e]){for(var u="",c=this.deltaHighlighted[this.fixedpwMapping[e]],m=this.fixedpwMapping[e],g=0;g"+m[g].escapeHTML()+"
":u+=m[g].escapeHTML();this.$(".fixedPW").html(u)}else this.$(".recommended").hide();s<=66?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show()):s<100?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show(),this.tookSuggestion&&(this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())):(this.$("#nonmodalFeedbackTable").hide(),this.$("#modalFeedbackTable").hide(),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())}else{this.inCompliance=!1,0!==e.length&&t.heardFromNn()&&2!==i||this.displayBar(s,!1),this.$("#confirmpw").hide(),this.$(".detailedFeedback").hide(),this.$(".portalToGenericAdviceModal").show(),this.$(".explainWhy").hide();var x="";(a=PasswordMeter.PasswordMeter.instance.getConfig()).remindAgainstReuse&&(x="Don't reuse a password from another account! (Why?)

 

");var b="Your password must:";this.$("#feedbackHeaderText").html(x+b),this.$("#feedbackHeaderTextModal").html(x+b),this.$("#nonmodalFeedbackTable").show(),this.$(".recommended").hide();var w=[],$=l.detail;for(var v in $.compliance)$.compliance[v]||w.push($.explanation[v]);this.$(".nonmodalColorCell").hide(),this.$(".modalColorCell").hide(),this.$(".modalColorCellSpacer").hide(),this.$(".nonmodalRow").hide(),this.$(".modalRow").hide();for(var M=0;M100&&(e=100);var s=e/100,i="rgb(160,160,160)";t&&s<.45?i="rgb("+Math.round(255)+","+Math.round(s/.45*140)+",0)":t&&s>=.45&&s<.65?i="rgb("+Math.round(255)+","+Math.round((s-.45)/.2*75+140)+",0)":t&&(i="rgb("+Math.round(255-(s-.65)/.35*205)+","+Math.round(215-(s-.65)/.035)+",0)"),this.$("#cups-passwordmeter-span").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span").css("background-color",i),this.$("#cups-passwordmeter-span-modal").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span-modal").css("background-color",i)},e.prototype.getMaxOfArray=function(e){return Math.max.apply(null,e)},e.prototype.expandHelpBut=function(){this.$("#expandHelpDiv").show(),this.$("#helpButton").hide()},e.prototype.modalShowCheck=function(){"text"==this.$("#pwbox").prop("type")?(this.$("#myModal").show(),this.storepw()):this.$("#expandHelpDiv").is(":visible")?(this.$("#myModal").show(),this.storepw()):this.expandHelpBut()},e.prototype.closeDiv=function(e){this.$(e).hide()},e.prototype.deselect=function(e){null==this.$.fn.slideFadeToggle&&(this.$.fn.slideFadeToggle=function(e,t){return this.animate({opacity:"toggle",height:"toggle"},"fast",e,t)}),this.$(".pop").slideFadeToggle(function(){e.removeClass("selected")})},e}();e.UIMisc=o,t=PasswordMeter.PasswordMeter.instance,s=t.getJquery(),i=new o(!1),t.setUI(i),s(document).ready(function(){s("#showpassword").prop("checked",!1),s("#showpassword").click(function(){document.getElementById("hide-show-label").textContent="Hide Password",s("#cbbutton").css("background-color","#f5f5f5"),"password"==s("#pwbox").prop("type")?s("#pwbox").prop("type","text"):(s("#pwbox").prop("type","password"),document.getElementById("hide-show-label").textContent="Show Password",s("#cbbutton").css("background-color","#f5f5f5"))})}),s(document).ready(function(){var e=s("#pwboxModal");s("#tip1, #sensText1").mouseover(function(){e.addClass("problemColor")}),s("#tip2, #sensText2").mouseover(function(){e.addClass("problemColor")}),s("#tip3, #sensText3").mouseover(function(){e.addClass("problemColor")})}),s(document).ready(function(){i.onReady()})}(UIMisc=exports.UIMisc||(exports.UIMisc={})); +"use strict";exports.__esModule=!0;var UIMisc,PasswordMeter=require("./PasswordMeter"),RuleFunctions=require("./rulefunctions"),Constants=require("./constants");!function(e){var t,s,i,o=function(){function e(e){this.pwWhenModalOpened="",this.tookSuggestion=!1,this.previouslyRated="",this.heuristicMapping={},this.feedbackMapping={},this.recommendedFixes={},this.recommendedFixesTries={},this.previousCandidate={},this.fixedpwMapping={},this.deltaHighlighted={},this.inCompliance=!1,this.randomlyOrderedCharClasses=[];var t=PasswordMeter.PasswordMeter.instance;this.helper=t.getHelper(),this.$=t.getJquery(),this.verboseMode=e;this.randomlyOrderedCharClasses=function(e){for(var t,s,i=e.length;0!==i;)s=Math.floor(Math.random()*i),t=e[i-=1],e[i]=e[s],e[s]=t;return e}(["uppercase letter","lowercase letter","digit","symbol"]),console.log("randomized class ordering: "+this.randomlyOrderedCharClasses.toString())}return e.prototype.getCharClassStringForCharClassCountReq=function(){return this.randomlyOrderedCharClasses.map(function(e){return e+"s"}).join("; ")},e.prototype.getCharClassStringForMandatoryCharClassReq=function(){for(var e=PasswordMeter.PasswordMeter.instance.getConfig(),t="",s=0;s0?t+=" and an uppercase letter":t="Contain an uppercase letter");break;case"lowercase letter":e.classRequire.lowerCase&&(t.length>0?t+=" and a lowercase letter":t="Contain a lowercase letter");break;case"digit":e.classRequire.digits&&(t.length>0?t+=" and a digit":t="Contain a digit");break;case"symbol":e.classRequire.symbols&&(t.length>0?t+=" and a symbol":t="Contain a symbol")}}return t},e.prototype.onReady=function(){this.$(".pop").fadeIn(),this.$("#showHidePWNonModal").prop("checked",!1),this.toggleShowHideNonModal(),this.spawnRating()},e.prototype.toggleShowHideNonModal=function(){this.$("#showHidePWNonModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWModal").prop("checked",!1)),this.spawnRating()},e.prototype.toggleShowHideModal=function(){this.$("#showHidePWModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWNonModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWNonModal").prop("checked",!1)),this.spawnRating()},e.prototype.storepw=function(){var e=this.$("#pwbox").val();this.pwWhenModalOpened=e,this.$("#pwboxModal").val(e)},e.prototype.enableDiscard=function(){this.$("#pwboxModal").val()===this.pwWhenModalOpened?(this.$("#discardButton").hide(),this.$("#keepButton").html("OK")):(this.$("#discardButton").show(),this.$("#keepButton").html("Keep Changes"))},e.prototype.keeppw=function(){this.$("#pwbox").val(this.$("#pwboxModal").val())},e.prototype.discardpw=function(){this.$("#pwbox").val(this.pwWhenModalOpened)},e.prototype.fixPWNonModal=function(){this.tookSuggestion=!0;var e=this.$("#nonmodalFixedPW").text();this.$("#pwbox").val(e),this.spawnRating()},e.prototype.fixPWModal=function(){this.tookSuggestion=!0;var e=this.$("#modalFixedPW").text();this.$("#pwboxModal").val(e),this.spawnRating(),this.enableDiscard()},e.prototype.showModal=function(){this.storepw(),this.$("#discardButton").hide(),this.$("#keepButton").html("OK"),this.$("#myModal").modal("show")},e.prototype.mayberate=function(){this.$("#pwbox").val()!==this.previouslyRated&&(this.previouslyRated=this.$("#pwbox").val(),this.spawnRating())},e.prototype.continueCheck=function(e){var t=!0;e&&(this.$("#usernamebox").val().length<1?(this.$("#usernameTooShort").show(),t=!1):this.$("#usernameTooShort").hide());this.inCompliance?(this.$("#feedbackHeaderText").css({color:"","font-weight":""}),this.$("#passwordNonCompliant").hide()):(t=!1,this.$("#confirmDoesNotMatch").hide(),e&&(this.$("#feedbackHeaderText").css({color:"red","font-weight":"bold"}),this.$("#passwordNonCompliant").show())),this.$("#pwbox").val()!==this.$("#confirmbox").val()?(t=!1,e&&this.inCompliance&&this.$("#confirmDoesNotMatch").show()):this.$("#confirmDoesNotMatch").hide(),e&&t&&alert("this would be submitted")},e.prototype.scaleGuessNumByMeterStringencyFactor=function(e){return e>0?e*Constants.Constants.METER_STRINGENCY_SCALE_FACTOR:e},e.prototype.spawnRating=function(){var e="",t=PasswordMeter.PasswordMeter.instance.getNN();e=this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown?this.$("#pwboxModal").val():this.$("#pwbox").val();var s=this.$("#usernamebox").val(),i=0,o=t.getNeuralNetNum(e);void 0===o?(t.setNeuralNetNum(e,-1),t.queryGuessNumber(e,!1)):o>=0&&i++,void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!0):this.heuristicMapping[e]>=0&&i++,0!==e.length&&t.heardFromNn()&&2!==i||this.displayRating(e)},e.prototype.generateCandidateFixed=function(e,t,s){if(!PasswordMeter.PasswordMeter.instance.getConfig().provideConcretePasswordSuggestions)return 1;var i=[];if(void 0===this.deltaHighlighted[e])for(var o=0;o=65&&n.charCodeAt(r)<=90?(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)+32)),i[r]=1):n.charCodeAt(r)>=97&&n.charCodeAt(r)<=122&&(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)-32)),i[r]=1)}else if(2===a||3===a){var l=32+Math.floor(95*Math.random()),d=Math.floor(n.length*Math.random());n.charCodeAt(d)!==l&&(i[d]=1),n=n.replaceAt(d,String.fromCharCode(l))}else if(a>=4){l=32+Math.floor(95*Math.random()),d=Math.floor((n.length+1)*Math.random());n=n.slice(0,d)+String.fromCharCode(l)+n.slice(d),i=i.slice(0,d).concat(1,i.slice(d))}var p=PasswordMeter.PasswordMeter.instance.getNN();void 0===p.getNeuralNetNum(n)&&(p.setNeuralNetNum(n,-1),p.queryGuessNumber(n,!0));var u=this.$("#usernamebox").val();return void 0===this.heuristicMapping[n]&&this.queryHeuristicGuessNumber(n,u,!1),RuleFunctions.RuleFunctions.verifyMinimumRequirements(n,u).compliant?(this.recommendedFixes[s]=n,this.deltaHighlighted[n]=i,this.verboseMode&&console.log("identified "+n+" as a potential fix for "+s),void 0===this.recommendedFixesTries[s]?this.recommendedFixesTries[s]=1:this.recommendedFixesTries[s]=this.recommendedFixesTries[s]+1,this.spawnFixedRating(n)):++t<8&&this.generateCandidateFixed(e,t,s),1},e.prototype.spawnFixedRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=this.$("#usernamebox").val();void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!1):t.getNeuralNetNum(e)>=0&&this.heuristicMapping[e]>=0&&this.synthesizeFixed(e)},e.prototype.synthesizeFixed=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0,o=!1;void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(i++,s=this.heuristicMapping[e]);var n=t.getNeuralNetNum(e),a=this.scaleGuessNumByMeterStringencyFactor(n);if(void 0!==n&&a>=0&&isFinite(a)&&(i++,(0===s||s>0&&a=67){for(var h in this.verboseMode&&console.log(e+" is a plausible fix above the 2/3rds threshold"),this.recommendedFixes)if(this.recommendedFixes[h]===e&&void 0===this.fixedpwMapping[h]){var r=0;void 0!==this.heuristicMapping[h]&&this.heuristicMapping[h]>=0&&(r=this.heuristicMapping[h]);var l=t.getNeuralNetNum(h),d=this.scaleGuessNumByMeterStringencyFactor(l);void 0!==l&&d>=0&&isFinite(d)&&(0===r||r>0&&dr+15?(this.fixedpwMapping[h]=e,console.log("mapping "+h+" to "+e),this.verboseMode&&console.log("mapping "+h+" to "+e),o=!0):(console.log("not mapping "+h+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s),this.verboseMode&&console.log("not mapping "+h+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s))}return o&&this.spawnRating(),1}var p=this.$("#pwbox").val();return this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown&&(p=this.$("#pwboxModal").val()),this.recommendedFixes[p]===e&&2===i&&void 0===this.fixedpwMapping[p]&&void 0!==this.recommendedFixesTries[p]&&this.recommendedFixesTries[p]<8&&(this.verboseMode&&console.log("trying again on "+e+" as current password is "+p),console.log("trying again on "+e+" as current password is "+p),this.generateCandidateFixed(e,0,p)),1},e.prototype.redundant=function(e,t){e=e.toLowerCase();for(var s=0;s0&&e.length>0&&(t[s].indexOf(e)>=0&&e.length>=.7*t[s].length||e.indexOf(t[s])>=0&&t[s].length>=.7*e.length))return!0;return!1},e.prototype.queryHeuristicGuessNumber=function(e,t,s){var i=e,o=[],n=[],a=[],h=[],r=RuleFunctions.RuleFunctions.contextual(e,[t]);void 0===(e=r.remaining)&&(e="");var l=RuleFunctions.RuleFunctions.blacklist(e);void 0===(e=l.remaining)&&(e="");for(var d=RuleFunctions.RuleFunctions.pwLength(e),p=RuleFunctions.RuleFunctions.characterClasses(e),u=RuleFunctions.RuleFunctions.duplicatedCharacters(e),c=RuleFunctions.RuleFunctions.repeats(e),m=RuleFunctions.RuleFunctions.keyboardPatterns(e),g=RuleFunctions.RuleFunctions.repeatedSections(e),w=RuleFunctions.RuleFunctions.structurePredictable(e),b=RuleFunctions.RuleFunctions.uppercasePredictable(e),x=RuleFunctions.RuleFunctions.digitsPredictable(e),y=RuleFunctions.RuleFunctions.symbolsPredictable(e),$=RuleFunctions.RuleFunctions.countUC(e),v=RuleFunctions.RuleFunctions.countLC(e),M=RuleFunctions.RuleFunctions.countDIGS(e),f=RuleFunctions.RuleFunctions.countSYMS(e),T=RuleFunctions.RuleFunctions.identifyDates(e),R=(RuleFunctions.RuleFunctions.verifyMinimumRequirements(e,t),RuleFunctions.RuleFunctions.alphabeticSequenceCheck(e)),C=RuleFunctions.RuleFunctions.commonSubstringCheck(e),F=RuleFunctions.RuleFunctions.combinedDictCheck(e),N=e.listSubstringsNoFilter(4),k=RuleFunctions.RuleFunctions.commonPwCheck(N),W=[1.53,.3129,.9912,.04637,-.03885,-.1172,-.2976,-8581e-7,-.3008,-.5566,0,.9108,.7369,.7578,0,-.1213,-.2402,-.1364,-.5534,1.927,.001496,-.3946],P=[1,d.length,p.count,u.count,c.count,m.score,g.count,w.score,b.score,x.score,y.score,$.count,v.count,M.count,f.count,T.count,R.count,C.count,F.length,F.dictionaryTokens,F.substitutionCommonness,k.length],S=W[0],H=1;H100&&(S=100),r.publicText.length>0&&(o.push(r.publicText),n.push(r.sensitiveText),a.push(r.reasonWhy),h.push(r.problemText)),l.publicText.length>0&&(o.push(l.publicText),n.push(l.sensitiveText),a.push(l.reasonWhy),h.push(l.problemText)),F.publicText.length>0&&!this.redundant(F.problemText,h)&&(o.push(F.publicText),n.push(F.sensitiveText),a.push(F.reasonWhy),h.push(F.problemText)),m.publicText.length>0&&(o.push(m.publicText),n.push(m.sensitiveText),a.push(m.reasonWhy),h.push(m.problemText)),c.publicText.length>0&&(o.push(c.publicText),n.push(c.sensitiveText),a.push(c.reasonWhy),h.push(c.problemText)),T.publicText.length>0&&(o.push(T.publicText),n.push(T.sensitiveText),a.push(T.reasonWhy),h.push(T.problemText)),g.publicText.length>0&&(o.push(g.publicText),n.push(g.sensitiveText),a.push(g.reasonWhy),h.push(g.problemText)),R.publicText.length>0&&(o.push(R.publicText),n.push(R.sensitiveText),a.push(R.reasonWhy),h.push(R.problemText)),k.publicText.length>0&&!this.redundant(k.problemText,h)&&(o.push(k.publicText),n.push(k.sensitiveText),a.push(k.reasonWhy),h.push(k.problemText)),b.publicText.length>0&&(o.push(b.publicText),n.push(b.sensitiveText),a.push(b.reasonWhy),h.push(b.problemText)),x.publicText.length>0&&(o.push(x.publicText),n.push(x.sensitiveText),a.push(x.reasonWhy),h.push(x.problemText)),y.publicText.length>0&&(o.push(y.publicText),n.push(y.sensitiveText),a.push(y.reasonWhy),h.push(y.problemText)),u.publicText.length>0&&(o.push(u.publicText),n.push(u.sensitiveText),a.push(u.reasonWhy),h.push(u.problemText)),d.publicText.length>0&&(o.push(d.publicText),n.push(d.sensitiveText),a.push(d.reasonWhy)),f.publicText.length>0&&(o.push(f.publicText),n.push(f.sensitiveText),a.push(f.reasonWhy)),$.publicText.length>0&&(o.push($.publicText),n.push($.sensitiveText),a.push($.reasonWhy)),M.publicText.length>0&&(o.push(M.publicText),n.push(M.sensitiveText),a.push(M.reasonWhy)),v.publicText.length>0&&(o.push(v.publicText),n.push(v.sensitiveText),a.push(v.reasonWhy)),C.publicText.length>0&&!this.redundant(C.problemText,h)&&(o.push(C.publicText),n.push(C.sensitiveText),a.push(C.reasonWhy)),w.publicText.length>0&&(o.push(w.publicText),n.push(w.sensitiveText),a.push(w.reasonWhy)),this.heuristicMapping[i]=S,this.feedbackMapping[i]=JSON.stringify({publictips1:o[0],publictips2:o[1],publictips3:o[2],sensitivetips1:n[0],sensitivetips2:n[1],sensitivetips3:n[2],reasonWhy1:a[0],reasonWhy2:a[1],reasonWhy3:a[2]}),s?(this.displayRating(i),x.fixedPw.length>0?(this.previousCandidate[i]=x.fixedPw,this.deltaHighlighted[x.fixedPw]=x.deltas):y.fixedPw.length>0&&(this.previousCandidate[i]=y.fixedPw,this.deltaHighlighted[y.fixedPw]=y.deltas)):this.synthesizeFixed(i)},e.prototype.displayRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0;if(e.length>0){void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(s=this.heuristicMapping[e],i++);var o=t.getNeuralNetNum(e),n=this.scaleGuessNumByMeterStringencyFactor(o);void 0!==o&&n>=0&&isFinite(n)&&(i++,(0==s||s>0&&n(Why?)
"),d+="

 

To make it even better:",this.$("#feedbackHeaderText").html(d),this.$("#feedbackHeaderTextModal").html(d)}else{var p="Your password appears strong.";h.remindAgainstReuse&&(p+=" Make sure you use it only for this account. (Why?)"),this.$("#feedbackHeaderText").html(p),this.$("#feedbackHeaderTextModal").html(p)}if(this.$(".nonmodalColorCell").show(),this.$(".modalColorCell").show(),this.$(".modalColorCellSpacer").show(),this.$(".recommended").show(),!0===this.$("#showHidePWNonModal").prop("checked")?(this.$(".fixedPWavailablePortal").hide(),this.$(".concreteSuggestionDiv").show(),this.$("#tipText1").html(a.sensitivetips1),this.$("#tipText2").html(a.sensitivetips2),this.$("#tipText3").html(a.sensitivetips3),this.$("#suggestion1").html(a.sensitivetips1),this.$("#suggestion2").html(a.sensitivetips2),this.$("#suggestion3").html(a.sensitivetips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)):(this.$(".fixedPWavailablePortal").show(),this.$(".concreteSuggestionDiv").hide(),this.$("#tipText1").html(a.publictips1),this.$("#tipText2").html(a.publictips2),this.$("#tipText3").html(a.publictips3),this.$("#suggestion1").html(a.publictips1),this.$("#suggestion2").html(a.publictips2),this.$("#suggestion3").html(a.publictips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)),h.provideConcretePasswordSuggestions&&void 0!==this.fixedpwMapping[e]){for(var u="",c=this.deltaHighlighted[this.fixedpwMapping[e]],m=this.fixedpwMapping[e],g=0;g"+m[g].escapeHTML()+"
":u+=m[g].escapeHTML();this.$(".fixedPW").html(u)}else this.$(".recommended").hide();s<=66?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show()):s<100?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show(),this.tookSuggestion&&(console.log("already took suggestion for "+e+" so hiding recs"),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())):(console.log("overall score is above 66 so for "+e+" so hiding recs"),this.$("#nonmodalFeedbackTable").hide(),this.$("#modalFeedbackTable").hide(),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())}else{this.inCompliance=!1,0!==e.length&&t.heardFromNn()&&2!==i||this.displayBar(s,!1),this.$("#confirmpw").hide(),this.$(".detailedFeedback").hide(),this.$(".portalToGenericAdviceModal").show(),this.$(".explainWhy").hide();var w="";(h=PasswordMeter.PasswordMeter.instance.getConfig()).remindAgainstReuse&&(w="Don't reuse a password from another account! (Why?)

 

");var b="Your password must:";this.$("#feedbackHeaderText").html(w+b),this.$("#feedbackHeaderTextModal").html(w+b),this.$("#nonmodalFeedbackTable").show(),this.$(".recommended").hide();var x=[],y=l.detail;for(var $ in y.compliance)y.compliance[$]||x.push(y.explanation[$]);this.$(".nonmodalColorCell").hide(),this.$(".modalColorCell").hide(),this.$(".modalColorCellSpacer").hide(),this.$(".nonmodalRow").hide(),this.$(".modalRow").hide();for(var v=0;v100&&(e=100);var s=e/100,i="rgb(160,160,160)";t&&s<.45?i="rgb("+Math.round(255)+","+Math.round(s/.45*140)+",0)":t&&s>=.45&&s<.65?i="rgb("+Math.round(255)+","+Math.round((s-.45)/.2*75+140)+",0)":t&&(i="rgb("+Math.round(255-(s-.65)/.35*205)+","+Math.round(215-(s-.65)/.035)+",0)"),this.$("#cups-passwordmeter-span").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span").css("background-color",i),this.$("#cups-passwordmeter-span-modal").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span-modal").css("background-color",i)},e.prototype.getMaxOfArray=function(e){return Math.max.apply(null,e)},e.prototype.expandHelpBut=function(){this.$("#expandHelpDiv").show(),this.$("#helpButton").hide()},e.prototype.modalShowCheck=function(){"text"==this.$("#pwbox").prop("type")?(this.$("#myModal").show(),this.storepw()):this.$("#expandHelpDiv").is(":visible")?(this.$("#myModal").show(),this.storepw()):this.expandHelpBut()},e.prototype.closeDiv=function(e){this.$(e).hide()},e.prototype.deselect=function(e){null==this.$.fn.slideFadeToggle&&(this.$.fn.slideFadeToggle=function(e,t){return this.animate({opacity:"toggle",height:"toggle"},"fast",e,t)}),this.$(".pop").slideFadeToggle(function(){e.removeClass("selected")})},e}();e.UIMisc=o,t=PasswordMeter.PasswordMeter.instance,s=t.getJquery(),i=new o(!1),t.setUI(i),s(document).ready(function(){s("#showpassword").prop("checked",!1),s("#showpassword").click(function(){document.getElementById("hide-show-label").textContent="Hide Password",s("#cbbutton").css("background-color","#f5f5f5"),"password"==s("#pwbox").prop("type")?s("#pwbox").prop("type","text"):(s("#pwbox").prop("type","password"),document.getElementById("hide-show-label").textContent="Show Password",s("#cbbutton").css("background-color","#f5f5f5"))})}),s(document).ready(function(){var e=s("#pwboxModal");s("#tip1, #sensText1").mouseover(function(){e.addClass("problemColor")}),s("#tip2, #sensText2").mouseover(function(){e.addClass("problemColor")}),s("#tip3, #sensText3").mouseover(function(){e.addClass("problemColor")})}),s(document).ready(function(){i.onReady()})}(UIMisc=exports.UIMisc||(exports.UIMisc={})); },{"./PasswordMeter":3,"./constants":6,"./rulefunctions":10}]},{},[3,4,5,6,7,8,9,10,11,12]); diff --git a/src/ts/config.ts b/src/ts/config.ts index 379a6b6..5609b30 100644 --- a/src/ts/config.ts +++ b/src/ts/config.ts @@ -81,6 +81,8 @@ export module Config { } export interface Config { + provideConcretePasswordSuggestions: boolean; + randomizeOrderCharClassRequirement: boolean; colors: ConfigColor; symbols: ConfigSymbols; remindAgainstReuse: boolean; @@ -102,6 +104,8 @@ export module Config { } export var passwordMeterDefaultConfig: Config = { + provideConcretePasswordSuggestions: true, + randomizeOrderCharClassRequirement: true, colors: { // display colors compliant: "#006600", // by default show completed requirement in green noncompliant: "#660000", // by default show outstanding requirement in red diff --git a/src/ts/rulefunctions.ts b/src/ts/rulefunctions.ts index c500004..18ce3ba 100644 --- a/src/ts/rulefunctions.ts +++ b/src/ts/rulefunctions.ts @@ -97,7 +97,13 @@ export module RuleFunctions { } else { thisExplanation = "Use " + minCharacterClasses.toString() + "-" + maxCharacterClasses.toString() + " of the following: "; } - thisExplanation += "uppercase letters; lowercase letters; digits; symbols"; + + if (config.randomizeOrderCharClassRequirement) { + var ui = PasswordMeter.PasswordMeter.instance.getUI(); + thisExplanation += ui.getCharClassStringForCharClassCountReq(); + } else { + thisExplanation += "uppercase letters; lowercase letters; digits; symbols"; + } // check if (numClasses >= minCharacterClasses && numClasses <= maxCharacterClasses) { @@ -126,33 +132,39 @@ export module RuleFunctions { var thisExplanation = ""; var compliant = false; - // explain - if (lowercaseLettersRequired) { - if (thisExplanation.length > 0) { - thisExplanation += " and a lowercase letter"; - } else { - thisExplanation = "Contain a lowercase letter"; + if (config.randomizeOrderCharClassRequirement) { + var ui = PasswordMeter.PasswordMeter.instance.getUI(); + thisExplanation += ui.getCharClassStringForMandatoryCharClassReq(); + } else { + + // explain + if (lowercaseLettersRequired) { + if (thisExplanation.length > 0) { + thisExplanation += " and a lowercase letter"; + } else { + thisExplanation = "Contain a lowercase letter"; + } } - } - if (uppercaseLettersRequired) { - if (thisExplanation.length > 0) { - thisExplanation += " and an uppercase letter"; - } else { - thisExplanation = "Contain an uppercase letter"; + if (uppercaseLettersRequired) { + if (thisExplanation.length > 0) { + thisExplanation += " and an uppercase letter"; + } else { + thisExplanation = "Contain an uppercase letter"; + } } - } - if (digitsRequired) { - if (thisExplanation.length > 0) { - thisExplanation += " and a digit"; - } else { - thisExplanation = "Contain a digit"; + if (digitsRequired) { + if (thisExplanation.length > 0) { + thisExplanation += " and a digit"; + } else { + thisExplanation = "Contain a digit"; + } } - } - if (symbolsRequired) { - if (thisExplanation.length > 0) { - thisExplanation += " and a symbol"; - } else { - thisExplanation = "Contain a symbol"; + if (symbolsRequired) { + if (thisExplanation.length > 0) { + thisExplanation += " and a symbol"; + } else { + thisExplanation = "Contain a symbol"; + } } } @@ -510,7 +522,7 @@ export module RuleFunctions { var unconservativeNnNum = conservativeNnNum + NeuralNetwork.NeuralNetwork.log10(config.neuralNetworkConfig.scaleFactor); if (conservativeNnNum < 0) { - console.log("looking up NN guess number: " + pw); + console.log("(still) looking up NN guess number: " + pw); } else if (conservativeNnNum > minLogNnGuessNum) { compliant = true; console.log("high enough NN guess number: " + pw + " (" + conservativeNnNum + diff --git a/src/ts/ui-misc.ts b/src/ts/ui-misc.ts index 09b73f2..0c60ace 100644 --- a/src/ts/ui-misc.ts +++ b/src/ts/ui-misc.ts @@ -9,6 +9,27 @@ import NeuralNetwork = require("./nn-misc"); import Constants = require("./constants"); export module UIMisc { + + // https://github.com/coolaj86/knuth-shuffle + function shuffle(array) { + var currentIndex = array.length, temporaryValue, randomIndex; + + // While there remain elements to shuffle... + while (0 !== currentIndex) { + + // Pick a remaining element... + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex -= 1; + + // And swap it with the current element. + temporaryValue = array[currentIndex]; + array[currentIndex] = array[randomIndex]; + array[randomIndex] = temporaryValue; + } + + return array; + } + export class UIMisc { helper: Helper.Helper.Helper; $: JQueryStatic; @@ -58,11 +79,76 @@ export module UIMisc { // We store this in a global to avoid double-calling the function each time. private inCompliance: boolean = false; + private randomlyOrderedCharClasses: Array = []; + constructor(verboseMode: boolean) { var registry = PasswordMeter.PasswordMeter.instance; this.helper = registry.getHelper(); this.$ = registry.getJquery(); this.verboseMode = verboseMode; + + // shuffle character classes and store for use in requirements feedback + // note: we do it here rather than shuffle each time dynamically to avoid + // confusing user with constantly changing requirements + var charClasses = ["uppercase letter", "lowercase letter", "digit", "symbol"]; + this.randomlyOrderedCharClasses = shuffle(charClasses); + console.log("randomized class ordering: " + this.randomlyOrderedCharClasses.toString()); + } + + getCharClassStringForCharClassCountReq(): string { + var pluralalizedCharClasses = this.randomlyOrderedCharClasses.map(x => x + "s"); + return pluralalizedCharClasses.join("; "); + } + + getCharClassStringForMandatoryCharClassReq(): string { + + var registry = PasswordMeter.PasswordMeter.instance; + var config: Config.Config.Config = registry.getConfig(); + var requirementString = ""; + for (var i = 0; i < this.randomlyOrderedCharClasses.length; i++) { + var charClass = this.randomlyOrderedCharClasses[i]; + switch (charClass) { + case "uppercase letter": + if (config.classRequire.upperCase) { + if (requirementString.length > 0) { + requirementString += " and an uppercase letter"; + } else { + requirementString = "Contain an uppercase letter"; + } + } + break; + case "lowercase letter": + if (config.classRequire.lowerCase) { + if (requirementString.length > 0) { + requirementString += " and a lowercase letter"; + } else { + requirementString = "Contain a lowercase letter"; + } + } + break; + case "digit": + if (config.classRequire.digits) { + if (requirementString.length > 0) { + requirementString += " and a digit"; + } else { + requirementString = "Contain a digit"; + } + } + break; + case "symbol": + if (config.classRequire.symbols) { + if (requirementString.length > 0) { + requirementString += " and a symbol"; + } else { + requirementString = "Contain a symbol"; + } + } + break; + } + } + + // mandatory classes should already be shuffled by design + return requirementString; } onReady(): void { @@ -136,7 +222,7 @@ export module UIMisc { } // They chose to discard their modal-modified password, - // so transfer the original password back to the main window + // so transfer the original password back to the main window discardpw(): void { this.$("#pwbox").val(this.pwWhenModalOpened); } @@ -281,6 +367,12 @@ export module UIMisc { // It requires the current candidate (pw), the current recursion depth (depth) // to avoid causing lag, and the original version of the password (originalPW) generateCandidateFixed(pw: string, depth: number, originalPW: string): number { + + var config = PasswordMeter.PasswordMeter.instance.getConfig(); + if (!config.provideConcretePasswordSuggestions) { + return 1; + } + // We keep a vector that tracks changes we make to the password for // future highlighting purposes. var deltas: Array = []; @@ -340,6 +432,10 @@ export module UIMisc { // Check the modification's compliance with the password-composition policy var currentUsername = this.$("#usernamebox").val() as string; + if (typeof (this.heuristicMapping[modifiedPW]) === "undefined") { + this.queryHeuristicGuessNumber(modifiedPW, currentUsername, false); + } + var verified = RuleFunctions.RuleFunctions.verifyMinimumRequirements(modifiedPW, currentUsername); if (verified.compliant) { // If it complies with the policy @@ -356,6 +452,7 @@ export module UIMisc { this.spawnFixedRating(modifiedPW); // If it does not comply, recursively calls itself to try again. } else { + // console.log("not adding " + modifiedPW + " as a recommended fix for " + originalPW + " because it does not comply with all policy requirements"); depth++; if (depth < 8) { this.generateCandidateFixed(pw, depth, originalPW); @@ -377,6 +474,8 @@ export module UIMisc { this.queryHeuristicGuessNumber(pw, username, false); // To avoid duplicating call when the heuristic function returns } else if (nni.getNeuralNetNum(pw) >= 0 && this.heuristicMapping[pw] >= 0) { + // console.log("[spawnFixedRating] heuristic mapping for " + pw + " is not undefined and is > 0: " + + // this.heuristicMapping[pw]); this.synthesizeFixed(pw); } } @@ -393,6 +492,8 @@ export module UIMisc { var changedAnyMappings: boolean = false; if (typeof (this.heuristicMapping[fixedpw]) !== "undefined" && this.heuristicMapping[fixedpw] >= 0) { + // console.log("[synthesizeFixed] heuristic mapping for " + fixedpw + " is not undefined and is > 0: " + + // this.heuristicMapping[fixedpw]); numberOfScores++; overallScore = this.heuristicMapping[fixedpw]; } @@ -401,6 +502,8 @@ export module UIMisc { if (typeof (nnNum) !== "undefined" && nnScoreAsPercent >= 0 && isFinite(nnScoreAsPercent)) { + // console.log("nn mapping for " + fixedpw + " is not undefined and and is > 0: " + + // nnScoreAsPercent); numberOfScores++; if (overallScore === 0 || (overallScore > 0 && nnScoreAsPercent < overallScore)) { @@ -412,6 +515,10 @@ export module UIMisc { + this.heuristicMapping[fixedpw] + ") and neural nets (" + nnScoreAsPercent + ")" + " " + numberOfScores); } + + // console.log("potential fixed " + fixedpw + " from heuristic (" + // + this.heuristicMapping[fixedpw] + ") and neural nets (" + // + nnScoreAsPercent + ")" + " " + numberOfScores); // When we have a sufficiently strong concrete suggestion, // find all original passwords that include that as a potential fix // and set it as the mapping @@ -419,6 +526,7 @@ export module UIMisc { if (this.verboseMode) { console.log(fixedpw + " is a plausible fix above the 2/3rds threshold"); } + // console.log(fixedpw + " is a plausible fix above the 2/3rds threshold"); for (var j in this.recommendedFixes) { if (this.recommendedFixes[j] === fixedpw && typeof (this.fixedpwMapping[j]) === "undefined") { @@ -429,23 +537,28 @@ export module UIMisc { originalOverallScore = this.heuristicMapping[j]; } var nnNumFix = nni.getNeuralNetNum(j); - var nnScoreAsPercentFix = this.scaleGuessNumByMeterStringencyFactor(nnNumFix); + var nnScoreAsPercentFix = this.scaleGuessNumByMeterStringencyFactor(nnNumFix); // note: heuristicMapping already scaled in queryHeuristicGuessNumber if (typeof (nnNumFix) !== "undefined" && nnScoreAsPercentFix >= 0 && isFinite(nnScoreAsPercentFix)) { + // console.log(fixedpw + ": NN is defined, stringency-scaled NN number is positive and finite"); + // if neural less tha heuristic score, then overall score becomes neural score if (originalOverallScore === 0 || (originalOverallScore > 0 && nnScoreAsPercentFix < originalOverallScore)) { originalOverallScore = nnScoreAsPercentFix; } } + console.log(j + ": delta improvement to overall score: " + (overallScore - originalOverallScore)); if (overallScore > (originalOverallScore + 15)) { this.fixedpwMapping[j] = fixedpw; + console.log("mapping " + j + " to " + fixedpw); if (this.verboseMode) { console.log("mapping " + j + " to " + fixedpw); } changedAnyMappings = true; } else { + console.log("not mapping " + j + " to " + fixedpw + " because it is not enough of an improvement " + originalOverallScore + " --> " + overallScore); if (this.verboseMode) { console.log("not mapping " + j + " to " + fixedpw + " because it is not enough of an improvement " + originalOverallScore + " --> " + overallScore); } @@ -474,6 +587,7 @@ export module UIMisc { if (this.verboseMode) { console.log("trying again on " + fixedpw + " as current password is " + currentpw); } + console.log("trying again on " + fixedpw + " as current password is " + currentpw); this.generateCandidateFixed(fixedpw, 0, currentpw); } return 1; @@ -899,7 +1013,7 @@ export module UIMisc { } // Recommend a concrete suggestion if we have one - if (typeof (this.fixedpwMapping[pw]) !== "undefined") { + if (config.provideConcretePasswordSuggestions && typeof (this.fixedpwMapping[pw]) !== "undefined") { // Change colors to highlight what was modified var coloredFixedPW = ""; var whereToColor = this.deltaHighlighted[this.fixedpwMapping[pw]]; @@ -928,10 +1042,12 @@ export module UIMisc { this.$(".portalToGenericAdviceModal").show(); // If they already took a concrete suggestion, don't show another if (this.tookSuggestion) { + console.log("already took suggestion for " + pw + " so hiding recs"); this.$(".recommended").hide(); this.$(".portalToGenericAdviceModal").hide(); } } else { + console.log("overall score is above 66 so for " + pw + " so hiding recs"); this.$("#nonmodalFeedbackTable").hide(); this.$("#modalFeedbackTable").hide(); this.$(".recommended").hide(); @@ -962,6 +1078,7 @@ export module UIMisc { this.$("#feedbackHeaderTextModal").html(requirementsHeader + nonCompliantAdmonition); this.$("#nonmodalFeedbackTable").show(); this.$(".recommended").hide(); + // console.log("not show rec for noncompliant password: " + pw); // Give text feedback about how they fail to comply with policy var policyGripes = []; @@ -996,7 +1113,8 @@ export module UIMisc { } // Start trying to generate a concrete suggestion - if ((pw.length === 0 || !nni.heardFromNn() || numberOfScores === 2) + if (config.provideConcretePasswordSuggestions && + (pw.length === 0 || !nni.heardFromNn() || numberOfScores === 2) && minReqObj.compliant && typeof (this.fixedpwMapping[pw]) === "undefined" && overallScore < 100) { this.generateCandidateFixed(pw, 0, pw); From a02359309086f1b92eaa1169f65597fe4931839a Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Mon, 4 Mar 2019 17:46:39 -0500 Subject: [PATCH 13/45] Cleaned up and commented code. --- README.md | 8 +- src/js/bloom-filter-js.js | 2 +- src/js/hibp-js.js | 12 +-- src/ts/PasswordMeter.ts | 6 +- src/ts/array.ts | 116 +++++++++++----------- src/ts/config.ts | 27 +---- src/ts/dict-misc.ts | 5 +- src/ts/helper.ts | 1 + src/ts/nn-misc.ts | 2 - src/ts/rulefunctions.ts | 200 +++++++++----------------------------- src/ts/string.ts | 103 ++++++++++---------- src/ts/ui-misc.ts | 57 +++-------- 12 files changed, 184 insertions(+), 355 deletions(-) diff --git a/README.md b/README.md index f7d2e94..715cbcb 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,11 @@ We expect that most people who take advantage of the example files will nonethel 1) "ignoredWords" should be updated to contain a list of site-specific words that should count for nothing in the password. We currently provide a small set of examples specific to CMU. -2) A number of variables (length, classCount, classRequire, classAllow, forbidPasswords, forbidChars, repeatChars, and usernameDifference) define the site's mandated password-composition policy. In the example file, it is set to require only that passwords contain 8 or more characters and are not one of 25 extremely common passwords. The other dimensions are currently set to inactive, but can be enabled by simply editing these variables. - -3) An additional variable (forbiddenPasswords) specifies whether or not to forbid passwords on a larger blacklist of ~100,000 common passwords taken from Mark Burnett's Xato.net corpus. In our example, it is currently set to active. For our research supporting this decision, please see: http://www.blaseur.com/papers/usec2017-blacklists.pdf +2) A number of variables (length, classCount, classRequire, classAllow, blacklist, forbidChars, repeatChars, and usernameDifference) define the site's mandated password-composition policy. In the example file, it is set to require only that passwords contain 8 or more characters. The other dimensions are currently set to inactive, but can be enabled by simply editing these variables. Beyond these configuration decisions, we expect that people who deploy our meter will edit the layout in /example/index.html and /example/config.css -Note that running the meter's code locally (e.g., from your computer's local hard disk) with browsers' default settings will not load the dictionary files (dictionary-*), and as a result no feedback will be given based on the use of dictionary words or common passwords, nor will the blacklist be active. In contrast, if loaded from a web server (e.g., Apache), these files will be loaded correctly. +Note that running the meter's code locally (e.g., from your computer's local hard disk) with browsers' default settings will not load the dictionary files (dictionary-*), and as a result no feedback will be given based on the use of dictionary words or common passwords. In contrast, if loaded from a web server (e.g., Apache), these files will be loaded correctly. Note also that the meter expects all files to be in the same directory as each other. @@ -75,7 +73,7 @@ We label each file with its intended purpose within the meter: main file; neural * **config.css** (Visual layout) The primary configuration settings for the meter's visual design are located in this file. These settings include colors, fonts, sizes, and border radii. - * **dictionary-blacklist1c8-compressed.txt** (Dictionary) An LZW compressed version of the 96,480 passwords containing at least 8 characters that appear in the Xato.net corpus of passwords at least four times. These form our optional blacklist of common 1class8 passwords. + * **dictionary-blacklist1c8-compressed.txt** (Dictionary) An LZW compressed version of the 96,480 passwords containing at least 8 characters that appear in the Xato.net corpus of passwords at least four times. * **dictionary-englishwords-compressed.txt** (Dictionary) An LZW compressed version of 80,031 frequently used English words taken from the intersection of the BYU Corpus of Contemporary American English (COCA) and the UNIX dictionary. diff --git a/src/js/bloom-filter-js.js b/src/js/bloom-filter-js.js index dd42803..b50623a 100644 --- a/src/js/bloom-filter-js.js +++ b/src/js/bloom-filter-js.js @@ -1,4 +1,4 @@ -// https://github.com/bbondy/bloom-filter-js +// based on https://github.com/bbondy/bloom-filter-js const toCharCodeArray = (str) => str.split('').map(c => c.charCodeAt(0)) diff --git a/src/js/hibp-js.js b/src/js/hibp-js.js index 6b4a88b..935336f 100644 --- a/src/js/hibp-js.js +++ b/src/js/hibp-js.js @@ -29,7 +29,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -// https://github.com/mehdibo/hibp-js (with additional tweaks for meter) +// based on https://github.com/mehdibo/hibp-js (with additional tweaks for meter/user study) class PasswordLeaks { @@ -67,9 +67,9 @@ class PasswordLeaks { } hibpCheck(pwd){ - // We hash the pwd first var that = this; - this.sha1(pwd).then(function(hash, self){ + // We hash the pwd first + this.sha1(pwd).then(function(hash){ // We send the first 5 chars of the hash to hibp's API const req = new XMLHttpRequest(); req.addEventListener("load", function(){ @@ -78,7 +78,6 @@ class PasswordLeaks { const resp = this.responseText.split('\n'); const hashSub = hash.slice(5).toUpperCase(); var wasLeakedResult = 0; - for (var index = 0; index < resp.length; index++){ // Check if the line matches the rest of the hash @@ -91,15 +90,13 @@ class PasswordLeaks { } // Trigger an event with the result that.updateHibpCache(pwd, wasLeakedResult); - }); - req.open('GET', 'https://api.pwnedpasswords.com/range/'+hash.substr(0, 5)); + req.open('GET', 'https://api.pwnedpasswords.com/range/' + hash.substr(0, 5)); req.send(); }); } previouslyLeaked(pwd) { - if (typeof(this.hibpCache[pwd])==="undefined") { this.hibpCache[pwd] = -1; // signal that we're finding out this.hibpTimings[pwd] = Date.now(); @@ -111,7 +108,6 @@ class PasswordLeaks { } else { return this.hibpCache[pwd] === 1; } - } } diff --git a/src/ts/PasswordMeter.ts b/src/ts/PasswordMeter.ts index ec199d0..9d52605 100644 --- a/src/ts/PasswordMeter.ts +++ b/src/ts/PasswordMeter.ts @@ -4,12 +4,8 @@ // LZString for LZString // optional passwordMeterConfig for configuration - - import JQuery = require("jquery"); import LZString = require("lz-string"); -//potentialTODO bootstrap has infected jquery already -//import Bootstrap = require("bootstrap"); import Helper = require("./helper"); import Config = require("./config"); import Dictionaries = require("./dict-misc"); @@ -84,7 +80,7 @@ export module PasswordMeter { getBootstrap():Bootstrap { return this.data["bootstrap"]; } - */ + */ } export var instance = new Registry(); diff --git a/src/ts/array.ts b/src/ts/array.ts index 529174e..1a3a697 100644 --- a/src/ts/array.ts +++ b/src/ts/array.ts @@ -3,81 +3,81 @@ /* ***************** */ interface Array { - removeDuplicates(): Array; - contains(x: T, strict: boolean): boolean; - listSubstringsMinMax(min: number, max: number): Array; - toHumanString(): string; + removeDuplicates(): Array; + contains(x: T, strict: boolean): boolean; + listSubstringsMinMax(min: number, max: number): Array; + toHumanString(): string; } // pretty print array to string (foo, bar and baz) -Array.prototype.toHumanString = function(): string { - // potentialTODO expect contiguous array. - var length = this.length; - if (length == 0) return "(empty)"; - if (length == 1) return this[0].toString(); - var buildString: string = this[0].toString(); - for (var i = 1; i < length - 1; i++) { - buildString += ", "+this[i].toString(); - } - buildString += " and "+this[length - 1].toString(); - return buildString; +Array.prototype.toHumanString = function (): string { + // potentialTODO expect contiguous array. + var length = this.length; + if (length == 0) return "(empty)"; + if (length == 1) return this[0].toString(); + var buildString: string = this[0].toString(); + for (var i = 1; i < length - 1; i++) { + buildString += ", " + this[i].toString(); + } + buildString += " and " + this[length - 1].toString(); + return buildString; } // Remove duplicate elements in array -Array.prototype.removeDuplicates = function(): Array { - var uniques: Array = (>this).filter(function(item: T, i: number, ar: Array) { - return ar.indexOf(item) == i; - }); - return uniques; +Array.prototype.removeDuplicates = function (): Array { + var uniques: Array = (>this).filter(function(item: T, i: number, ar: Array) { + return ar.indexOf(item) == i; + }); + return uniques; } // Checks for membership of x in the array // Accepts an optional parameter strict where true indicates // a case-sensitive check. By default, we assume strict is false. -Array.prototype.contains = function(x: T, strict: boolean): boolean { - var i = this.length; - strict = typeof strict !== 'undefined' ? strict : false; - while (i--) { - if (this[i] == x) { - return true; - } - // Check non-case-sensitive equality - if (!strict && typeof x == 'string' && typeof this[i] == 'string') { - if ((x).toLowerCase() == this[i].toLowerCase()) { - return true; - } - } - } - return false; +Array.prototype.contains = function (x: T, strict: boolean): boolean { + var i = this.length; + strict = typeof strict !== 'undefined' ? strict : false; + while (i--) { + if (this[i] == x) { + return true; + } + // Check non-case-sensitive equality + if (!strict && typeof x == 'string' && typeof this[i] == 'string') { + if ((x).toLowerCase() == this[i].toLowerCase()) { + return true; + } + } + } + return false; }; // potentialTODO should this be only in array? // Returns an array of all substrings of each array element. // Substrings are ordered from longest (max_length) to shortest (min_length). Array.prototype.listSubstringsMinMax = function(minLength: number, maxLength: number): Array { - var a = new Array(); - var longestPartLength = 0; - for (var part = 0; part < this.length; part++) { - longestPartLength = Math.max(longestPartLength, this[part].length); - } + var a = new Array(); + var longestPartLength = 0; + for (var part = 0; part < this.length; part++) { + longestPartLength = Math.max(longestPartLength, this[part].length); + } - // potentialTODO handle this better? - // Set the default minLength to 2 if unspecified - minLength = typeof minLength !== 'undefined' ? minLength : 2; - // Set the default maxLength to the length of the longest part if unspecified - maxLength = typeof maxLength !== 'undefined' ? maxLength : longestPartLength; + // potentialTODO handle this better? + // Set the default minLength to 2 if unspecified + minLength = typeof minLength !== 'undefined' ? minLength : 2; + // Set the default maxLength to the length of the longest part if unspecified + maxLength = typeof maxLength !== 'undefined' ? maxLength : longestPartLength; - // Iterate (descending) through substring lengths - for (var i = maxLength; i >= (minLength); i--) { - // Iterate through password parts - for (var k = 0; k < this.length; k++) { - // If password part is at least the length we're examining - if (this[k].length >= i) { - for (var j = 0; (j + i) <= this[k].length; j++) { - a.push(this[k].substring(j, j + i)); - } - } - } - } - return a; + // Iterate (descending) through substring lengths + for (var i = maxLength; i >= (minLength); i--) { + // Iterate through password parts + for (var k = 0; k < this.length; k++) { + // If password part is at least the length we're examining + if (this[k].length >= i) { + for (var j = 0; (j + i) <= this[k].length; j++) { + a.push(this[k].substring(j, j + i)); + } + } + } + } + return a; }; diff --git a/src/ts/config.ts b/src/ts/config.ts index 5609b30..a2ef597 100644 --- a/src/ts/config.ts +++ b/src/ts/config.ts @@ -29,11 +29,6 @@ export module Config { symbols: boolean; } - // interface ConfigForbidPasswords { - // active: boolean; - // includeLargerList: boolean; - // } - interface ConfigForbidChars { active: boolean; list: Array; @@ -61,7 +56,7 @@ export module Config { rejectionFeedback: string; } - interface ConfigBlacklist { // josh: probably should export this since pass on to dependency + interface ConfigBlacklist { active: boolean; // if case-insensitive, blacklist file should contain all lowercase entries // if stripsDigitsSymbol, blacklist file should contain all letters @@ -70,7 +65,7 @@ export module Config { stripDigitsSymbolsFromPassword: boolean; checkSubstrings: boolean; checkSubstringLength: number; // (minimum) substring length of blacklisted-item that password should be checked against - lengthException: number; + lengthException: number; // -1 if no length exception } export interface ConfigNeuralNetwork { // raise visibility because we pass it on to a dependency @@ -87,12 +82,10 @@ export module Config { symbols: ConfigSymbols; remindAgainstReuse: boolean; ignoredWords: Array; // list of words that should count for nothing in the password - // forbiddenPasswords: Array; // list of passwords that should be rejected length: ConfigLength; classCount: ConfigClassCount; classRequire: ConfigClassBoolean; classAllow: ConfigClassBoolean; - // forbidPasswords: ConfigForbidPasswords; forbidChars: ConfigForbidChars; repeatChars: ConfigLimit; sameChars: ConfigLimitLengthException; @@ -116,11 +109,6 @@ export module Config { }, remindAgainstReuse: true, // true to emphasize *not* reusing passwords ignoredWords: ["mechanical", "amazon", "mturk", "turk", "survey", "bonus", "qualtrics", "study", "carnegie", "mellon", "university"], - // forbiddenPasswords: - // ["123456", "password", "12345", "12345678", "qwerty", "1234567890", "1234", - // "baseball", "dragon", "football", "1234567", "monkey", "letmein", "abc123", - // "111111", "mustang", "access", "shadow", "master", "michael", "superman", - // "696969", "123123", "batman", "trustno1"], length: { active: true, minLength: 8, @@ -145,17 +133,12 @@ export module Config { digits: true, symbols: true, }, - // forbidPasswords: { - // active: true, - // includeLargerList: true, // setting this to true also blacklists tens of thousands //TODO change this - // // of common passwords loaded for the common passwords dictionary check - // }, forbidChars: { active: false, list: [], }, repeatChars: { - active: true, + active: false, limit: 3, // prohibit a character being repeated N or more times consecutively }, sameChars: { @@ -164,7 +147,7 @@ export module Config { lengthException: 20, // constraint does not apply if password is longer than 20 chars }, usernameDifference: { - active: true, + active: false, limit: 1, // prohibit passwords being N or fewer characters different than username }, minLogNnGuessNum: { @@ -173,7 +156,7 @@ export module Config { rejectionFeedback: "Not be similar to extremely common passwords", }, prohibitKnownLeaked: { - active: true, + active: false, smallestLength: 5, }, blacklist: { diff --git a/src/ts/dict-misc.ts b/src/ts/dict-misc.ts index e7fa059..faecdc4 100644 --- a/src/ts/dict-misc.ts +++ b/src/ts/dict-misc.ts @@ -1,6 +1,5 @@ import PasswordMeter = require("./PasswordMeter"); import Helper = require("./helper"); -// import * as BloomFilter from "./bloom-filter-js"; // was also working import BloomFilter = require("../js/bloom-filter-js"); import Config = require("./config"); import PasswordLeaks = require("../js/hibp-js"); @@ -12,11 +11,11 @@ export module Dictionaries { namesDict: Dictionary; phrasesDict: Dictionary; - passwordsDict: Dictionary; // josh: keep around; used in rulefunction.ts commonPwCheck() + passwordsDict: Dictionary; // used in rulefunction.ts commonPwCheck() englishwordsDict: Dictionary; wikipediaDict: Dictionary; petnames: Dictionary; - blacklistDict: Dictionary; // josh: use this for blacklist rule, not passwordsDict + blacklistDict: Dictionary; blacklistBloom: BloomFilter.BloomFilter; leaks: PasswordLeaks.PasswordLeaks; diff --git a/src/ts/helper.ts b/src/ts/helper.ts index 632e581..f0eb6dd 100644 --- a/src/ts/helper.ts +++ b/src/ts/helper.ts @@ -107,6 +107,7 @@ export module Helper { return dict; } + // function for loading compressed dictionaries into a bloom filter that supports substring lookup compressedFileToBloomFilter(path: string, blacklistSubstringLength: number) { // "The 1% false-positive rate can be reduced by a factor of ten diff --git a/src/ts/nn-misc.ts b/src/ts/nn-misc.ts index 58e73d9..05043e6 100644 --- a/src/ts/nn-misc.ts +++ b/src/ts/nn-misc.ts @@ -81,7 +81,6 @@ export module NeuralNetwork { // When it returns, it will display the rating (update the UI). function nnCallback(result: number, password: string): void { postProcessNnNumAndCache(result, password); - var UI = PasswordMeter.PasswordMeter.instance.getUI(); UI.displayRating(password); } @@ -90,7 +89,6 @@ export module NeuralNetwork { // concrete suggestions for a better password export function nnFixedCallback(result: number, password: string): void { postProcessNnNumAndCache(result, password); - var UI = PasswordMeter.PasswordMeter.instance.getUI(); UI.synthesizeFixed(password); } diff --git a/src/ts/rulefunctions.ts b/src/ts/rulefunctions.ts index 18ce3ba..3d5db7b 100644 --- a/src/ts/rulefunctions.ts +++ b/src/ts/rulefunctions.ts @@ -29,7 +29,7 @@ export module RuleFunctions { var compliance: { [key: string]: boolean } = {}; if (config.length.active) { - // dimension 1: length (min / max) + // requirement: length (min/max) var minLength = config.length.minLength; var maxLength = config.length.maxLength; var compliant = false; @@ -59,7 +59,7 @@ export module RuleFunctions { compliance["length"] = compliant; } - // prep for dimensions 2-4 + // prep for character-class requirements var hasLowercase = false; var hasUppercase = false; var hasDigits = false; @@ -84,7 +84,7 @@ export module RuleFunctions { hasSymbols = true; } - // dimension 2: mandatory # of character classes + // requirement: mandatory # of character classes if (config.classCount.active) { var minCharacterClasses = config.classCount.minCount; var maxCharacterClasses = config.classCount.maxCount; @@ -122,7 +122,7 @@ export module RuleFunctions { compliance["classCount"] = compliant; } - // dimension 3: mandatory character classes + // requirement: mandatory character classes if (config.classRequire.active) { var uppercaseLettersRequired = config.classRequire.upperCase; var lowercaseLettersRequired = config.classRequire.lowerCase; @@ -189,10 +189,9 @@ export module RuleFunctions { explanation["classRequire"] = thisExplanation; compliance["classRequire"] = compliant; - } - // dimension 4: forbidden character classes + // requirement: forbidden character classes if (config.classAllow.active) { var uppercaseLettersPermitted = config.classAllow.upperCase; var lowercaseLettersPermitted = config.classAllow.lowerCase; @@ -276,52 +275,10 @@ export module RuleFunctions { compliance["classAllow"] = compliant; } - // // dimension 5: forbidden passwords - // // potentialTODO how much of this is covered by forbidPasswords? - // if (config.forbidPasswords.active) { - // // potentialTODO put this under forbidPasswords? - // var forbiddenPasswords = config.forbiddenPasswords; - // var includelargerlist = config.forbidPasswords.includeLargerList; - // var thisExplanation = ""; - // var compliant = false; - - // // explain - // thisExplanation = "Not be an extremely common password"; - - // // check - // // if it's in our small array from the config file OR, - // // assuming we included the larger list, it's on that list (case-insensitive) - - // // potentialTODO use Array.contains? no strictness. - // if (pw.length === 0 || forbiddenPasswords.indexOf(pw.toLowerCase()) === -1) { - // if (includelargerlist) { - // if (pw.length === 0 || dictionaries.passwordsDict[pw.toLowerCase()] !== true) { - // compliant = true; - // } - // } else { - // compliant = true; - // } - // } - - // // report - // // note that we are only complaining about disallowed passwords if they use one - // if (compliant) { - // } else { - // thisExplanation = "" + noncompliantSymbol + thisExplanation + ""; - - // } - - // if (!compliant) { - // explanation["forbidPasswords"] = thisExplanation; - // } - // compliance["forbidPasswords"] = compliant; - // } - - // blacklist / forbidden passwords + // requirement: blacklist / forbidden passwords if (config.blacklist.active) { var thisExplanation = ""; var compliant = false; - var blacklisted = false; // explain thisExplanation = "Not be an extremely common password"; @@ -337,66 +294,16 @@ export module RuleFunctions { stringToCheck = stringToCheck.toLowerCase(); } - // switch (blacklistAlgorithm) { - // case "lc_strip_num_sym_fullstring": - // stringToCheck = pw.replace(/[^a-zA-Z]/gi, ''); - // stringToCheck = stringToCheck.toLowerCase(); - // break; - // case "case_ins_fullstring": - // case "case_ins_substring": - // stringToCheck = pw.toLowerCase(); - // break; - // default: // fullstring - // stringToCheck = pw; - // break; - // } isBlacklisted = dictionaries.blacklistRejects(stringToCheck); - - // if (!config.blacklist.checkSubstrings) { - // // just do fullstring for stringToCheck - // isBlacklisted = dictionaries.passwordsDict[stringToCheck]; - // } else { - // isBlacklisted = blacklistBloom.substringExists(pwdToCheck, blacklistSubstringLength); - - // } - // switch (blacklistAlgorithm) { - // case "case_ins_substring": - // isBlacklisted = substringOfPwdIsBlacklisted(stringToCheck); - // break; - // default: // fullstring-based matching algs - // isBlacklisted = blacklistDict[stringToCheck]; // also load appropriate lettercased blacklist in conditionX.php - // break; - // } - - } - - // // check - // // if it's in our small array from the config file OR, - // // assuming we included the larger list, it's on that list (case-insensitive) - - // // potentialTODO use Array.contains? no strictness. - // if (pw.length === 0 || forbiddenPasswords.indexOf(pw.toLowerCase()) === -1) { - // if (includelargerlist) { - // if (pw.length === 0 || dictionaries.passwordsDict[pw.toLowerCase()] !== true) { - // compliant = true; - // } - // } else { - // compliant = true; - // } - // } + } compliant = !isBlacklisted || pw.length === 0 || (config.blacklist.lengthException != -1 && pw.length >= config.blacklist.lengthException) - - // report - // note that we are only complaining about disallowed passwords if they use one - if (compliant) { - //console.log(stringToCheck + " is not on the blacklist [password: " + pw + "]"); - } else { + // report (note that we are only complaining about disallowed passwords if they use one) + if (!compliant) { thisExplanation = "" + noncompliantSymbol + thisExplanation + ""; - //console.log(stringToCheck + " IS on the blacklist [password: " + pw + "]"); } if (!compliant) { @@ -405,7 +312,7 @@ export module RuleFunctions { compliance["blacklist"] = compliant; } - // dimension 6: forbidden/permitted characters + // requirement: forbidden/permitted characters if (config.forbidChars.active) { var forbiddenChars = config.forbidChars.list; var thisExplanation = ""; @@ -413,10 +320,9 @@ export module RuleFunctions { // explain thisExplanation = "Not include the following characters: " + disallowedChars; - // note that we are only complaining about disallowed characters if they use one - // potentialTODO we apparently also check for ASCII - // check + // check + // potentialTODO we apparently also check for ASCII var pwUnique = pw.removeDuplicateChars(); var disallowedChars = ""; @@ -431,7 +337,7 @@ export module RuleFunctions { compliant = true; } - // report + // report (note that we are only complaining about disallowed characters if they use one) if (compliant) { } else { thisExplanation = "" + noncompliantSymbol + thisExplanation + ""; @@ -443,7 +349,7 @@ export module RuleFunctions { compliance["forbidChars"] = compliant; } - // dimension 7: repeated consecutive characters + // requirement: repeated consecutive characters if (config.repeatChars.active) { var repeatedCharsLimit = config.repeatChars.limit; var thisExplanation = ""; @@ -467,11 +373,9 @@ export module RuleFunctions { // report if (compliant) { thisExplanation = "" + compliantSymbol + thisExplanation; - } else { thisExplanation += " (" + charsRepeatedConsecutively.removeDuplicates().join(", ") + ")"; thisExplanation = "" + noncompliantSymbol + thisExplanation; - } thisExplanation += ""; @@ -479,7 +383,7 @@ export module RuleFunctions { compliance["repeatChars"] = compliant; } - // dimension 8: password - username comparison + // requirement: password - username comparison if (config.usernameDifference.active) { var differenceFromUsername = config.usernameDifference.limit; var thisExplanation = ""; @@ -488,7 +392,7 @@ export module RuleFunctions { // explain thisExplanation = "Not base your password around your username"; - //check + // check var pwcopy = pw.toLowerCase(); var usernamecopy = username.toLowerCase(); // remove all occurrences of username @@ -512,7 +416,7 @@ export module RuleFunctions { compliance["usernameDifference"] = compliant; } - // min NN guess number requirement + // requirement: min NN guess number (in log10) if (config.minLogNnGuessNum.active) { var compliant = false; var thisExplanation = ""; @@ -521,16 +425,20 @@ export module RuleFunctions { var conservativeNnNum = nni.getNeuralNetNum(pw); var unconservativeNnNum = conservativeNnNum + NeuralNetwork.NeuralNetwork.log10(config.neuralNetworkConfig.scaleFactor); - if (conservativeNnNum < 0) { - console.log("(still) looking up NN guess number: " + pw); - } else if (conservativeNnNum > minLogNnGuessNum) { - compliant = true; - console.log("high enough NN guess number: " + pw + " (" + conservativeNnNum + - " > " + minLogNnGuessNum + ") [unconservative NN guess number: " + unconservativeNnNum + "]"); - } else { - console.log("too low NN guess number: " + pw + " (" + conservativeNnNum + - " < " + minLogNnGuessNum + ") [unconservative NN guess number: " + unconservativeNnNum + "]"); - thisExplanation = "" + noncompliantSymbol + config.minLogNnGuessNum.rejectionFeedback; + // if nnNum < 0, then we are still waiting to hear back from the NN + if (conservativeNnNum >= 0) { + if (conservativeNnNum > minLogNnGuessNum) { + compliant = true; + console.log("high enough NN guess number: " + pw + " (" + conservativeNnNum + + " > " + minLogNnGuessNum + ") [unconservative NN guess number: " + + unconservativeNnNum + "]"); + } else { + console.log("too low NN guess number: " + pw + " (" + conservativeNnNum + + " < " + minLogNnGuessNum + ") [unconservative NN guess number: " + + unconservativeNnNum + "]"); + thisExplanation = "" + + noncompliantSymbol + config.minLogNnGuessNum.rejectionFeedback; + } } if (!compliant) { @@ -539,7 +447,7 @@ export module RuleFunctions { compliance["minLogNnGuessNum"] = compliant; } - // same character (repeated in password but not consecutively) + // requirement: same character (repeated in password, including non-consecutive repetition) if (config.sameChars.active) { var sameCharsLimit = config.sameChars.limit; var thisExplanation = ""; @@ -548,22 +456,22 @@ export module RuleFunctions { // explain if (pw.length >= config.sameChars.lengthException || (satisfiesMaxChar(pw, sameCharsLimit))) { compliant = true; - } - else { - thisExplanation = "Not contain the same character more than " + sameCharsLimit.toString() + "+ times"; + } else { + thisExplanation = "Not contain the same character more than " + sameCharsLimit.toString() + + "+ times"; } // report (only explain if violate requirement) if (!compliant) { - thisExplanation = "" + noncompliantSymbol + thisExplanation + ""; + thisExplanation = "" + noncompliantSymbol + + thisExplanation + ""; explanation["sameChars"] = thisExplanation; } compliance["sameChars"] = compliant; } - // prohibit perviously-known leaked passwords + // requirement: prohibit known previously-leaked passwords if (config.prohibitKnownLeaked.active) { - var compliant = false; var thisExplanation = ""; @@ -571,10 +479,10 @@ export module RuleFunctions { compliant = true; } else { compliant = false; - thisExplanation = "" + noncompliantSymbol + "Not use a password found in previous security leaks"; + thisExplanation = "" + noncompliantSymbol + + "Not use a password found in previous security leaks"; explanation["prohibitKnownLeaked"] = thisExplanation; } - compliance["prohibitKnownLeaked"] = compliant; } @@ -596,6 +504,8 @@ export module RuleFunctions { return ret; } + // helper function to determine if a password satisfies a max-char requirement + // for a given threshold function satisfiesMaxChar(pw: string, maxAllowed: number) { var pwChars = {}; for (var i = 0; i < pw.length; i++) { @@ -667,7 +577,6 @@ export module RuleFunctions { var uppercaseCount = 0; var publicText = ""; var sensitiveText = ""; - //var problemText = ""; var reasonWhy = ""; var fixedPW = ""; var config = PasswordMeter.PasswordMeter.instance.getConfig(); @@ -682,9 +591,6 @@ export module RuleFunctions { publicText = "Consider using more uppercase letters"; sensitiveText = "Consider using "; sensitiveText += (uppercaseCount + 1).toString() + " or more uppercase letters"; - //if(uppercaseCount != 1) { - // sensitiveText+="s"; - //} reasonWhy = "Uppercase letters are surprisingly uncommon in passwords, which makes them hard to guess"; var char1 = 65 + Math.floor(Math.random() * 26); // add an uppercase letter somewhere var loc1 = Math.floor(1 + Math.random() * (pw.length - 1)); // don't make it the first or last character since so many pws have that @@ -711,7 +617,6 @@ export module RuleFunctions { var lowercaseCount = 0; var publicText = ""; var sensitiveText = ""; - //var problemText = ""; var reasonWhy = ""; var fixedPW = ""; var config = PasswordMeter.PasswordMeter.instance.getConfig(); @@ -728,9 +633,7 @@ export module RuleFunctions { publicText = "Consider using more lowercase letters"; sensitiveText = "Consider using "; sensitiveText += (lowercaseCount + 1) + " or more lowercase letters"; - //if(lowercaseCount != 1) { - // sensitiveText+="s"; - //} + var char1 = 97 + Math.floor(Math.random() * 26); // add a lower letter somewhere var loc1 = Math.floor(1 + Math.random() * (pw.length - 1)); // don't make it the first or last character since so many pws have that fixedPW = pw.slice(0, loc1) + String.fromCharCode(char1) + pw.slice(loc1); @@ -771,9 +674,6 @@ export module RuleFunctions { reasonWhy = "Most passwords contain no digits or digits in predictable places; doing otherwise makes your password harder to guess"; sensitiveText = "Consider using "; sensitiveText += (digitCount + 1) + " or more digits"; - //if(digitCount != 1) { - // sensitiveText+="s"; - //} } return { @@ -796,7 +696,6 @@ export module RuleFunctions { var symbolCount = pw.replace(/[A-Za-z0-9]/g, "").length;; var publicText = ""; var sensitiveText = ""; - var problemText = ""; var reasonWhy = ""; var config = PasswordMeter.PasswordMeter.instance.getConfig(); // potentialTODO active? @@ -807,9 +706,6 @@ export module RuleFunctions { reasonWhy = "Few passwords contain symbols, which makes passwords with symbols harder to guess"; sensitiveText = "Consider using "; sensitiveText += (symbolCount + 1) + " or more symbols"; - //if(symbolCount != 1) { - // sensitiveText+="s"; - //} } return { @@ -1103,7 +999,6 @@ export module RuleFunctions { problemText: problemText, deltas: deltas } - } interface SymbolsPredictableComment { @@ -1339,8 +1234,6 @@ export module RuleFunctions { } */ } - // var keyvectorsjoined = "[" + keyvectors.join("][") + "]"; - // return keyvectorsjoined; var score = longestmatchlength + 1; // these are the inter-key jumps, so add 1 to get length of string var publicText = ""; var sensitiveText = ""; @@ -1689,6 +1582,7 @@ export module RuleFunctions { } } + // note: this is unrelated to the blacklist requirement specified in config interface BlacklistComment { length: number; reasonWhy: string; @@ -1833,7 +1727,6 @@ export module RuleFunctions { var wikipediaArray = new Array(); var englishwordArray = new Array(); - var registry = PasswordMeter.PasswordMeter.instance; var dictionaries = registry.getDictionaries(); var helper = registry.getHelper(); @@ -2101,9 +1994,6 @@ export module RuleFunctions { var rx = new RegExp(YYYY, "g"); dateanalyze(rx); - //console.log(datesUsed); - //console.log(passwordParts); - if (score > 0) { publicText = "Avoid using dates"; sensitiveText = "Avoid using dates like " + Helper.Helper.boldAll(datesUsed).toHumanString(); @@ -2242,7 +2132,6 @@ export module RuleFunctions { var publicText = ""; var sensitiveText = ""; var reasonWhy = ""; - //var problemText = ""; var score = 0; var pw = pw.replace(/[A-Z]/g, "U"); // replace uppercase letters with U (do this first since U is uppercase!) var pw = pw.replace(/[a-z]/g, "L"); // replace lowercase letters with L @@ -2251,7 +2140,6 @@ export module RuleFunctions { var whereInArray = Constants.Constants.commonStructures.indexOf(pw); if (whereInArray >= 0) { score = numStructures - whereInArray; - //problemText = ""; reasonWhy = "One technique attackers use is to try all possible passwords within common structures, or arrangements of character classes (e.g., where lowercase letters and digits are located)"; publicText = "The way you structure your password is predictable"; sensitiveText = publicText + " ("; diff --git a/src/ts/string.ts b/src/ts/string.ts index 63c7988..e421465 100644 --- a/src/ts/string.ts +++ b/src/ts/string.ts @@ -3,86 +3,83 @@ /* ***************** */ interface String { - replaceAt(index: number, str: string): string; - listSubstringsNoFilter(minLength: number): Array; - escapeHTML(): string; - listSubstrings(minLength: number): Array; - frequencies(): Array; - removeDuplicateChars(): string; - reverse(): string; + replaceAt(index: number, str: string): string; + listSubstringsNoFilter(minLength: number): Array; + escapeHTML(): string; + listSubstrings(minLength: number): Array; + frequencies(): Array; + removeDuplicateChars(): string; + reverse(): string; } - String.prototype.replaceAt = function(index: number, str: string): string { - return this.substr(0, index) + str + this.substr(index + 1); + return this.substr(0, index) + str + this.substr(index + 1); } // Returns an array of all substrings after lowercasing the password. // Substrings are ordered from longest to shortest (min_length). String.prototype.listSubstringsNoFilter = function(minLength: number) { - var a = new Array(); - var sanitized = this.toLowerCase(); - var theLength = sanitized.length; - for (var i = theLength; i >= (minLength - 1); i--) { - for (var j = 0; (i + j) < theLength; j++) { - var sub = sanitized.substring(j, j + i + 1); - a.push(sub); - } + var a = new Array(); + var sanitized = this.toLowerCase(); + var theLength = sanitized.length; + for (var i = theLength; i >= (minLength - 1); i--) { + for (var j = 0; (i + j) < theLength; j++) { + var sub = sanitized.substring(j, j + i + 1); + a.push(sub); } - return a; + } + return a; }; // Escape HTML in the concrete suggestion to avoid mangling the HTML layout String.prototype.escapeHTML = function(): string { - return this.replace(/&/g, '&').replace(//g, '>'); + return this.replace(/&/g, '&').replace(//g, '>'); } - - // Returns an array of all substrings after removing non-alphabetic characters // and lowercasing the password. // Substrings are ordered from longest to shortest (min_length). -String.prototype.listSubstrings = function(minLength:number): Array { - var a = new Array(); - var sanitized = this.toLowerCase(); - // Remove non-letters - var sanitized = sanitized.replace(/[^a-z]/g, ""); - var theLength = sanitized.length; - for (var i = theLength; i >= (minLength - 1); i--) { - for (var j = 0; (i + j) < theLength; j++) { - var sub = sanitized.substring(j, j + i + 1); - a.push(sub); - } - } - return a; +String.prototype.listSubstrings = function(minLength: number): Array { + var a = new Array(); + var sanitized = this.toLowerCase(); + // Remove non-letters + var sanitized = sanitized.replace(/[^a-z]/g, ""); + var theLength = sanitized.length; + for (var i = theLength; i >= (minLength - 1); i--) { + for (var j = 0; (i + j) < theLength; j++) { + var sub = sanitized.substring(j, j + i + 1); + a.push(sub); + } + } + return a; }; // Returns ASCII frequency array String.prototype.frequencies = function(): Array { - var asciiArray: Array = []; - for (var i = 0; i < this.length; i++) { - var ascii:number = this.charCodeAt(i); - if (asciiArray[ascii] == undefined) { - asciiArray[ascii] = 0; - } - asciiArray[ascii]++; - } - return asciiArray; + var asciiArray: Array = []; + for (var i = 0; i < this.length; i++) { + var ascii: number = this.charCodeAt(i); + if (asciiArray[ascii] == undefined) { + asciiArray[ascii] = 0; + } + asciiArray[ascii]++; + } + return asciiArray; }; // Return only one instance of each character that appears in a string String.prototype.removeDuplicateChars = function(): string { - return this.split('').filter(function(item: string, i: number, ar: Array) { - return ar.indexOf(item) === i; - }).join(''); + return this.split('').filter(function(item: string, i: number, ar: Array) { + return ar.indexOf(item) === i; + }).join(''); } // Returns the reverse of any string String.prototype.reverse = function(): string { - var a: string = ''; - var i: number = this.length; - while (i--) { - a += this[i]; - } - return a; -}; \ No newline at end of file + var a: string = ''; + var i: number = this.length; + while (i--) { + a += this[i]; + } + return a; +}; diff --git a/src/ts/ui-misc.ts b/src/ts/ui-misc.ts index 0c60ace..743b4b3 100644 --- a/src/ts/ui-misc.ts +++ b/src/ts/ui-misc.ts @@ -10,17 +10,15 @@ import Constants = require("./constants"); export module UIMisc { - // https://github.com/coolaj86/knuth-shuffle + // based on: https://github.com/coolaj86/knuth-shuffle function shuffle(array) { var currentIndex = array.length, temporaryValue, randomIndex; // While there remain elements to shuffle... while (0 !== currentIndex) { - // Pick a remaining element... randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; - // And swap it with the current element. temporaryValue = array[currentIndex]; array[currentIndex] = array[randomIndex]; @@ -62,15 +60,19 @@ export module UIMisc { // Mapping of passwords to a potential concrete suggestion. // If the suggestion is scored highly enough, then store it in fixedpwMapping. private recommendedFixes: { [key: string]: string } = {}; + // To avoid excess computation, keep track of how many tries we've made // trying to generate a strong concerete suggestion. If too many, // give up rather than potentially cause UI lag. private recommendedFixesTries: { [key: string]: number } = {}; + // Keep track of the previous candidate we tried for the concrete suggestion. // If insufficiently strong, we'll want to modify it private previousCandidate: { [key: string]: string } = {}; + // Final mapping of password to (pre-validated) stronger concrete suggestion private fixedpwMapping: { [key: string]: string } = {}; + // How the concrete suggestion was modified from the original (for highlights) private deltaHighlighted: { [key: string]: Array } = {}; @@ -79,6 +81,7 @@ export module UIMisc { // We store this in a global to avoid double-calling the function each time. private inCompliance: boolean = false; + // randomly-ordered list of the 4 character classes, for use in feedback private randomlyOrderedCharClasses: Array = []; constructor(verboseMode: boolean) { @@ -92,16 +95,16 @@ export module UIMisc { // confusing user with constantly changing requirements var charClasses = ["uppercase letter", "lowercase letter", "digit", "symbol"]; this.randomlyOrderedCharClasses = shuffle(charClasses); - console.log("randomized class ordering: " + this.randomlyOrderedCharClasses.toString()); } + // return randomly-ordered list of all 4 character classes, as string getCharClassStringForCharClassCountReq(): string { var pluralalizedCharClasses = this.randomlyOrderedCharClasses.map(x => x + "s"); return pluralalizedCharClasses.join("; "); } + // return string containing randomly-ordered, required character classes getCharClassStringForMandatoryCharClassReq(): string { - var registry = PasswordMeter.PasswordMeter.instance; var config: Config.Config.Config = registry.getConfig(); var requirementString = ""; @@ -147,7 +150,7 @@ export module UIMisc { } } - // mandatory classes should already be shuffled by design + // mandatory classes should already be shuffled, by construction return requirementString; } @@ -313,8 +316,8 @@ export module UIMisc { } } - // translate NN/heuristic guess number to a percentage-based score (based on stringency configuration). - // this will influence meter fill. + // translate NN/heuristic guess number to a percentage-based score (based on meter + // stringency configuration). this will influence meter fill. scaleGuessNumByMeterStringencyFactor(guessNum: number): number { if (guessNum > 0) { return guessNum * Constants.Constants.METER_STRINGENCY_SCALE_FACTOR; @@ -452,7 +455,6 @@ export module UIMisc { this.spawnFixedRating(modifiedPW); // If it does not comply, recursively calls itself to try again. } else { - // console.log("not adding " + modifiedPW + " as a recommended fix for " + originalPW + " because it does not comply with all policy requirements"); depth++; if (depth < 8) { this.generateCandidateFixed(pw, depth, originalPW); @@ -474,8 +476,6 @@ export module UIMisc { this.queryHeuristicGuessNumber(pw, username, false); // To avoid duplicating call when the heuristic function returns } else if (nni.getNeuralNetNum(pw) >= 0 && this.heuristicMapping[pw] >= 0) { - // console.log("[spawnFixedRating] heuristic mapping for " + pw + " is not undefined and is > 0: " + - // this.heuristicMapping[pw]); this.synthesizeFixed(pw); } } @@ -492,8 +492,6 @@ export module UIMisc { var changedAnyMappings: boolean = false; if (typeof (this.heuristicMapping[fixedpw]) !== "undefined" && this.heuristicMapping[fixedpw] >= 0) { - // console.log("[synthesizeFixed] heuristic mapping for " + fixedpw + " is not undefined and is > 0: " + - // this.heuristicMapping[fixedpw]); numberOfScores++; overallScore = this.heuristicMapping[fixedpw]; } @@ -502,8 +500,6 @@ export module UIMisc { if (typeof (nnNum) !== "undefined" && nnScoreAsPercent >= 0 && isFinite(nnScoreAsPercent)) { - // console.log("nn mapping for " + fixedpw + " is not undefined and and is > 0: " + - // nnScoreAsPercent); numberOfScores++; if (overallScore === 0 || (overallScore > 0 && nnScoreAsPercent < overallScore)) { @@ -516,9 +512,6 @@ export module UIMisc { + nnScoreAsPercent + ")" + " " + numberOfScores); } - // console.log("potential fixed " + fixedpw + " from heuristic (" - // + this.heuristicMapping[fixedpw] + ") and neural nets (" - // + nnScoreAsPercent + ")" + " " + numberOfScores); // When we have a sufficiently strong concrete suggestion, // find all original passwords that include that as a potential fix // and set it as the mapping @@ -526,7 +519,6 @@ export module UIMisc { if (this.verboseMode) { console.log(fixedpw + " is a plausible fix above the 2/3rds threshold"); } - // console.log(fixedpw + " is a plausible fix above the 2/3rds threshold"); for (var j in this.recommendedFixes) { if (this.recommendedFixes[j] === fixedpw && typeof (this.fixedpwMapping[j]) === "undefined") { @@ -541,7 +533,7 @@ export module UIMisc { if (typeof (nnNumFix) !== "undefined" && nnScoreAsPercentFix >= 0 && isFinite(nnScoreAsPercentFix)) { - // console.log(fixedpw + ": NN is defined, stringency-scaled NN number is positive and finite"); + // if neural less tha heuristic score, then overall score becomes neural score if (originalOverallScore === 0 || (originalOverallScore > 0 @@ -549,16 +541,14 @@ export module UIMisc { originalOverallScore = nnScoreAsPercentFix; } } - console.log(j + ": delta improvement to overall score: " + (overallScore - originalOverallScore)); + if (overallScore > (originalOverallScore + 15)) { this.fixedpwMapping[j] = fixedpw; - console.log("mapping " + j + " to " + fixedpw); if (this.verboseMode) { console.log("mapping " + j + " to " + fixedpw); } changedAnyMappings = true; } else { - console.log("not mapping " + j + " to " + fixedpw + " because it is not enough of an improvement " + originalOverallScore + " --> " + overallScore); if (this.verboseMode) { console.log("not mapping " + j + " to " + fixedpw + " because it is not enough of an improvement " + originalOverallScore + " --> " + overallScore); } @@ -587,7 +577,6 @@ export module UIMisc { if (this.verboseMode) { console.log("trying again on " + fixedpw + " as current password is " + currentpw); } - console.log("trying again on " + fixedpw + " as current password is " + currentpw); this.generateCandidateFixed(fixedpw, 0, currentpw); } return 1; @@ -770,43 +759,36 @@ export module UIMisc { publictips.push(lenObj.publicText); sensitivetips.push(lenObj.sensitiveText); reasonWhy.push(lenObj.reasonWhy); - //problemText.push(lenObj.problemText); } if (symbolObj.publicText.length > 0) { publictips.push(symbolObj.publicText); sensitivetips.push(symbolObj.sensitiveText); reasonWhy.push(symbolObj.reasonWhy); - //problemText.push(symbolObj.problemText); } if (upperObj.publicText.length > 0) { publictips.push(upperObj.publicText); sensitivetips.push(upperObj.sensitiveText); reasonWhy.push(upperObj.reasonWhy); - //problemText.push(upperObj.problemText); } if (digitObj.publicText.length > 0) { publictips.push(digitObj.publicText); sensitivetips.push(digitObj.sensitiveText); reasonWhy.push(digitObj.reasonWhy); - //problemText.push(digitObj.problemText); } if (lowerObj.publicText.length > 0) { publictips.push(lowerObj.publicText); sensitivetips.push(lowerObj.sensitiveText); reasonWhy.push(lowerObj.reasonWhy); - //problemText.push(lowerObj.problemText); } if (commonsubstringObj.publicText.length > 0 && !this.redundant(commonsubstringObj.problemText, problemText)) { publictips.push(commonsubstringObj.publicText); sensitivetips.push(commonsubstringObj.sensitiveText); reasonWhy.push(commonsubstringObj.reasonWhy); - //problemText.push(commonsubstringObj.problemText); } if (structureObj.publicText.length > 0) { publictips.push(structureObj.publicText); sensitivetips.push(structureObj.sensitiveText); reasonWhy.push(structureObj.reasonWhy); - //problemText.push(structureObj.problemText); } // Save the mapping of password to score @@ -841,8 +823,6 @@ export module UIMisc { } } - - // Update all aspects of the UI (bar and text feedback) to reflect password. // Note that the password score and feedback was generated + cached in other functions. displayRating(pw: string): void { @@ -888,14 +868,13 @@ export module UIMisc { reasonWhy3: "", }); } - var feedback = JSON.parse(this.feedbackMapping[pw]); + var feedback = JSON.parse(this.feedbackMapping[pw]); var config = PasswordMeter.PasswordMeter.instance.getConfig(); - var currentUsername = this.$("#usernamebox").val() as string; var nni = PasswordMeter.PasswordMeter.instance.getNN(); - var minReqObj = RuleFunctions.RuleFunctions.verifyMinimumRequirements(pw, currentUsername); + // If password complies with password policy, show feedback if (minReqObj.compliant) { this.inCompliance = true; @@ -1042,12 +1021,10 @@ export module UIMisc { this.$(".portalToGenericAdviceModal").show(); // If they already took a concrete suggestion, don't show another if (this.tookSuggestion) { - console.log("already took suggestion for " + pw + " so hiding recs"); this.$(".recommended").hide(); this.$(".portalToGenericAdviceModal").hide(); } } else { - console.log("overall score is above 66 so for " + pw + " so hiding recs"); this.$("#nonmodalFeedbackTable").hide(); this.$("#modalFeedbackTable").hide(); this.$(".recommended").hide(); @@ -1078,7 +1055,6 @@ export module UIMisc { this.$("#feedbackHeaderTextModal").html(requirementsHeader + nonCompliantAdmonition); this.$("#nonmodalFeedbackTable").show(); this.$(".recommended").hide(); - // console.log("not show rec for noncompliant password: " + pw); // Give text feedback about how they fail to comply with policy var policyGripes = []; @@ -1109,7 +1085,6 @@ export module UIMisc { mRow.show(); suggestion.html(gripe); } - } // Start trying to generate a concrete suggestion @@ -1207,7 +1182,6 @@ export module UIMisc { e.removeClass('selected'); }); } - } (function() { @@ -1252,5 +1226,4 @@ export module UIMisc { }); }()) - } From ecb32eca8b7427e30f9b8d1b6d0efade50ff9466 Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Mon, 4 Mar 2019 17:50:02 -0500 Subject: [PATCH 14/45] Updated compiled js --- src/PasswordMeter.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PasswordMeter.js b/src/PasswordMeter.js index f9cfc06..50b004f 100644 --- a/src/PasswordMeter.js +++ b/src/PasswordMeter.js @@ -2,7 +2,7 @@ const toCharCodeArray=t=>t.split("").map(t=>t.charCodeAt(0)),simpleHashFn=t=>(r,e,s)=>e?(e-s*Math.pow(t,r.length-1))*t+r[r.length-1]:r.reduce((e,s,i)=>e+s*Math.pow(t,r.length-i-1),0),setBit=(t,r)=>t[r/8|0]|=1<!!(t[r/8|0]&1<r(t)%this.bufferBitSize)}getHashesForCharCodes(t,r,e){return this.hashFns.map((s,i)=>s(t,r?r[i]:void 0,e,this.bufferBitSize))}add(t){t.constructor!==Array&&(t=toCharCodeArray(t)),this.getLocationsForCharCodes(t).forEach(this.setBit)}exists(t){return t.constructor!==Array&&(t=toCharCodeArray(t)),this.getLocationsForCharCodes(t).every(this.isBitSet)}substringExists(t,r){let e,s;t.constructor!==Uint8Array&&(t.constructor!==Array&&(t=toCharCodeArray(t)),t=new Uint8Array(t));for(let i=0;it%this.bufferBitSize).every(this.isBitSet))return!0;s=t[i]}return!1}}exports.BloomFilter=BloomFilter; },{}],2:[function(require,module,exports){ -class PasswordLeaks{constructor(){this.hibpCache={},this.hibpTimings={}}sha1(e){var t=new TextEncoder("utf-8").encode(e);return crypto.subtle.digest("SHA-1",t).then(function(e){for(var t=[],s=new DataView(e),i=0;i=t;e--)for(var s=0;s=e)for(var h=0;h+e<=this[s].length;h++)i.push(this[s].substring(h,h+e));return i}; },{}],5:[function(require,module,exports){ -"use strict";var Config;exports.__esModule=!0,function(e){e.passwordMeterDefaultConfig={provideConcretePasswordSuggestions:!0,randomizeOrderCharClassRequirement:!0,colors:{compliant:"#006600",noncompliant:"#660000"},symbols:{compliant:"✔ ",noncompliant:"❑ "},remindAgainstReuse:!0,ignoredWords:["mechanical","amazon","mturk","turk","survey","bonus","qualtrics","study","carnegie","mellon","university"],length:{active:!0,minLength:8,maxLength:0},classCount:{active:!1,minCount:1,maxCount:4},classRequire:{active:!1,upperCase:!1,lowerCase:!0,digits:!0,symbols:!1},classAllow:{active:!1,upperCase:!0,lowerCase:!0,digits:!0,symbols:!0},forbidChars:{active:!1,list:[]},repeatChars:{active:!0,limit:3},sameChars:{active:!1,limit:3,lengthException:20},usernameDifference:{active:!0,limit:1},minLogNnGuessNum:{active:!1,threshold:7,rejectionFeedback:"Not be similar to extremely common passwords"},prohibitKnownLeaked:{active:!0,smallestLength:5},blacklist:{active:!1,blacklistFile:"blacklist-cmu-compressed.txt",caseSensitive:!1,stripDigitsSymbolsFromPassword:!1,checkSubstrings:!1,checkSubstringLength:5,lengthException:20},neuralNetworkConfig:{intermediate:"basic_3M.info_and_guess_numbers.no_bloomfilter.json",file:"basic_3M.weight_arch.quantized.fixed_point1000.zigzag.nospace.json",zigzag:!0,scaleFactor:300}}}(Config=exports.Config||(exports.Config={})); +"use strict";var Config;exports.__esModule=!0,function(e){e.passwordMeterDefaultConfig={provideConcretePasswordSuggestions:!0,randomizeOrderCharClassRequirement:!0,colors:{compliant:"#006600",noncompliant:"#660000"},symbols:{compliant:"✔ ",noncompliant:"❑ "},remindAgainstReuse:!0,ignoredWords:["mechanical","amazon","mturk","turk","survey","bonus","qualtrics","study","carnegie","mellon","university"],length:{active:!0,minLength:8,maxLength:0},classCount:{active:!1,minCount:1,maxCount:4},classRequire:{active:!1,upperCase:!1,lowerCase:!0,digits:!0,symbols:!1},classAllow:{active:!1,upperCase:!0,lowerCase:!0,digits:!0,symbols:!0},forbidChars:{active:!1,list:[]},repeatChars:{active:!1,limit:3},sameChars:{active:!1,limit:3,lengthException:20},usernameDifference:{active:!1,limit:1},minLogNnGuessNum:{active:!1,threshold:7,rejectionFeedback:"Not be similar to extremely common passwords"},prohibitKnownLeaked:{active:!1,smallestLength:5},blacklist:{active:!1,blacklistFile:"blacklist-cmu-compressed.txt",caseSensitive:!1,stripDigitsSymbolsFromPassword:!1,checkSubstrings:!1,checkSubstringLength:5,lengthException:20},neuralNetworkConfig:{intermediate:"basic_3M.info_and_guess_numbers.no_bloomfilter.json",file:"basic_3M.weight_arch.quantized.fixed_point1000.zigzag.nospace.json",zigzag:!0,scaleFactor:300}}}(Config=exports.Config||(exports.Config={})); },{}],6:[function(require,module,exports){ "use strict";var Constants;exports.__esModule=!0,function(L){L.LOWERCASE_LETTERS=new RegExp("[a-z]"),L.LOWERCASE_LETTERS_GLOBAL=new RegExp("[a-z]","g"),L.UPPERCASE_LETTERS=new RegExp("[A-Z]"),L.UPPERCASE_LETTERS_GLOBAL=new RegExp("[A-Z]","g"),L.NONALPHA=new RegExp("[^A-Za-z]"),L.DIGITS=new RegExp("[0-9]"),L.DIGITS_GLOBAL=new RegExp("[0-9]","g"),L.SYMBOLS=new RegExp("[^A-Za-z0-9]"),L.SYMBOLS_GLOBAL=new RegExp("[^A-Za-z0-9]","g"),L.startASCII=32,L.endASCII=126,L.METER_STRINGENCY_SCALE_FACTOR=67/12,L.commonStructures=["LLLLLL","LLLLLLLL","LLLLLLL","DDDDDDDD","DDDDDD","LLLLL","DDDDDDD","LLLLLLDD","LLLLLLLLL","LLLL","DDDD","LLLLLLLD","LLLLLD","LLLLLLLLLL","LLLLLDD","LLLLDDDD","LLLLLLD","LLLLDD","LLLLLDDD","DDDDD","LLLDDD","LLLDDDD","DDDDDDDDD","LLLLLLLLLLL","DDDDDDL","LLLLLDDDD","LLLLDDD","LLLLLLLDD","DDDDDDDDDD","LLLLLLLLLLLL","LLLLLLDDDD","DDDDDDDDL","UUUUUUUU","LLLLLLDDD","LLDDDD","DDDDDDDDDDD","ULLLLL","LLLLLLLLDD","LLLLLLLLD","ULLLLLLL","UUUUUU","ULLLLLLD","LLLLLLLLLLLLL","ULLLLLL","LLLLLLLDDDD","LLLLLLLDDD","ULLLLLD","DDDDLLLL","LLLLLLLLLLLLLL","LLLLD","LLDDDDDD","DLLLLLLL","UUUUUUU","LLLLLLLLLD","DDLLLLLL","DDDDLL","DDDDDDLL","LDDDDDD","LLLDDDDD","ULLLLLDD","LLLLLLLLDDDD","DDDLLL","LLLLLLLLLDD","DDDDDDDL","LLLLLLLLLLLLLLL","DDDDLLL","DULLLLL","DULLLLLL","LLLDDDDDD","ULLLLD","LLLLLLLLDDD","DLLLLL","DDDDDDLLL","LLLLDLLL","LLLLDDDDDD","ULLLL","LLLDD","LDDDDDDD","LLLDLLLL","LLLLLLLLLLLLLLLL","DDLLLL","LLLDDLLL","DDDDDDDDDDDD","DLLLLLL","DDLLLLL","LLLLLDLL","LLLLLLLLLLDD","LLDDDDD","LLLLLDDDDDD","DDDLLLLL","LDDDDDDDD","DDDDDDLLLL","UUUUU","LLLLLLDL","LDDDDD","ULLLDDDD","ULLLLDDD","ULLLLLLLL","LLLLLLLLLDDD","DDDDDL","LLLLLLDDDDDD","LLLLLLLLLLDDDD","DULLLL","ULLLLDD","LLLLDDDDD","LLLLDL","LDLLLLLL","LLDLLLLL","LLLDLL","LLDLLL","LLLLLLLLLLD","LLLDLLL","LLLLLDDDDD","DDDDLLLLL","LDLDLDLD","DDDDDDDDLL","DDDDDDDDLLL","LLLLLLLLLDDDD","DDDLLLL","DDDDDDDDLLLL","DLLLLLLD","LLDDD","LDLDLD","LLLD","DDDDDDDDDL","DLLLDLLL","LDLLLL","LLLLDDDDDDDD","LLLLDLL","UUUU","ULLLLDDDD","LLLLLDL","ULLLLLLDD","DDLLLLDD","LLLLLLDDDDD","LLDDLL","DDDDLLLLLL","DDDDDLLL","DDDDDDDDDDDL","DDDDDDDDDDL","LLLDDDDDDDD","LDDDDL","LLLLDDLL","ULLL","LLLLLLLLLLLDD","LLLLLLLLLLLLLLLLL","DDDDDDLLLLL","LLLLLLLLLLLLDD","LLLLLLLLLLLD","ULLLLLDDDD","LDDDLL","ULLLLLLLLL","ULLLDD","LLLDDDDDDD","LLDDDDDDD","LLLDLLLD","DDLLLDD","DDDDDDDLL","LLDDDDDDDD","ULLLLLLLD","LLLLLDDL","DLDLDLDL","LLDDDDLL","DDDDDDDLLL","DLDLDL","ULLLLLDDD","LLLLLDDDDDDDD","UUUUUUDD","LLDLLLL","LLLLLLLLLLDDD","LDDDDDDL","DDDDDLL","ULLLD","LLLLDDDDDDD","LLDDLLLL","LLLDDDLL","DDDDDDLLLLLL","DLLLLD","DLLLL","LLLLLLLLLLLLLLLLLL","LLLDDLL","ULLLLLLLDD","LLDDLLDD","UUUUUUUUU","LLLLLLLLLLLDDDD","DULLL","ULLLDDD","DDLLLLLLL","LLL","UUUUDDDD","DDLLDD","DDDLLLLLL","DDDDDDDDLLLLL","LLLDDL","DLLLLLD","DDDDDDDLLLL","LDLLLLL","UUUDDDD","LLLLLLLDDDDDD","DLLLLLLLL","LLLLLLLLLLLDDD","LLLLLLLLLLLLLDD","LLLLLLDDDDDDDD","UUUUUD","UUUUDD","LDDLLLLL","LLLLDLLLL","DDDDLLLLLLL","LLLLLDDDDDDD","DDDDL","UUUDDD","LLLLLLLLLLLLD","UUDDDD","UUUUUUUD","LLLLLLLLLLLLDDDD","LDLDLDLDLD","LDDD","LLDLLD","DDDDDDU","LLLLDDL","LLLDDDDL","UUUUUDD","LLLLLLLDDDDD","DDLLLLLDD","UDDDDDD","LLDD","LDDDD","LLDDDLL","ULLLULLL","DDDDLLLLLLLL","LDLLLDLL","DDDDDLLLL","LDDLLL","LLLLLDLD","ULLLLLLDDD","ULLLLU","DDLLL","LLDDLLL","ULLLLLLDDDD","LDDLDD","LDLLDL","ULLLLLLLLLL","LLDLLLDL","","LLLLDLLD","LLDLLDLL","LLLDL","LLDLLLLD","ULDDDDDD","ULLULL","LLLDDDLLL","UUUUUDDD","LLDLL","UUUUUUD","LLLLDDDL","LLLLLLLLLLLLLD","LLLLLLLLDDDDDD","UUUUUUUUUU","LDLLLLDL","LLLLDLDL","LDLLDLLL","LLLLLLLLLLLLLLLLLLL","DLDLLLLL","DDDLLLDDD","DDDDDLLLLL","LLLDDDL","DLLLLDLL","LLLDLLDL","LLLLLLLLLLLLDDD","LDDDDDDDDD","ULLLLLLLLD","LDLDLLLL","LLLLLLLLLLLLLLDD","DDLLLLLLLL","LLDLDLLL","DLLLLLDL","DDDDDDDDU","DDDDDDDDLLLLLL","LDDDDDDDDDD","LDLLLLLD","DDLLLLLLDD","LLDDDL","LLLDLDLL","DLLL","ULLDDDD","DDLLDLLL","DLLLLLLLLL","DLLDLLLL","DDDLL","LLLLLLDDDDDDD","DDD","LLLLLLLDDDDDDDD","LLLDLD","DDLLLLLD","DLLDLL","LLLLLLDLL","UUDDDDDD","DDDDDDDDDLLL","LLDDDLLL","ULLLLLLLLDD","ULULLL","DDLLDDLL","DLLLLLDD","LDLLL","DDDDDDDLLLLL","DDLDDLDDL","ULULUL","ULLLUL","LDLLLD","UDDDDDDDD","LLLLLDLLL","LDLDLL","ULLLLULL","DDDDDDDDDDDDD","ULLLLLLLDDDD","UUUUDDD","LLLLLLLLLLLLLLLLLLLL","DDDDDDDDDDDDDD","DDDLDDD","DDLDDL","DLLLDL","ULLLUU","DLDLDLDLDL","ULLLLLLLDDD","ULLDDD","LLLLLLDLLL","DDDLLLLLLL","DDDDDDDDDDLL","DDLLLDDDD","UDDDDDDD","ULUULL","ULULLU","ULLLLLLLLLD","ULUULU","DDDDDDDDDLL","LLLLLDLLLL","DDDDDDDDDDDLLLL","ULUUUL","ULUUUU","ULLUUU","ULLULU","ULLUUL","LLDLDL","LLLLLLLDL","LLLLLLLS","LLDL","LLLLLLLLLLLLLLD","LDDDDDDDDL","LDDDLLL","LLLLLLS","ULULUU","LDDDDDDDDDDD","LLLLLLLLLLLLLDDD","LLLLLLLLLDDDDDD","DDDDDDLLLLLLL","DDDDDDDDDDLLL","LLLDDLLD","DDDLLDDD","LDDLDDLDD","LLLDLLLLL","ULLLLLLLLLLL","LLLLDDLLL","DDLLLD","LLLDDDDLLL","DDDDDDDDDDDLLL","LDLDLDL","LLLLLLLLDDDDD","LLLLSLLL","LLLLLLLLDDDDDDDD","DLLLDD","LLLLDLD","DDDDDDDDDDDDDDDD","DLDLLL","UUUUUDDDD","DDDDDDDDDDLLLL","LLLLDLLLLL","DLLLD","DDDDDDDU","DDDDDDUU","DDDLLLDD","LLDDDDL","DLLLLLLLD","LLLSLLL","LDDLLLL","ULLLDDDDDD","LLLLLLLLLLLLLDDDD","DDLLLLD","ULLULLLL","LLLDDLLLL","LLLLDDLLLL","DDDLLLLDDD","LDLL","LDDDDDDDL","LLLDLLLLLL","DDDDDDDDDLLLL","LDDDLLDD","LDDDLLLL","LLDDLLLD","DDDDDDDDDDDLL","LLLDLLDD","DDLL","DDDDUU","DDLDDLDD","DDDDDDLLLLLLLL","DDLDDDD","DDDDLLDD","LLLLLS","ULLDDDDDD","LLDLLDL","LDLDLDLL","LLLLDLDD","LDLLLLLLL","DDDLLLD","LLDLLLDD","ULLDDDDD","ULLLLLLU","ULDDDD","LLLDDLLLDD","UUUUUUUDD","LLLLLLLDDDDDDD","UUUDDDDD","LLDLLLD","UUDDDDD","LDLDL","UUUUUUUUUUU","LDLLLLDD","LLDLLLLLL","LLLDDLDL","DLLLDLL","DLLLLDD","LLLLLSDD","DDDDULLL","DDLLDDDD","LLLLLLLDLL","DLLLLDL","LLLLLLLLDL","LDLLLDL","DLDLDLD","LLDLDD","LLLDDDDDDDDD","ULLLLDDDDDD","LDDDLDDD","DDDDDDDDDDDDDDD","DDDDDDDDDDDDL","ULLULLL","LDLDLDLDLDLD","LLLDLLD","DDDDDDDLLLLLL","LDDDDDL","DDDLLLLLLLLL","LLDDL","LLLLLLDDL","LDLLDLL","LDLLDLDL","LLLLLLLLLLLLLLLDD","UULLLLLL","ULLLLLLLLLDD","LDDDDLL","LDLLDLLD","DDDLDD","DDLLLLLLLDD","LLLLLLLLS","UUUUUUDDDD","LLLLDDLD","UDDDDD","LLDDLDLL","DDDDDDDDLLLLLLL","UUUDDDDDD","DDDDLDDDD","LLDDLD","LLLLLDDLLL","DDLLLDDD","UUUUUUDDD","LLLLLDDLL","LLLLDDDDDDDDDD","DDDLLLLLLLL","LLLLLLLLLDDDDD","LDLLDD","LLLLLLLLLLLLLLLLLLLLL","LLLLLLLLLLLLLLLD","LLLSLLLL","DDDDLD","DDLDDD","DDDDUUUU","DLDLL","LDLLLLD","DLDLLLDL","LLLLSLLLL","LDLDLLDL","DDLDLLLL","DDDDDDDDDDDLLLLL","LLLLLLLLLLDDDDDD","UUUUUUUUUUUU","LLLDLDL","LLLLDDDDDDDDD","DDDDDLLLLLL","DDULLLLL","ULLLULL","LLLLLLLLLLLLLLDDDD","DLLDLLDL","LLLDLDLD","LLLDDDDDDDDDD","DDDDLLLLDDDD","LLLLSL","LDLDLLL","DLLLLLLLLD","LDLLLDLD","DDDDLDD","ULDDDLL","LLDLLLLLLL","LLLLLLSDD","DLDLLLL","ULLLLLLLLDDD","LLDLDLL","DDDDDDS","DDLLLLLLLLL","LDLLLDDL","ULLLLDLL","DDLLLDLL","DDLLDL","LLLLLSLLL","DLLLDDLL","LDLDLDLDL","DLLLDLDL","DLLDLLL","DLLDL","DLDLDLLL","LLDDLLD","DDDLLLLLDDD","DDSDDSDDDD","LLDDLLDL","DLLDLLLD","DLLLDDD","LLDLLDDL","LLLLLU","DLLDLDLL","LDDLDL","LDDLLD","LLDLLDLD","DDLLDDD","DDDDLLLD","DLLDDL","ULLLLLDDDDDD","DDDLDDDL","DDLLD","LLLLLDLLLLL","LLLDDLDD","LLDLDLLD","LDDDDLLL","DLLDDLLL","LLLLDDDDDDDDDDD","DLDLLDLL","LLDDDDDDDDD","DDDDDDUUU","DLDDLLLL","DDDLLD","LDDLLLLD","LDLLLLLLLL","DDDDUUU","LLDLDLDL","DLLLLDLD","DDLLLLDDDD","ULLLLDDDDD","LUULDDL","ULLLDDDDD","LDDLLLDL","ULLLLLLLLDDDD","DDLLLLDL","DLLLLLLLLLL","ULLLLLU","LLLLLSLL","DLLLLDDL","LDLDLLLD","DLDLLLLD","UUUDD","LDLDDLLL","LLLLLLDLLLL","LDLLD","DDDDDDUL","LDLD","DLLLLDDD","LDLLDDLL","UUUUD","LDDLLDLL","LLLLLLLLDDDDDDD","LLLDLDDL","DLLLDLLD","DDDDDDDDDDLLLLL","LLLLLDDDDDDDDD","DDDDDDDDUU","LLLLLDDDDDDDDDD","ULDDDDDDDD","UUULLL","LLLLLSLLLLL","LLLLLSLLLL","DLDLLD","LLLSDDDD","LLDDDDDDLL","DLLLDDDD","DLDLD","ULLLLLLLLLLLL","LLLLLLULLLLL","LLDLDDLL","LLLLLLLLLLLLLLDDD","DDDDLLD","LLLDDDLD","ULLLLULLLL","LDDLL","DDLLLDDL","DDDLLLLD","DDDL","ULDDDDDDD","LLLLLLLU","DDDLLDD","LLLLLLLLLLDDDDD","DDLDD","LLLLLLLLLLLLLLLLLLLLLL","UDLLLLLL","LLLLSDD","LDDLDLLL","DLDDLL","LLLLSLLLLL","LLLLSLLLLLL","LLDDDDDDDDDD","DLDDDD","ULLLDLLL","LLLDDDDLL","DDDDLDDD","DLDLDLDLDLDL","ULLLLLUL","DDLDLL","UUULLLLL","UDDDDDDL","LLLLLLDDDDDDDDD","LLLLLLLLLS","LLSLLL","LLDLD","DDDLDDDD","LLLLLLLLLLLLLLLLDD","LLLDDLD","LLLLLLSD","UUUUUUUUDD","LDLDDD","LLDLLDD","DDDDLLLDDDD","DDLLLLLLLLDD","LLLLDDDDLLLL","DDDDDU","UUUDDDUU","DDDDDDDDLLLLLLLL","LLLLDLLLLD","UUUUUUUUD","LLLLSDDD","LLLLLDDDDDDDDDDD","DDDLLLLLLDDD","DLLDDD","DLLDLD","LLDDLLLLL","UDDDDDDU","LSLLLL","LLLLLLULLLLLL","DDDDDDDDDLLLLL","LLLLLLDDLL","DDDDDDDDS","LLLLLSDDD","LDDLLDDL","ULLULLDD","DLLLLLLDD","ULLLLULLL","LLDLLDDD","UULLLL","ULLLULLLL","LLLLLLSLLL","LLLDDLLLLL","UUDDDDDDDD","LLLLLLU","DDDDDDLLLLLLLLL","ULLLDDDDDDDD","DDLDL","DLLDD","LDLDDL","LDDLDDL","LLLLLLDDDDDDDDDD","LLLLLLSLLLLLL","DDDLD","DDDDDDLD","DDLLLLLDDDD","LDDLDDDD","UUDDDDDDD","DUUUUUUU","LDDL","DDDUUU","ULULLLLL","LDLDLDD","LLLDDDDDDDDDDD","DLLDDLLD","UUUUUUUDDD","LLLDLDD","DDDDLLLDD","LLLLLDDDL","ULLLLLDL","ULULULUL","LLLLLLLDDL","LDDLLLDD","ULLLLLLLLLLD","DDDULLLL","LLLSLL","LLLLLLSL","LLLDDDLLLDDD","LLLDDDLLLL","LLLLDDDLLL","LDLLLDDD","LLLSLLLLL","LLLLDDDDL","LLLLDDDLL","LDDDL","LLLLLLULLLLLLL","DDDDDDDDDDLLLLLL","LLLLLLLSDD","UDDDDU","LLLDLDDD","LLLLLSLLLLLL","LLDDLDD","DLDDL","LDLLLDD","LLLLLLDDLLL","DDLDLLL","DDDDDDDDDDDU","LLDDLDL","DLLDLLD","LDDDDLDDDD","LLLLLLSLLLLL","DDDDDDDDDLLLLLL","UUUUUUUDDDD","ULDDDDD","LLLDLLLDDD","DDLLDDL","ULLLLLDDDDD","LLDDDLLD","UUUULLLL","ULLLLLUU","DDDDDDDLLLLLLL","LLLLDDDLLLL","DLDDLD","DDDDLLDDDD","DDSDDSDD","ULLDLLLL","LDDLDDLD","DDDDDDDDUUU","DLLDDLL","DDDDDDDDDDDDDDDDDD","LLLLLLLLLLLLLLLDDD","ULLLU","LLLLLLDLD","UUDDDDUU","LLLLLDDDDL","LLLLLLLLLLLLLLLDDDD","LLLSDD","LLLLLLSLLLL","LLLLLLLLLDDDDDDD","LSLLLLL","LDDDLD","ULLLLDDDDDDDD","DDDDLLLLLDDDD","DDDDDDDDDU","LLLLSDDDD","LDDLDDLL","ULLLLUDD","LDLLDDDD","ULLULLLD","LLLDDDDDDLLL","LLDDDDDL","ULLDDLLL","DDDLDL","LLLLLSL","LDLLDLD","LDLLDLDD","LDLDLLD","DLDLDD","DDDDLLLLLLLLL","LLLLDDDDLL","LLLDLLLLD","DDLLDLL","DDLLLLLLDDDD","ULLDD","UUUDDDDDDDD","ULULLLL","DDLDDLLL","LDLDLLDD","ULLLULLD","DLLDLLDLL","DDUUUUUU","LDDLLDD","ULULDDDD","LLLLLLLLDLL","LLLLSLL","LLLLDLLLLLL","DDLLLLLLLLLL","LLDLLDLLD","LLLLLSDDDD","LLLLLLLLLDL","DLDLDLDLD","LLLLLSD","LLLLLDDLLLL","DDDDDDDDDDDDLLL","DLDL","LLLLDDLLLLL","LLLLLLLDLLL","LLSLLLLL","DDLLLLLLD","DDLDDDDD","LDDLLLLLL","LLDDDDLLL","DLDDDL","LLLLLDDLLLLL","LLLLLLLLLLLLLLLLLDD","LLLLLLLLLLLDDDDD","LLLLLLLSLLLLLL","LDDLLDL","LLLLLLUU","DULLLLLD","UUUUDDDDDD","DLLD","UUDDD","LLLLLLLDLLLL","LLLLLLLLLDDDDDDDD","LDLLDDL","DDULLLL","ULLLDL","DLLLDLLLDLLL","LLLLDDDDLLL","LDLDLDDD","LLDLDDDD","DLDDD","DDDDDDDDDDU","LLUULL","LLLLLLSDDD","UULLDDDD","LLLLUU","LDLDDLDL","DDDLLLDL","LLLLLLLLSDD","DDDLDLLL","UULLLLL","ULLLLLLLLLLDDDD","DDDDDDDDUL","ULLLDDDLLLL","LLLSDDD","DDLDDLL","DDDSDDD","LLLULL","DDDDUL","DDDDDLLLLLLL","UUUUDUUU","DLDLDLL","LDLDDLDD","LLLLLLLLLLLDDDDDD","DDDDULLLL","ULDLLLLL","DDLDLD","DDDDDDLLLLLLLLLL","DDDDDLDD","DDDLLLLLDD","LDLDLDDL","ULDLDD","LLLLLLDDDL","DLLLLDLLL","LLLUUU","LLLLLDDDLL","DDLLDLLD","DLLLDDDL","DDDDDDDDDDDDLLLL","DLLLDDL","LLDDLDDL","ULLLULLLLL","DLDLLLD","ULLDLL","DLDLLLDD","LSLLLLLL","DLLDDDLL","DLLLLDLLLL","DDDLLDLL","ULLDDDDDDD","LLLLLLLSD","LLLLUL","DLLDLLDD","LLLSLLLLLL","UDLLLL","LLLLLLSLLLLLLL","UUULLLDD","DDLDDLD","LLLLLLLLLLLLLLLLD","DDDDDDDS","LULLLL","LLLLLLSDDDD","DDUUUUU","UDDDDDDDDD","LLSLLLL","DDDDLLLLDD","LLLLLLLSLLLLL","DDDLLLLDD","LDDLLLD","LLLLDLLLD","LLLLULLL","DDULLL","DDSULL","LDDDLLLD","LDDDDLDD","DDDDDDDDDDDDLL","LLLLLLLULLLLL","ULLLLLLLLLDDDD","UUUUUDUU","DDDDDLD","ULLDDDDDDDD","LLLLLLLDDDDDDDDD","ULLLLULLLLL","DDLLLDL","LLLLLSLLLLLLL","UUUDUUUU","DDUUUU","DLLLLLLLLLLL","LDDLD","LLLLLLULLLL","LLDLDLDD","UULLLLDD","ULUL","ULLLLUUU","ULLLDDDDDDD","LDDDLDLL","DLDDLDLL","LDLDDDDD","LLDDDDDDL","ULLLLLUD","DDDDLLLLLLDDDD","UULLLDDD","ULLLLLDDDDDDDD","DLLLDLLLL","LDDLLDLD","DLLLLLLDL","LLDDLLLLLL","DLDDDLLL","LLLLLULL","DDDDDDDUU","DDDLLLDDDLLL","UUDDDUU","LDDLDLDL","LDDDDDLL","DDDDDDDDDDDDDDDDDDDD","UULLUU","LLDDDLDD","UUU","LULULU","UUUDLLLL","UDDDUU","DLLLDDLD","DDLLDLDL","DDDUUUUU","LDLLDDDL","DLDDDDDD","SLLLLL","LLLDLLLLLLL","UDDDDDDDDL","LDLLDDLD","UULLL","LLDDDLDL","LLLLLDLLD","ULLLDLL","DDLDDLDDDDL","LLLLU","UUUUUUDU","ULLLLLULLLL","DDLDDDDL","ULLLLLULLLLL","DLLDDLDL","DLLLLLLLLLD","LLLLLLLSLLLL","UDDDDDDDDDD","ULLLLLULLL","LDDLLDDD","DLLLDLD","DDDDDUU","DDLDDLDDDD","UUUUUUUUUD","DLDLLDL","LLDDDDDDDDLL","LLDLLLLDL","LLLLLLLLLLLLLLLLLLLLLLL","DLLDDLD","DLDDLLL","DLDLDDLL","DDDDULL","LDDDLLDDD","LLDDLDLD","LLLLLLLLLLLLLLLLDDDD","DDLLLLDDD","LDLDDDLL","LLLDDDDLLLL","DLLDLDL","DLDLDLLD","LDLLLLDLL","LLULLLLL","UUUUULLL","UUUUUUUUDDDD","ULLLLDDDDDDD","LDDDDDDDDDL","UDUDUD","DUUUUU","LLLLSLLLLLLL","UDDDD","DLDDLLDL","DDLDLDLL","ULLULULL","DDDLDDL","DLLDLDLD","LLDLDDL","LLULLL","UDLDLDLD","UUULLLL","LLLLLLLULLLLLL","DLDDLLLD","ULLLLDL","LLDDDDDDDDDDD","LLDLDDLD","LLLLLLSLL","DDLDLLDL","DDLLLDLD","DDL","LLDLDLD","LDDDDDDDDDDL","LDDLDLLD","DLLDDDD","DDLDLLLD","ULLDLLL","DLLLDLDD","LDLDD","UDDDDDDDL","LLLLLLDDLLLL","DDDDDUUU","LDDLLLLLLL","UDUDUDUD","DDDLDLL","DLDLLDDL","LLLLLLSLLLLLLLL","DLLDLDDL","ULLULLD","LLLLDLLDD","LDDLDLDD","ULLLLLLLLLLDD","ULLLLLLDDDDDD","ULLLLLLLLLLLLL","ULLSDD","LDDDLDD","UDLLLLL","DLDDDDD","LLLLLLLLLLDDDDDDDD","LUUUUU","DDU","LULULL","LLLLLLLLLLLLLLLLLLLLLLLL","LLLLLLLSLLLLLLL","LDLDDLLD","LLLLLLLSLL","DLDLLDLD","DLDLLLLLL","UUUUUUUUUDD","LDDDLLDL","UUUUUUUUUUUUU","DDUUU","LDLLLLLLD","LDLDDDD","DDDDLLDL","DSDSDDD","DLDDLLD","LLLDDDLLLD","LDDLDDD","LLLLLLLDLD","LLULUL","LLDDLDDD","ULLLLLULL","LLLLDDLLLLDD","LDLDDLL","LLLDDLLDD","DLDLDLDD","LLLLLLLLLSDD","LLDDDDDLL","DDDDDLLD","LLLLLDLDL","LLLLLLDLLLLL","UUDUUUUU","LLLLLLLLSLLLLLL","LLLLLLUUUUUU","SSSSSS","LLLLLLLLLLLLDDDDDD","DDULL","LLLLLLLLLLSLLLLL","DDDDDS","LLDLDDD","DLLLLLDLL","ULLLLUD","DUUUU","LLLLLLLLSL","DLDDLDDL","LLLLLLLLLLLSLLLL","LLLLLDDDLLL","ULDLLL","ULLLLLLULLLL","UUUDDDDDDD","ULLLULLU","UULLLU","ULLLULUL","LDDLDLL","DUUUUUU","DDDDLDDDDL","LLLLLLLLSLLLLL","DDDLLDL","LLLLLLLLLDLL","ULLLLLLDDDDD","LLLLLLLSLLL","LLLLLLLLLSLLL","UDUUUUUU","LDLDLLLLL","DDDDDDUUUU","DULLLULL","DDDDDDULLL","LLDLLLLLLLL","ULLULLUL","LLDDLLLDD","LLLLUD","UUUD","ULLDDULL","ULLLLLLLLLDDD","LLLLLLDDDDL","DDDDDDDLLLLLLLL","UULLLLLD","LDLLDLLLL","LLLULLLL","LLDLLLLDLL","DDLDDLDDLDDL","LLLLLSLLLLLLLL","LDLLDDD","ULULU","LULLUL","LLLULU","LLLLLLLLLLLSLLLLL","DDDDDDLU","UULUUL","LLDDLLDDLLDD","LLLLLLLSL","DDLDDLDL","LLLLLLUD","UUUUUULL","UDDDUDDD","LLLDDDLLLLLL","ULLLUD","ULLLDDLL","LDDDDDDDDDDDD","UDDDDDDDDDDD","ULULL","ULLLLDDL","DDLLDDDL","DDDDLDDL","SLLLLLL","LLLLLLLDDLL","DDDDLLLLLDD","ULULULU","SLLLLLLL","LLLLDLLDL","UUDDUU","DDLLLLLLLLLDD","UUUULU","UUUDDUUU","UUULUU","LLUULU","DLLDLLLLL","LLUUUU","ULLULULU","ULUUUULL","DDLDDDLL","LLDLLLLLD","ULLLDULL","DDDDLLLLLLLLLL","ULLULLLU","LLLLLLLLLLSLLLL","DULLLLLLL","ULLUDDDD","LLLLLDDDDLLLLL","LLLLDDDDDDDDDDDD","DDDDU","DDDULL","DDULLLDD","LLLLLLLLSLLLL","LLDLDDDL","LLLDLDLLL","LLLLLLLSDDDD","LLDDDLD","UUUUDDDDD","DSDSDSDDD","DDDDULLLLL","DDLDDLLD","LLLLLLLULLLLLLL","ULLULLLLL","ULULLLUL","LDLLLLLLLLL","UUUULL","LLLDLLDLL","LDLLLLLDL","ULULULLL","DDDLLLLLLLDDD","DDUUUDD","LLLLLLLLULLLLL","LDDLDDLDDLDD","ULLUULLU","DLLLLLLU","ULULLLLU","LDDLDLD","LLLUDD","UULULL","LLLLLLLLLLLLLLLLDDD","UUUUUDDDDDD","LLDLLLDLL","DDDLDDLL","DDDUUUU","LDDDLLD","LLLLLLULLLLLLLL","DDDDDDULL","LLLLLLLLSLLL","UUUUUUUUDDD","LDLDDLD","ULLLUULL","ULULLULL","LLLLLLLLDLLL","LLLLLLLLLLSLLL","LLLLLLLDDLLL","DDDDDDDDDDS","LLLLLLLLLLLLDDDDD","UDDDDDDDDU","LLLLLLLLLLDL","ULLLLULU","LLUUUL","DUUUUUUD","LUULUU","LLLLLLLLLLLSLLL","ULULUUUL","LLLLLLLLLLLLSLLL","LDDDDDDLL","UUULLLDDD","ULLLULLLLLL","DDLLDDLD","ULULLULU","LLLLLLLSDDD","LLLLLLLLLSLLLL","DDLLDLD","ULLUL","LLLLLLLLLLLLLLLLLLDD","LLLLLLLLLSLLLLLL","DUDLUDUL","DLLLLDDDD","DDLDLLDD","UUULUL","LLLLLLLLDDL","LLLLLLLLLSLLLLL","ULLUUUUU","SSSSS","UULLLULL","DLDLLDDD","ULLULLUU","ULULUULU","LULUUU","LLLLLLLLSLLLLLLL","LLLLLLLSLLLLLLLL","LLLLLUUU","LLLDDLLLLLL","ULLLLUL","DDUUUUDD","DDLDDDL","LDDLDDLDDDD","LLLLUUUU","UULLLLLU","LLLULLL","ULULLLUU","ULLUULLL","DDDDDDDDDDDDDDL","LUULLU","LLLDLLLLLD","LLDDLLDDLL","LDDLDDLDDL","LLDDDLLLL","LLLDLLLDL","LUUULL","LUULLL","DLLDLDD","UULLUUUL","ULULLUUL","LDLDLDLDLDL","DDLDLDDL","ULUUULLL","UULLULLL","ULLLUUUU","DDUU","LLLDDDLLLLL","LLLLLLUUUUUUU","UUUDUUU","LLULUU","LLLLLLLLLLLSDD","ULLLLUUL","ULUULULU","LLLUUL","LLLLLDLLLLLL","LULLLLLL","UUDUUU","DDDDLDLL","LLSLLLLLL","LLLLDDDLLLLDDD","UUUULULL","UUULLUUL","LLLLLLLLLLLLSLLLLL","LULLL","DDDLLLDDDD","DDDDDDDDUUUU","LLLLDLDLL","LSLLL","DLDLDDDL","LDDDLLLLL","LDDDDDDDDDDDL","UULLLLUL","UULUUU","UUULLLLU","UULULU","ULUULULL","UUUUULUU","UUUDU","ULUULUUL","UUULLULL","ULLUUULU","ULULULLU","UULLLLUU","UUDUU","DULULLLL","UULLLUUU","DDDDLDL","ULLLULUU","UUULLLLD","LLLLLLLDLLLLLL","LLLLLLLLDLLLLLL","DDDLDLLD","DDLLLLLLLD","LLLLLLLLSLLLLLLLL","LLDLLDLLL","UUULULLL","LLLLLLDDDLLL","LLLDLLLDD","UUULUULL","ULLUULUL","UULUUULL","UULLULLU","LSLLLLLLL","LLLLSLLLLLLLL","DLLLLLDLLL","LDDDLLDDLLL","LLLSLLLLLLL","LDLLLDLLL","DLLLDLLLLL","LLLLSD","LLLLLDDDDLL","LLDDDLLDDD","LLLLLLDLDL","ULDDLLLL","LLLLDDLLLLLL","LLDLLLLLDL","UDDUDD","DDLLDLDD","LLLLLLDDS","UUUDDLLL","ULUULUUU","DLLDDDDD","DDUUDD","UULLULUU","DDLUL","DDDDDDDDDDDLLLLLL","LUUULU","DULLU","DULUL","LLLLLLLLDLLLL","LLLDDLLLD","DDDDDDDDULLL","DDDULLL","DDDDDDUD","UULULLLL","ULLLLLLLU","ULLULUUL","ULLUUULL","LLLUUD","LLLLLLDLLD","LLLLLLDDDLL","UUUUUUUUUUUUUU","LDDDLDDL","UDDLLLLL","UULLLUUL","DDDLLDDDD","DDUUL","ULULDD","UULULULU","UDUUU","DDLLLLLLLDDDD","ULUUUUUL","DLDDLLDD","LSLLDDDD","DDDDDDDDDDDDDDDDD","LLULL","DULLULLL","LULLLU","LLLLLLLLLLLSLLLLLL","LLLLLLLULLLL","UUUUUL","ULDDLL","DLLLLLLLDD","UULLUULU","UDDDUUDD","LLLLLLLLULLLLLL","DLDDLDL","UUUUUUDDDDDD","DDLLU","DDDLLLLLLLLLL","ULLLLSDD","LLLLLLLLU","LLLLLLLLLLLLLLLLLD","DDDDDDDDDDDS","UUULLULU","LLLLDLLLLLLL","DDDLLDDL","DDDDDDULLLL","LLDLLLDLLL","DLDLDDD","LLLLLLLLSD","UUUUUUUL","DDDDDLDL","LLLUL","UUUUUULU","DULLLLUL","LLLLLUDD","LSLLLLLLLL","DLDLLDD","ULLLLLDDDDDDD","UUULULUL","LLUUL","UULULLUL","LLUUUD","UUUULUUL","ULLDULLL","ULDDDDDDDDD","DDLLDDLLDD","ULLUULUU","ULUULLUL","ULUUULLU","UUULUUUU","UUUUDU","DDDDLLLLD","UULUUUUU","ULULULUU","DLDLDDL","LLLLLLULLLLDD","ULULULDD","DDDLLLLLLLLDDD","DDUULLLL","ULLLULLLDD","LLLLLDLLLLLD","ULLLUUUL","DDLDLDD","ULUULLUU","DLLUL","UUULLLUU","DDDDSDD","DDLLDDDDDD","DDDDDDLLLLDD","LLLLLLLLLLSLLLLLL","UUULLLUL","DDDDDDDUL","UUULULUU","LLLLLDDDDLLL","DLLUU","DLLLLLLLLLLD","ULLLLLSD","LLLLLLLLLLLLSLLLL","UDDDDUDD","LLLLLLLLULLLLLLL","DDLDLLD","DDDDLLLDDD","UUUDUU","ULULUULL","DDDUU","LLLLLLLDLLLLLLL","LUULUL","UULLUUUU","DDDDDDLLLLLDD","DLLULLLL","DDLDLDLD","DDDLDDLD","ULLLULDD","ULDLLLL","DDDDUDDD","LDDLDDDL","DDLDLDL","ULLLLLSDD","UDDDDDU","ULULLUUU","LDLDLDLDLDLDLD","LLLLLLLLLLLLSDD","DLLLDLLLD","DLDDDLDD","ULUUUULU","UUUUDDDDDDDD","UUUUUDDDDD","DUUULLLL","ULLULUUU","LDLLLLDLLL","LLLLLLLLLLLDDDDDDDD","ULLLLULLLLLL","LLULU","DLUULLUL","LLLLLLULLLLLDD","UUUUULUL","ULLLUDDD","LLLLDLDLLL","DDUDDUDD","DULLLULU","DLLLLLDDDD","LLLLLDDDDLLLL","UUULL","DLLDDLDD","UUULUULU","DDDDDDDDDDDDDL","ULLLUULU","UULUULLU","DUULLUUL","ULLLLLLLDDDDDD","ULUULLLU","DLLULULL","LUULL","DLDDDLLD","LLLLLLLLLLSDD","DDLU","DULULUUL","DLDDLDD","UULLULUL","DDLDDDLD","LLLLDDDDUU","DLULU","ULUUUUUU","LLLLLLLLDDLL","LLLLDLLLDL","DDUL","ULULUUUU","ULUULLLL","UDDUDDUDD","LLDDDDLD","LLULLU","UDUUUU","UUUULLUU","LLLLLLDDDDLLLLLL","DDDLDLDL","ULUUULUL","UUULULLU","UUDDUUDD","ULLLLLDDS","DLLDDDL","DDDDDDLLLLLLDD","UULUULLL","UULULULL","DLLLULLU","ULULLLLD","DULLLLLU","LLDLDLLLL","DLDDDDL","ULULUD","UUUULLLU","UUUULLUL","UUULLUUU","DUUULLUL","DUUULULU","UULLUULL","DDDDDDLDD","DDDDUUUUU","DDDLLLLLD","LLLLLLUL","DLLLLLLLDL","LLDLLLLDD","DULULLLU","DDDDLLDDD","UULUUUUL","DULULULU","DDDDLLLLLLLDDDD","LLDLLLLLLD","LLLLLDLDD","UULULLLU","LLLDDDDLLLLLL","LLLLLLDDDDDDDDDDD","DLDLDDDD","LLLLLLLLLLLLLLLLLDDDD","DDDDLDLD","LLDDDDLLLL","LLLLLLLDDDL","DDLD","LLLUU","DDDLDLD","DDULU","DUULLLUL","UUUUULLU","DLLDLDDD","DDLDLDDD","ULLUUUUL","DLLUUULU","ULLU","DUULLLLL","UULUULUL","UULULLUU","LLLLDU","DLLUULUU","DDDDDDDDDLLLLLLL","DLLLLLUU","ULUUULUU","DDDDDDDUUU","ULDDD","LLUUU","DLDLDLDLDLD","DDLLLDDLL","LLDDDDDDDLL","DDDLLDLD","ULLDULLD","DLLLULLL","UULLLULU","DULULULL","UULUULUU","DDLLLLLDDD","DULULLUL","UDDUDDDD","UUUULULU","DDDDLLLLLLDD","DUULU","DLLLLULU","DDULLLLLL","DLLLULUU","DDDUDDDD","LLLLLDLLDL","UUDDDDLL","DLDLLLLLLL","DDLLLDDLLL","LLLLLSLLLLLLLLL","LLLLLLLLLLLLSLLLLLL","ULLLUDD","LLLDULLL","DUUUL","DDDDDDSS","UULULUUL","LLLDDDDDDDDLLL","DUULLLLU","LLDLLDLLLL","DUULLULU","LLLLLUU","DDLDDDDDD","DUUULLUU","DDLUU","LLLLDLLDLL","DLDDDLL","UUUULUUU","LLDLDLLLLL","DLLLU","LLLLLLLDLLLLLLLL","LLLLLDLLLD","LLULLD","LDLLLLDDL","DDDLDLDD","UUULLU","DDDDDDDDDS","DUULULUU","UDDUDDD","ULLLUUU","DLULUUUL","UDDDDL","DUUUULLU","LLLLLLLLLDDL","LLLLLLLLLLSLLLLLLL","LLLUUUDD","LDLLLDLLLL","DLDDDLD","LDDDDLD","DULUUULL","DLLUUULL","DULUULLU","UULUUULU","LLLLLDDS","ULLLLLDDDLLLL","ULLDL","UULLLD","LLLDDDDLLLLL","DULLLUUL","LLLDLLDLLL","DUULULLL","UULLUL","DDDDLLLLLLLLLLL","ULLLLLLDDDDDDDD","ULLLLUU","DLUUULUL","DULUULLL","DDDDDDDLDD","DLLULLLU","ULLLLULD","ULLDLLLD","DULLULUL","DLLDDDDL","LUUUUL","DUULD","DLUUUULL","DUUULLLU","LLLLLLLLLLLLLSLLLLL","LUUUU","UULLLDD","DDULLLLDD","DLLULL","UULLDD","DSULL","DLLLUULL","UULULUUU","ULUUL","DUUUULUU","DLULLULL","UDLLLLLD","DDLDLLLLL","UULUL","ULLLLLLULLL","LLLLLLDS","UDDDDDDDU","LLLLLLLLLDLLL","DLLUULLL","LLLDDDDDDDDDDDD","DLLLLLDDD","DDDDDDDDDDDDDDDL","ULUDDD","DULLUULL","LLLLLUD","ULLLLLLLLLLLLLL","LDDDLDLD","UUUUDUU","UDDDDDUD","DLULLLLU","LLLDLLDDD","LLLLLLLLLLLLLLLLLDDD","ULDDDDLL","DULLUULU","DUUUULUL","LDLLLLLLLD","LLDLLDDDD","DDLLDDLLDDLL","DLULULLL","DULUULUL","DULLLU","DLLLULUL","DUULLLUU","LULLUU","DUULLULL","DLDDDDLL","LLSLLLLLLL","DDDDDDULLLLL","ULLULLLLLL","DULUU","DULLULLU","LDDDDLLD","ULULLLDD","DLLLLLUL","DUDUDUDU","LLLLLLDLLLLLL","ULDDULDD","DULLUUUL","LLLLLDDDLLLL","ULDULL","LLLLLDDDLLLLL","DLLLUUUU","LUDDDDDD","ULDULD","UDLLLLDD","ULLLDLLLL","DUUULUUU","ULLD","UUUDUUUD","ULLLLLLS","DUULULUL","DUULUUUL","UDDUDDUD","DLDDDLDL","UUUUUUUUUDDD","LLDDDDDDLLL","DLDDLDDD","LLLLLLLLLLS","DDULLDD","DULULLUU","DUULULLU","UUDDUUUU","LLLLLLLLLLLDL","DDDDDDLLLLLLLLLLL","ULLLLUUD","DLDLLLLLD","UUUDDDU","DULUULUU","LLLLLLLLLLLLLDDDDDD","ULLLULLLD","DLLUULLU","LULUUL","DUUULUUL","UUUDDUU","LLLDLLLDLL","DUUUUUUL","DUULL","LDDLLLDDL","DDLLLLLLLLLLL","UUUUDDUU","DDDDDDDDLLLLLLLLL","ULLUU","LLLLULLD","UUUDDDDU","LLLLLLLLLSLL","DDSDDSDDDDS","DLLUUUUL","UULUU","DLUUULLL","LLLLLLLLDLLLLLLL","DULULUUU","DLLDDDLD","DLUUULUU","DDDDDDLLD","DULULU","ULL","ULUUU","ULLDDLL","DULUUULU","DUUUUULU","UUUUUDDU","LLLLULL","LLLLDDDDDDLLLL","UUDD","DUULUULL","UUUUL","DLLLDDLLL","LLLLLLLLLLLLLDDDDD","ULULLLD","ULLLLLDLL","DDDDDUDD","LLLLLLDDDDLLL","DLULLLLL","DLUULULL","ULLLLLLLLLLLDD","DULLLUUU","LLLDLDLLLL","LLLLLDLLDD","ULLLLLLDS","DULLLLD","LUUUUUUU","ULLLLLLLLLLDDD","ULLUDD","ULLLLLLLLLLLD","LLLLUULL","DLULUULU","DDDDSDDDD","DDDUUDDD","LLLLLLLLLLLLLSLLLL","DLLLLUUU","DLLULLUU","DUUUULLL","DUULUULU","LLDDDLLLLL","LLLDDDLLLLLLLL","DDDDDDLLLDD","DUUULULL","DLDULU","DLUUULLU","DULLUUUU","DUUDU","LLLLLLLLLLLLSLLLLLLL","LULULULU","LLLLLDDLD","DLUULLLL","DDDDUUDD","LLLLLLLLLLSLL","LULLU","DLLULLUL","DULUUUUL","DDSDDSDDS","ULLLLLULLLLLDDDD","ULULUDDD","ULLLLLUDD","LDLDDDL","DUULUUUU","LLLDDDDDDDLLL","LLLLLLLLLLLLDDDDDDDD","DLDDLDLD","LLLDDDDDLLL","DUULLUUU","UDUDDDDD","LUUUL","LLLLUDDD","DULUUUUU","ULUDDDD","LDLLDLLDL","UUULUUUL","DLDD","LULUULUL","LULUL","DUDUUUUU","DLLLLULL","LLLLLLDDLLLLLL","DDDUDDD","DLLLLLLDLL","LLLLLLLLLLLLDL","LUUULLUU","DDLLLLLLLLLLDD","LLLLLLLLLSLLLLLLL","UDDDDDUU","LLLLDLLDDDD","DULLULUU","LLLLLLSS","DULLLLUU","LLLLDDDLLLLL","DLUULUUU","LLLLLLLLLLLSLLLLLLL","UDLDLD","DUDDDDDD","UUUDDDLL","LDLLDLLLLL","LLLDDDLLLLLLL","LDLDLLLLLL","DLULLLUU","LLLLSS","LLLLLLLLSDDD","UUUUUUUUUUUUUUU","LLLLLLDDLLLLL","UUDUUUU","DLULLUUU","LLLDLLDDDD","SLLLLLS","ULULULUD","LLLLLLDDDDLL","DDDDLLLLDDD","LLLLUUU","UUUDULLL","DULULL","LLLLLLLDLLLLL","LLLUULLL","LLLLLLULLLLLLLLL","LLLLLLLLSLL","UUUUUUUUUUDD","LLLULLLD","LDLDDDDL","LLUUUULL","ULLDDDLL","LDLDLDLLL","LLLLLLLLLDLLLL","ULULDDD","LLLLLDLDLL","LLLLLLLLLLDLLLL","UDDUDDU","DLLUUL","ULLLULLLLLLL","DDDDDULL","LLLLLLLLLLLLLSDD","DLLLLUUL","LUULU","DLUUUUUL","DDDULLLLL","LLLLLLLLDDDL","DUUUUULL","DLUUL","LLLLLLUUUUUUUU","LLDDLLDDD","ULDDDDDDDDDD","LLLLLLDU","DLULUULL","DDDUL","SLLLLLLLL","LLUUUUUU","DLUULLUU","LLLLLLSLLLLLLLLL","LLSLLLLLLLL","UUUDDDLD","LLLSLLLLLLLL","LLLLSLLLLLLLLL","DDUDDDDD","DLLDLLLLLL","LULLLLLLDD","DDLLDDLLL","LDDLLLLDL","LLLLLLLDDDLL","DLLUUUUU","LLLDLLLLDL","ULLLLDLD","DLLLUULU","LLLLDDDU","LLLLLLLLLSD","DLUUUULU","DLLLLDDLL","LULLLLLU","DLLUULUL","UULLU","LLLLLLLLLLLSL","LDLDLDLDLDLDLDLD","DLLLUL","ULUUUD","DLDDDDDL","ULLLDLLD","LLLDLLLDLLLD","DLDLDDLD","LLLDDDDLLLLLLLL","LLLLLDDU","LLLLLLLLSDDDD","LLDDLLLLD","DLULLULU","LLLULLLU","LLLU","ULLLLLDS","LLLLLLLLDLLLLLLLL","UULLLLD","DLDUU","DLULUUUU","UUDDDDDU","LLULUD","LLLLLLULLLDD","LDLLLLLDLL","UUUULLLD","LLLLLLLLLLLLLLLLLLD","DDUDDU","DUUUUD","DLLULUUU","DDUDDDD","LSSL","UULDUU","LLDDDDLLDDDD","UDDDDUU","DDDDDDDDULLLL","UUUUDDDDDDD","LLULLLLU","DLULLUUL","USLLLLLDDDD","LLLLLLLDS","LLLLLLLLDLLLLL","LLLLLLLLLLDLL","ULLLLLLLDDDDD","LLLLLLLLLLSL","LDDDDLDL","UUUULLL","LLLSL","LLLLDDDDDDDDLLLL","ULLLLLS","ULLLLDUL","DDDUDDDU","LLUDLU","UUUDUDD","DDDDLLLLLLLLDDDD","DDLLLLLU","DLLLLLLLLLLLL","LUULLLUU","LLULLLL","UUULU","UUDDUUU","LLLDDDDLLLLLLL","DDDLLLLLLDD","LLLDLLLLDD","DULLD","DLULLL","DUUUDUUU","LLDLLLDDDD","LLLLLLLLLLLLLLLLLLLDD","LLLLLLLDDDDDDDDDD","LDLLLLLDD","LLUULLLL","UUULLLD","UUUUUDDDDDDDD","LDLDLDLDLL","DDDDDDUUUUU","DDDDDDDLD","UDLLL","UUDDLLLL","UUDDDDU","LULLLULL","DDDDDDDLU","DLULLU","LLLLLLLLDDLLL","LLLLULUU","DLULLLUL","LLLDDLLLLD","DLULL","DLDLDLDLL","LLLLLLLLLLLLLLLLLLLLLLLLLL","DULDL","ULLLUDDDD","ULLLDU","DDDLLLLDDDD","DULUUU","DDDUUUDD","ULLLLDDU","SDDDDDDS","LLLUD","DUULLU","DLLULUUL","LDDDDLLLL","LLLLLLLUUUUUU","LLLLLLLLLLDLLL","LDDDDDLD","LDLLLLLLDL","DULLUL","UDULLLLL","DDUDD","DLUULUUL","LLLLDDDDU","DUUUUDUU","LLLLDDDDLLLLL","LLLUUULL","LLLLLLLLULLLL","DUUDUUUU","LDDDLDDDD","LLLLLLLLLLLSLL","ULDLLLLU","DLUULULU","LDDDLDL","ULLLLLDU","LUUUUULL","LLDULL","LLLLULLLL"],L.blacklistedSubstrings=["12345678","password","23456789","11198","land","blue","04199","07199","02199","06199","08199","angel","10199","09199","12199","11199","01197","05197","07197","a199","04197","03197","10197","08197","123123","12197","06197","master","dragon","09197","fish","02197","black","11197","a200","2112","fire","mike","baby","pussy","line","test","mark","cher","wood","mama","bear","cool","ling","anne","fred","illa","a198","anti","alle","marc","monkey","life","man1","dick","ness","good","daniel","sexy","o123","time","assi","gold","shan","shadow","rain","ters","alli","ford","play","mont","anta","mine","qazwsx","ache","stra","erry","michael","dima","green","sher","nick","shar","wolf","ring","killer","suck","tina","robert","01196","even","elin","aris","2211","dark","bird","jordan","paul","1108","scar","ones","lock","123321","0909","arri","mustang","rose","shit","asta","money","121212","0505","arch","03196","football","stro","hill","01019","letmein","dman","chin","10219","04196","05196","amil","pant","baseball","porn","david","james","onic","eron","10419","mini","stal","ison","abc123","lover","ander","alen","30319","t123","erin","ina1","vers","0303","ings","martin","mega","olly","ante","hello","11119","0108","90519","00119","08196","21219","shka","10196","hunter","30119","40419","00319","30219","02196","yboy","666666","10619","1102","vlad","70719","pers","1211","nova","12196","10919","anni","sara","lian","010119","07196","30419","0707","elli","oker","50219","er123","atch","00519","00419","rest","06196","50319","side","na19","60619","1107","50419","1210","00619","50819","80319","11196","90919","1109","tran","arma","anton","30519","50719","andrew","l123","09196","50119","31019","enny","0808","40219","90619","01119","80219","34567890","fuckyou","70219","00719","40519","anch","sweet","30719","80519","51219","40619","80419","soccer","21119","2108","00819","70419","60319","1204","60519","80819","1205","1002","elly","race","00919","7777777","60219","stic","steve","40319","70519","west","41019","90419","30619","thomas","01219","51019","boob","tche","30819","less","assa","60719","allo","ital","poli","light","50919","lion","30919","50619","90319","70319","2109","80119","ment","70919","70119","60419","60119","40719","40819","81219","80719","0404","70819","1208","0112","31219","0107","asti","90119","harley","each","70619","40119","51119","0304","80619","90719","bone","well","41219","0606","80919","71019","10101","1206","phil","0105","brand","1209","61219","1202","90819","1105","696969","71119","lick","ista","11111111","91019","lisa","more","0110","1005","123qwe","91219","1106","alis","60819","0106","60919","1000","41119","stre","arry","1207","llin","1007","charlie","enko","40919","1203","1004","k123","1110","31119","71219","long","61019","buster","apple","1003","wing","91119","ivan","1123","reat","1103","81019","61119","tori","0506","batman","stri","2212","anov","sion","2107","leon","1104","81119","isha","2102","a197","power","summer","superman","anya","qwertyui","sing","3108","pepper","1312","2311","george","ence","nker","lore","2110","tech","alan","3112","87654321","1006","card","2106","1008","part","ryan","ross","123a","liver","amin","gran","1402","cock","aron","william","ssie","gene","2512","2301","01200","elan","ipper","ding","para","rish","maria","nson","dave","frank","sasha","1311","2103","moon","rill","buck","tigger","amel","mara","hand","2105","1812","ollo","2309","roni","kate","1512","happy","2525","2505","0405","1301","21985","redd","2202","arth","terr","iloveyou","hockey","2310","mper","2501","2210","3012","per1","2206","adam","3107","abri","tron","emen","0123","olli","11991","isto","game","cent","1009","3110","2305","achi","arta","emin","21990","1310","ladi","hawk","gfhjkm","moni","21989","gate","ines","ing1","lone","llen","ania","elis","mary","alina","2412","ardo","tall","itte","crea","mani","2204","indi","dogg","1478","shel","0502","0305","tree","ning","ation","peter","real","scott","miss","ucki","sant","slav","liza","erna","3010","olle","2510","oria","enne","meli","asca","0308","0708","chie","access","1510","reds","bass","justin","esse","sche","1305","0508","roll","1412","jxrf","2511","sman","2104","1504","0905","niko","hammer","arre","ender","2303","erto","0507","hall","1410","2207","2410","1502","1501","svet","sama","2203","1303","ingo","bitch","1308","2205","1503","esta","0501","1511","98765432","1404","222222","112233","2503","ress","m123","2504","0212","pres","2304","f123","ming","lucky","lass","fuckme","jessica","1307","1306","lash","1302","0211","an19","tlan","jennifer","1405","link","acker","2306","0306","ener","harr","0301","0503","0302","marl","1235","0509","0809","wild","1612","21984","lori","1411","2411","cola","ger1","andrea","1221","21992","0310","avis","0803","snow","came","3003","1507","illo","mist","sandr","cand","rate","1711","silver","hant","1508","daddy","3001","franc","unny","90219","taylor","1304","2401","ashi","3004","freedom","1704","3105","dead","2208","2509","0607","amanda","0307","joshua","11984","1805","arie","asse","1403","trin","2209","1705","yman","rett","kell","jeff","0609","inst","2502","stas","matthew","lanc","0608","2507","alia","1605","0406","alie","2404","tana","bble","ngle","21991","1801","2307","face","stone","1611","1309","1408","2606","hone","1401","mash","anas","mann","aren","wertyuio","son1","2508","8888888","00219","3006","0504","nicole","1712","1213","1707","poop","1407","asper","3103","dallas","erri","dream","denis","teri","2805","mina","ader","diamond","ride","eral","asshole","0912","ashley","team","cheese","bobb","2506","1406","1710","11983","thunder","ister","hero","roman","er19","2405","chen","3005","21983","n200","ginger","serge","0908","2707","kiss","1811","1604","2406","smoke","0309","lord","maggie","trustno1","2611","1509","mila","wall","2601","s200","pack","1802","arme","trac","1703","2909","0311","44444","orne","2812","1606","arne","i123","dude","2711","cookie","1702","2308","kara","0512","sere","1706","sunshine","holl","tell","1601","2403","101198","1803","ertyuiop","wind","2801","1610","2802","1603","2701","ers1","anny","2612","21982","ound","radi","1506","nman","0407","arro","0408","0510","stat","mail","11992","1804","0807","2808","1602","1810","east","2703","2811","nika","enda","astr","barb","victor","osto","abel","2710","2905","ember","0709","1806","ckle","0711","1409","2901","0312","1808","ker1","2605","rena","arke","olga","n199","colo","0410","ckie","rach","2904","2603","0403","dina","2704","2803","alon","corn","2712","ally","papa","0906","anthony","otte","icks","rona","0704","2804","audi","2810","0702","2602","iner","cart","2604","11982","reak","2702","russ","bron","tain","0605","0910","hbyf","1709","pimp","bond","03200","ristin","1608","0602","devil","2903","shot","phan","08200","etro","2610","05200","1230","lant","2402","house","aran","ana1","enter","mali","slan","2408","2407","01195","erse","ardi","159753","gust","cali","kova","azer","e200","1222","chil","andra","2705","0610","chelsea","princess","0902","1809","ermi","2607","ango","oose","0710","3007","hack","atan","0402","11980","0511","04200","adri","0401","on12","nokia","lady","0805","onde","0601","0412","z123","essa","0603","0810","plan","0411","michelle","maks","inde","2906","blow","nasty","0701","computer","aine","mira","ucks","core","2912","qwerty1","2409","1708","lson","aint","0812","0911","2709","1609","toni","iron","eave","1088","ture","oner","some","0705","tere","onta","skin","vent","3009","fast","merlin","4123","1807","0706","0802","0901","1607","2910","0806","0904","11981","atur","02200","09200","2911","tten","elena","0612","white","manu","zxcvbnm","yankees","0604","blin","ammy","2907","samm","0001","nica","acha","2609","starwars","oleg","1018","2807","0801","alls","water","12200","guitar","boom","tara","0409","0611","0804","mate","2809","nell","rton","boot","ffff","vill","2708","bles","maxim","ster1","3008","eeee","0907","flor","riel","rebe","maha","lton","2468","berg","0712","2806","chicken","tony","jackson","tick","cham","igma","avel","anut","ales","lane","ichi","2608","nche","welcome","0903","2706","ckers","lari","onne","inka","apri","kari","dann","07200","adis","10200","call","pion","london","pink","ddie","0703","erson","sport","eren","peac","1qaz2wsx","11200","1029","03195","beer","lala","sssss","metal","opper","ydog","brown","carol","buff","r200","amor","ennis","cros","brad","2424","init","anes","frog","esto","06200","igor","fant","21993","12011","13579","ncc1701","cast","eddy","rush","n198","rris","stel","05195","kins","11993","enta","0000000","magic","kman","vert","10195","2908","4789","ease","tera","arsenal","0811","them","erre","rter","1100","21980","5150","rome","6123","sham","1194","lman","bigdog","brian","uffy","jake","greg","poll","moto","aser","21981","rando","rash","8963","ooke","sparky","oger","jason","wwww","golfer","jane","arat","eagles","rado","ping","scooter","assword1","medi","lera","poke","nett","arge","sten","high","cont","ddog","user","ambo","anim","phoenix","3344","nity","mars","oren","ashe","octo","orma","work","stud","conn","2369","coll","der1","spider","7896","onte","y200","teen","elvi","sting","hanna","lips","rida","marina","yama","term","tigers","kenn","brit","10203","anad","ooper","08195","atte","bast","vika","billy","ferrari","ishi","kkkk","river","tttt","llar","lakers","rend","04195","11195","able","rita","trip","nice","ilan","barn","seve","usty","bbie","boss","dash","iris","itan","sana","cass","ka19","nina","feli","soni","anil","ussi","aram","ampi","ablo","olla","ton1","toma","gman","rama","02195","spri","isco","rack","mers","admi","lade","olan","333333","inal","tani","1089","1078","lana","temp","lly1","unner","09195","adin","12195","9090","rent","man2","honda","tany","na12","131313","4545","jami","nake","r1234","ples","acki","vova","back","ghbdtn","g123","hema","estr","onald","stia","5252","book","cccc","dale","secret","1515","anis","mana","anal","rell","rion","1415","corvette","emil","madd","tink","icky","h123","103198","tine","surf","ssan","bang","speed","1128","onnie","bubba","23232","best","iant","lter","hhhh","nathan","gent","gina","vera","eart","riss","apol","marine","llis","ager","9999999","spec","renc","q1w2e3r4","lley","llll","07195","arad","mous","iann","rola","iter","aper","fylh","slayer","anet","erpo","trav","carlo","rrrr","orange","lent","herm","spir","cana","1232","kola","adim","01010","alexand","1414","ass1","alic","mish","a196","mily","drum","ter2","smith","11979","tits","asia","acka","21994","dger","r199","moll","ores","egor","ishe","x123","tyle","rangers","osta","alpha","haha","jesus","wer1","herr","nders","020219","clar","buddy","olas","tian","lovem","vfvf","rney","ley1","mans","oopy","rami","orth","lice","ttie","mero","babe","o200","carr","barr","lder","brook","klas","nikita","acer","anic","2334","21978","open","er20","er11","ina2","cowboys","mano","an123","read","anit","bara","rsch","iber","ties","gian","field","obby","q123","outh","ilia","anci","anga","na20","32323","down","ravi","ktor","llan","ine1","bren","112198","amat","21979","beat","3141","ndia","11978","solo","road","alma","amma","steph","internet","nich","bbbbb","nite","vita","arde","form","rans","ndro","austin","enna","mall","bloo","ants","107198","endo","1087","valer","icia","mack","ommy","anana","erbo","simp","dent","arty","1191","mach","asha1","cris","appe","simon","nard","alker","lovel","arga","icker","06195","mela","music","teme","bigg","chik","ler1","bite","rocke","nkin","ver1","lica","domin","geni","105198","aska","izard","coco","banan","tomm","11994","tasha","gang","anka","pook","petr","101199","stya","oone","illie","inner","adma","icho","iman","donn","0100","5123","inky","etta","123654","gand","tewa","9632","slut","maverick","lama","amber","mala","ksan","mona","mino","ddddd","bart","8097","eres","lolo","qazxsw","arks","olina","scha","brie","8098","ugar","richard","here","ntan","hamp","ysta","marg","mmmmm","01020","crazy","oles","soft","wins","drey","ney1","pire","gera","3000","serv","eddi","mercedes","alte","1321","dust","020319","020419","spank","unda","1017","qweasd","erbe","yfcn","magn","shor","horse","aaaaaaa","bern","reme","lett","snoop","artem","egas","guar","plat","bandit","nsta","2580","rdon","s199","108198","dona","horny","asil","ordo","nny1","1472","hear","walk","abbi","otto","baba","8912","ickl","boog","inha","erica","ical","1028","10120","1098","kota","ican","dest","harm","raci","onco","rice","evel","789456","qwas","post","tard","atar","unch","aleks","arah","hers","whatever","amba","guin","ellow","mode","1q2w3e","doug","natas","ffin","8050","tele","winn","1593","202198","burn","a111","steelers","lvin","nada","veta","erti","nna1","madi","ulle","zzzzzz","ena1","duck","4242","indo","oron","matrix","fhby","11995","020819","9119","andal","hoot","eway","abcde","deli","chas","issi","pand","iden","orte","list","rost","laster","punk","nior","heri","polo","nand","kitty","butter","rini","cking","110198","yana","olive","start","linda","1090","pala","051987","21977","1717","chuc","rule","020519","nima","entr","ailey","ador","haro","turn","eder","atti","brea","koff","hans","vero","mati","julia","arce","izza","7891","fucker","011990","orri","erik","leas","mother","natali","thead","arco","rant","erta","b123","020119","gator","heel","ard1","grea","anat","mer1","vfrc","020619","olden","ick1","help","bbit","mera","akot","pool","erst","erni","8951","inch","lame","nchi","death","5555555","1058","kati","011987","aras","lexi","rrie","ierr","mili","dboy","ates","kristi","perf","case","bean","asto","randy","oris","iles","falcon","1516","5050","llio","nati","inni","91989","anki","rame","kevin","207198","a2010","lest","a123456","rega","friend","chevy","aval","andon","red1","verp","lava","omar","kiri","as12","cara","amir","olit","hani","annon","tive","okey","nther","1092","estin","ickey","204198","11977","unit","dance","031988","arba","trai","juan","d1234","rger","11975","1079","020719","dell","rabb","rmin","thor","rlan","jean","jone","scorpio","11976","p123","shal","erlo","nest","hele","5566","en12","want","ayne","est1","erem","issy","208198","ygir","burg","s1234","forever","ions","enka","flower","uren","sass","051990","ashk","theb","isse","scho","2119","camp","031987","201198","tima","0012","ophi","les1","rene","9874","late","oome","205198","chip","hica","ento","loves","2131","pace","21976","inke","ction","little","duke","206198","elic","onat","ancer","sala","doll","onik","eria","cord","eanu","chang","gord","kaka","diab","asdfghj","elia","1237","umpe","dies","alam","gala","fort","nine","11121","1118","rker","2128","071987","avan","soph","oshi","knight","bomb","arra","jimmy","1314","1285","mple","like","imbo","bigt","1324","dodge","rchi","fend","ikol","1129","ocky","r198","1022","lege","inat","llo1","bber","041988","rade","ebel","kass","robi","elec","hari","aldo","otti","stef","ssma","erda","luca","samu","leri","tati","ears","adel","frea","iano","ya19","offe","yell","ochka","geli","esha","15051","dmin","morgan","bella","onna","21995","8910","31991","ameri","annah","isla","truck","asmin","071986","020919","anthe","s198","compa","beth","041986","a777","121987","061986","raider","grac","atash","051988","stle","joke","041987","male","4455","driv","tita","051986","nato","amal","0010","3030","patrick","09876","jjjjj","charle","item","41984","edog","1290","121986","stop","demon","ious","lissa","cheste","5935","4725","chol","warr","atro","entin","umbe","ma19","22011","tata","asan","host","skip","on19","lipp","abra","nish","alib","erro","ench","mpir","1190","1077","10111","10121","dogs","lphin","nnet","ippy","berl","71990","llet","011988","junio","203198","41985","arit","71985","cons","ronc","craft","ongo","ingl","1086","ka12","iking","81990","ooooo","ergi","ritt","hester","10011","031986","cats","brav","011986","7258","2123","k199","lita","81985","011985","0990","johnny","terp","samsung","mang","city","71989","micke","huck","91986","etty","desi","aura","021019","oser","fall","key1","ssin","timo","joseph","viki","orgi","061987","world","anja","iabl","hjcn","mass","hank","5454","anky","comm","21975","051985","91988","81987","arsh","fami","q2w3e4r","051989","obra","twin","011989","gabr","rles","muff","elove","209198","61990","1127","071988","qqqqqq","imbe","erty12","baile","061988","ilip","rico","dward","rova","erde","ghjc","lect","eone","cky1","irina","0019","monster","9357","oster","lish","edwar","3698","shing","inho","idas","1245","01041","shak","1038","ppppp","girls","5656","45612","yste","5000","smar","amie","ners","raven","pean","meric","ulie","laure","look","n1234","210198","101987","2344","idge","ymrf","rpoo","31985","ffer","081988","viper","tton","thing","031990","choo","101986","41990","oodl","right","miller","31989","evan","onto","bian","eigh","manc","lace","lema","ggggg","heather","nnnn","tenn","orin","emar","ssio","hort","loui","camaro","squi","carm","31983","061985","8908","inga","2341","kath","7852","kbyf","stea","view","lldog","pson","ty123","ris1","ert1","1234q","eles","ouch","20011","hman","ova1","arik","dirt","1188","8904","name","ooby","christi","dria","ethe","plea","ra19","1080","boro","dako","pain","earl","rple","ocket","deep","livi","elon","01031","1068","61989","sabe","01021","tyrj","hark","ontr","rink","vfhb","amant","utch","in12","lean","01091","hara","nsto","rocks","e1234","20021","dolphi","asda","iell","anin","fghjk","icki","albert","rato","latin","bulldo","1082","505198","popo","ceman","eras","dog1","23021","mell","71983","mario","ber1","smile","rlos","hane","roke","1016","homer","ntai","xxxxxxx","winte","storm","lova","purpl","kare","41991","coob","091987","nita","count","021988","okin","2342","081989","diana","ione","ntha","pira","pear","dawg","beav","imal","obbi","aroli","71984","2333","081986","tdog","bigbo","rove","erba","blad","bett","usha","ndri"]}(Constants=exports.Constants||(exports.Constants={})); @@ -26,12 +26,12 @@ Array.prototype.toHumanString=function(){var t=this.length;if(0==t)return"(empty "use strict";exports.__esModule=!0;var NeuralNetwork,PasswordMeter=require("./PasswordMeter"),Constants=require("./constants");!function(e){var t=!0,r={};function n(e){return Math.log(e)/Math.LN10}function s(e,r){e*=function(e){var t=1,r=e.substr(1);if(e.charAt(0)===e.charAt(0).toUpperCase()&&e.charAt(0)!==e.charAt(0).toLowerCase()&&r===r.toLowerCase())t=1.5;else if(-1==e.search(/[a-z]/)){var n=e.replace(Constants.Constants.UPPERCASE_LETTERS_GLOBAL,"");e.length>=n.length+3&&(t=2)}else e!==e.toLowerCase()&&(t=10);return t}(r),t=!1;var s=n(e);e<=1&&(s=n(1.1)),r.length>0&&e==Number.POSITIVE_INFINITY&&(s=100),isNaN(e)&&(s=-1),PasswordMeter.PasswordMeter.instance.getNN().setNeuralNetNum(r,s)}function o(e,t){s(e,t),PasswordMeter.PasswordMeter.instance.getUI().displayRating(t)}function a(e,t){s(e,t),PasswordMeter.PasswordMeter.instance.getUI().synthesizeFixed(t)}e.log10=n,e.nnFixedCallback=a;var u,i,N,c,l,w=function(){function e(e,t){this.nn=e,this.nnfixed=t}return e.prototype.heardFromNn=function(){return!t},e.prototype.setNeuralNetNum=function(e,t){r[e]=t},e.prototype.getNeuralNetNum=function(e){return r[e]},e.prototype.queryGuessNumber=function(e,t){t?this.nnfixed.query_guess_number(e):this.nn.query_guess_number(e)},e}();e.NeuralNetworkInterface=w,u=PasswordMeter.PasswordMeter.instance,i=u.getConfig().neuralNetworkConfig,N=new NeuralNetworkClient(a,i),c=new NeuralNetworkClient(o,i),l=new w(c,N),u.setNN(l)}(NeuralNetwork=exports.NeuralNetwork||(exports.NeuralNetwork={})); },{"./PasswordMeter":3,"./constants":6}],10:[function(require,module,exports){ -"use strict";exports.__esModule=!0;var RuleFunctions,PasswordMeter=require("./PasswordMeter"),Helper=require("./helper"),Constants=require("./constants"),NeuralNetwork=require("./nn-misc");!function(e){e.verifyMinimumRequirements=function(e,t){var s=PasswordMeter.PasswordMeter.instance,r=s.getConfig(),a=s.getDictionaries(),n=r.colors.compliant,o=r.colors.noncompliant,i=r.symbols.compliant,l=r.symbols.noncompliant,c={},h={};if(r.length.active){var u=r.length.minLength,g=r.length.maxLength,d=!1,p="";p=g>0?"Contain "+u.toString()+"-"+g.toString()+" characters":"Contain "+u.toString()+"+ characters",e.length>=u&&(e.length<=g||0===g)&&(d=!0),p=d?""+i+p:""+l+p,p+="",c.length=p,h.length=d}var m=!1,f=!1,w=!1,b=!1,v=0;if(e.match(Constants.Constants.LOWERCASE_LETTERS_GLOBAL)&&(v++,m=!0),e.match(Constants.Constants.UPPERCASE_LETTERS_GLOBAL)&&(v++,f=!0),e.match(Constants.Constants.DIGITS_GLOBAL)&&(v++,w=!0),e.match(Constants.Constants.SYMBOLS_GLOBAL)&&(v++,b=!0),r.classCount.active){var y=r.classCount.minCount,C=r.classCount.maxCount;p="",d=!1,p=4===C?"Use "+y.toString()+"+ of the following: ":"Use "+y.toString()+"-"+C.toString()+" of the following: ",r.randomizeOrderCharClassRequirement?p+=PasswordMeter.PasswordMeter.instance.getUI().getCharClassStringForCharClassCountReq():p+="uppercase letters; lowercase letters; digits; symbols",v>=y&&v<=C&&(d=!0),p=d?""+i+p:""+l+p,p=p+="",c.classCount=p,h.classCount=d}if(r.classRequire.active){var A=r.classRequire.upperCase,x=r.classRequire.lowerCase,M=r.classRequire.digits,T=r.classRequire.symbols;p="",d=!1,r.randomizeOrderCharClassRequirement?p+=PasswordMeter.PasswordMeter.instance.getUI().getCharClassStringForMandatoryCharClassReq():(x&&(p.length>0?p+=" and a lowercase letter":p="Contain a lowercase letter"),A&&(p.length>0?p+=" and an uppercase letter":p="Contain an uppercase letter"),M&&(p.length>0?p+=" and a digit":p="Contain a digit"),T&&(p.length>0?p+=" and a symbol":p="Contain a symbol")),x&&!m||A&&!f||M&&!w||T&&!b||(d=!0),p=d?""+i+p:""+l+p,p=p+="",c.classRequire=p,h.classRequire=d}if(r.classAllow.active){var k=r.classAllow.upperCase,S=r.classAllow.lowerCase,L=r.classAllow.digits,P=r.classAllow.symbols;if(p="",d=!1,S||(p.length>0?p+=" or lowercase letters":p="Not include lowercase letters"),k||(p.length>0?p+=" or uppercase letters":p="Not include uppercase letters"),L||(p.length>0?p+=" or digits":p="Not include digits"),P||(p.length>0?p+=" or symbols":p="Not include symbols"),!S&&m||!k&&f||!L&&w||!P&&b||(d=!0),d)p=""+i+p;else{var E=[];!S&&m&&(E=E.concat(e.match(Constants.Constants.LOWERCASE_LETTERS))),!k&&f&&(E=E.concat(e.match(Constants.Constants.UPPERCASE_LETTERS))),!L&&w&&(E=E.concat(e.match(Constants.Constants.DIGITS))),!P&&b&&(E=E.concat(e.match(Constants.Constants.SYMBOLS)));var R=(E=E.removeDuplicates()).indexOf(" ");R>-1&&(E[R]="[space]"),p=""+l+(p+=" (You used "+E.join(", ")+")")}p=p+="",c.classAllow=p,h.classAllow=d}if(r.blacklist.active){p="",d=!1,p="Not be an extremely common password";var H=!1;if(e.length>0){var N=e;r.blacklist.stripDigitsSymbolsFromPassword&&(N=N.replace(/[^a-zA-Z]/gi,"")),r.blacklist.caseSensitive||(N=N.toLowerCase()),H=a.blacklistRejects(N)}(d=!H||0===e.length||-1!=r.blacklist.lengthException&&e.length>=r.blacklist.lengthException)||(p=""+l+p+""),d||(c.blacklist=p),h.blacklist=d}if(r.forbidChars.active){var D=r.forbidChars.list;p="",d=!1,p="Not include the following characters: "+W;for(var O=e.removeDuplicateChars(),W="",q=0;qConstants.Constants.endASCII||D.indexOf(O.charAt(q))>=0)&&(W+=O.charAt(q));0===W.length&&(d=!0),d||(p=""+l+p+""),d||(c.forbidChars=p),h.forbidChars=d}if(r.repeatChars.active){var z=r.repeatChars.limit;p="",d=!1,p="Not repeat the same character "+z.toString()+"+ times in a row";for(var I=[],_=z-1;_"+i+p:""+l+(p+=" ("+I.removeDuplicates().join(", ")+")"),p+="",c.repeatChars=p,h.repeatChars=d}if(r.usernameDifference.active){var G=r.usernameDifference.limit;p="",d=!1,p="Not base your password around your username";for(var U=e.toLowerCase(),B=t.toLowerCase();B.length>0&&U.indexOf(B)>-1;)U=U.substr(0,U.indexOf(B))+U.substr(U.indexOf(B)+B.length);(0==B.length||0==e.length||U.length>=G)&&(d=!0),d||(p=""+l+p+""),d||(c.usernameDifference=p),h.usernameDifference=d}if(r.minLogNnGuessNum.active){d=!1,p="";var Z=r.minLogNnGuessNum.threshold,F=PasswordMeter.PasswordMeter.instance.getNN().getNeuralNetNum(e),Y=F+NeuralNetwork.NeuralNetwork.log10(r.neuralNetworkConfig.scaleFactor);F<0?console.log("(still) looking up NN guess number: "+e):F>Z?(d=!0,console.log("high enough NN guess number: "+e+" ("+F+" > "+Z+") [unconservative NN guess number: "+Y+"]")):(console.log("too low NN guess number: "+e+" ("+F+" < "+Z+") [unconservative NN guess number: "+Y+"]"),p=""+l+r.minLogNnGuessNum.rejectionFeedback),d||(c.minLogNnGuessNum=p),h.minLogNnGuessNum=d}if(r.sameChars.active){var $=r.sameChars.limit;p="",d=!1,e.length>=r.sameChars.lengthException||function(e,t){for(var s={},r=0;rt)return!1}else s[a]=1}return!0}(e,$)?d=!0:p="Not contain the same character more than "+$.toString()+"+ times",d||(p=""+l+p+"",c.sameChars=p),h.sameChars=d}r.prohibitKnownLeaked.active&&(d=!1,p="",e.length"+l+"Not use a password found in previous security leaks",c.prohibitKnownLeaked=p),h.prohibitKnownLeaked=d);var K=!0;for(var J in h)if(!(K=K&&h[J]))break;return{compliant:K,detail:{compliance:h,explanation:c}}},e.pwLength=function(e){var t=e.length,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().length.maxLength;return t<16&&(0===n||t=65&&e.charCodeAt(i)<=90&&t++;if(t<.15*e.length&&o){s="Consider using more uppercase letters",r="Consider using ",r+=(t+1).toString()+" or more uppercase letters",a="Uppercase letters are surprisingly uncommon in passwords, which makes them hard to guess";var l=65+Math.floor(26*Math.random()),c=Math.floor(1+Math.random()*(e.length-1));n=e.slice(0,c)+String.fromCharCode(l)+e.slice(c)}return{count:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:n}},e.countLC=function(e){for(var t=0,s="",r="",a="",n="",o=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.lowerCase,i=0;i=97&&e.charCodeAt(i)<=122&&t++;if(t<.15*e.length&&o){a="Having variety in the types of characters you use makes your password harder to guess",s="Consider using more lowercase letters",r="Consider using ",r+=t+1+" or more lowercase letters";var l=97+Math.floor(26*Math.random()),c=Math.floor(1+Math.random()*(e.length-1));n=e.slice(0,c)+String.fromCharCode(l)+e.slice(c)}return{count:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:n}},e.countDIGS=function(e){for(var t=0,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.digits,o=0;o=48&&e.charCodeAt(o)<=57&&t++;return t<.15*e.length&&n&&(s="Consider using more digits",a="Most passwords contain no digits or digits in predictable places; doing otherwise makes your password harder to guess",r="Consider using ",r+=t+1+" or more digits"),{count:t,reasonWhy:a,publicText:s,sensitiveText:r}},e.countSYMS=function(e){var t=e.replace(/[A-Za-z0-9]/g,"").length,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.symbols;return t<.15*e.length&&n&&(s="Consider using more symbols",a="Few passwords contain symbols, which makes passwords with symbols harder to guess",r="Consider using ",r+=t+1+" or more symbols"),{count:t,reasonWhy:a,publicText:s,sensitiveText:r}},e.characterClasses=function(e){var t=0;e.match(Constants.Constants.LOWERCASE_LETTERS)&&t++,e.match(Constants.Constants.UPPERCASE_LETTERS)&&t++,e.match(Constants.Constants.DIGITS)&&t++,e.match(Constants.Constants.SYMBOLS)&&t++;var s=t,r="",a="",n="",o=PasswordMeter.PasswordMeter.instance.getConfig().classAllow;if(e.match(Constants.Constants.UPPERCASE_LETTERS)||e.match(Constants.Constants.DIGITS)||e.match(Constants.Constants.SYMBOLS))if(e.match(Constants.Constants.DIGITS)||e.match(Constants.Constants.SYMBOLS))e.match(Constants.Constants.UPPERCASE_LETTERS)||e.match(Constants.Constants.SYMBOLS)?e.match(Constants.Constants.SYMBOLS)||o.symbols&&(r="Add symbols in unpredictable locations",a="Add symbols in unpredictable locations",n="Because only 1% of passwords use symbols, adding them unpredictably strengthens your password"):(i=[],l="",o.symbols&&i.push("symbols"),o.upperCase&&i.push("uppercase letters"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="42% of passwords contain only lowercase letters and number, making them easy for attackers to guess");else{var i=[],l="";o.symbols&&i.push("symbols"),o.digits&&i.push("digits"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="42% of passwords contain only letters, making them easy for attackers to guess"}else{var i=[],l="";o.symbols&&i.push("symbols"),o.digits&&i.push("digits"),o.upperCase&&i.push("uppercase letters"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="38% of passwords contain only lowercase letters, making them easy for attackers to guess"}return{count:s,reasonWhy:n,publicText:r,sensitiveText:a}},e.uppercasePredictable=function(e){var t=0,s="",r="",a="",n="",o="";if(e.charAt(0)===e.charAt(0).toUpperCase()&&e.charAt(0)!==e.charAt(0).toLowerCase()){var i=e.substr(1);if(i===i.toLowerCase()){t=1,s="Capitalize a letter in the middle",r="Capitalize a letter in the middle, rather than the first character",n=e.charAt(0).escapeHTML(),a="30% of people also capitalize only the first character";for(var l=new Array,c=0;c=97&&e.charCodeAt(c)<=122&&l.push(c);var h=Math.floor(Math.random()*l.length);o=e.substring(0,l[h]),o+=e.charAt(l[h]).toUpperCase(),o+=e.substring(l[h]+1)}}if(-1==e.search(/[a-z]/)){var u=e.replace(/[A-Z]/g,"");if(e.length>=u.length+3){t=1,s="Mix up your capitalization",r="Mix up your capitalization, rather than capitalizing everything",a="21% of passwords also contain only uppercase letters";var g=new Array;for(c=0;c=65&&e.charCodeAt(c)<=90&&g.push(c);var d=Math.floor(Math.random()*g.length);o=e.substring(0,g[d]),o+=e.charAt(g[d]).toLowerCase(),o+=e.substring(g[d]+1)}}return{score:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:o,problemText:n}},e.digitsPredictable=function(e){var t=0,s="",r="",a="",n="",o="",i=[],l=new RegExp("[^0-9]"),c=new RegExp("^[0-9]+[^0-9]+$"),h=new RegExp("^[^0-9]+[0-9]+$");if(e.length>=4&&!e.match(l)){t=1,s="Add more letters and symbols to your password",r="Add characters other than digits to your password",a=e.escapeHTML(),n="35% of people also use only digits";var u=58+Math.floor(68*Math.random()),g=Math.floor(1+Math.random()*(e.length-1));o=e.slice(0,g)+String.fromCharCode(u)+e.slice(g);for(var d=0;d=4&&e.match(c)){t=1,r="Consider inserting digits into the middle, not just at the beginning",s="Consider inserting digits into the middle",n="10% of people also put digits at the beginning of the password";for(var p=1;e.charCodeAt(p)>=48&&e.charCodeAt(p)<=57;)p++;for(a=e.slice(0,p).escapeHTML(),g=Math.floor(p+1+Math.random()*(e.length-p-1)),o=e.slice(p,g)+e.slice(0,p)+e.slice(g),d=0;d=4&&e.match(h)){t=1,r="Consider inserting digits into the middle, not just at the end",s="Consider inserting digits into the middle",n="38% of people also put digits at the end of the password";for(var m=e.length-2;e.charCodeAt(m)>=48&&e.charCodeAt(m)<=57;)m--;for(a=e.slice(m+1).escapeHTML(),g=Math.floor(1+Math.random()*(e.length-m-1)),o=e.slice(0,g)+e.slice(m+1)+e.slice(g,m+1),d=0;d=4&&e.match(l)){t=1,r="Move symbols and digits earlier, rather than just at the end",s="Move symbols and digits elsewhere in your password",a=e.match(h)[0].escapeHTML(),n="14% of people also use letters, followed by symbols, followed by digits";var u=e.search(h);a=e.slice(u).escapeHTML();var g=Math.floor(1+Math.random()*(u-1));o=e.slice(0,g)+e.slice(u)+e.slice(g,u);for(var d=0;d=4&&e.match(c)){for(t=1,r="Move your symbols earlier, rather than just at the end",s="Move symbols and digits elsewhere in your password",n="16% of people also put symbols only at the end of the password",u=e.search(h),a=e.slice(u).escapeHTML(),g=Math.floor(1+Math.random()*(u-1)),o=e.slice(0,g)+e.slice(u)+e.slice(g,u),d=0;d":[3,9],"/":[3,10],"?":[3,10]," ":[4,5]},s="",r=0;rl&&"0,0"!==h&&(i=c,l=r-c),c=r)}var u=l+1,g="",d="",p="",m="";return u>=4&&(g="Avoid using a pattern on your keyboard",d="Avoid using a pattern on your keyboard like "+(p=s.substring(i,i+l+1).escapeHTML())+"",m="Because keyboard patterns are very common in passwords, attackers know to guess them"),u<3&&(u=0),{score:u,reasonWhy:m,publicText:g,sensitiveText:d,problemText:p}},e.duplicatedCharacters=function(e){var t=e.split("").removeDuplicates(),s=e.length-t.length,r="",a="",n="",o="";if(t.length<=.5*e.length&&t.length<=5){o="",r="Have more variety in the characters you choose";var i="";t.length>1&&(i="s"),a="Have more variety than repeating the same "+t.length+" character"+i+" ("+Helper.Helper.boldAll(t.sort()).toHumanString()+")",n="Passwords that use only a few different characters are easy for attackers to guess"}return{count:s,reasonWhy:n,publicText:r,sensitiveText:a,problemText:o}},e.repeatedSections=function(e){for(var t=0,s="",r="",a="",n="",o=!1,i=(e=e.toLowerCase()).length,l=Math.floor(i/2);l>=3;l--){for(var c=0;c<=i-l;c++){for(var h=e.substring(c,c+l),u=h.split("").reverse().join(""),g=0;g+l<=c;g++)e.substring(g,g+l)===h?(t+=l,a=h.escapeHTML()):e.substring(g,g+l)===u&&(t+=l,a=h.escapeHTML(),o=!0);for(g=c+l;g+l<=i;g++)e.substring(g,g+l)===h?(t+=l,a=h.escapeHTML()):e.substring(g,g+l)===u&&(t+=l,a=h.escapeHTML(),o=!0);if(t>=3){t>=4?(s="Avoid repeating sections",r="Avoid repeating sections ("+a+")",n="In their guessing, attackers know to try duplicating parts of the password",o&&(s+=", forwards or backwards",r+=", forwards or backwards")):a="";break}}if(t>0)break}return{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.repeats=function(e){for(var t=e.length,s=1,r=1,a="",n="",o="",i="",l="",c=1;cs&&(s=r,a=e[c]):r=1;var h=s;if(s>=3){n="Don't repeat the same character many times in a row";for(var u=0;u"+(i=i.escapeHTML())+") many times in a row",l="Hitting the same key over and over adds little to your password's strength"}return 1===h&&(h=0),{count:h,reasonWhy:l,publicText:n,sensitiveText:o,problemText:i}},e.contextual=function(e,t){for(var s=0,r="",a="",n="",o="",i=e,l=0;l=5){s=u.length,r="Don't use your account information in your password",a="Don't use your account information ("+(n=u.escapeHTML())+") in your password",o="Attackers know to guess your username and email address as part of your password";var g=e.indexOf(u);g>-1&&(i=e.substr(0,g)+e.substr(g+u.length))}return{count:s,reasonWhy:o,publicText:r,sensitiveText:a,problemText:n,remaining:i}},e.commonSubstringCheck=function(e){var t=0,s="",r="",a="",n="",o=new Array;e=e.toLowerCase();for(var i=Constants.Constants.blacklistedSubstrings,l=0;l0){s="Avoid strings of characters commonly found in passwords",r="Avoid strings of characters commonly found in passwords like "+o.join(" and ")+"",n="Even if they don't make sense, these strings of characters show up in many passwords, which makes them bad to use in yours.",a=o[0].escapeHTML();for(var c=0;c as part of your own password",n=e[r].escapeHTML();return{length:e[r].length,reasonWhy:s,publicText:"Avoid using very common passwords as part of your own password",sensitiveText:a,problemText:n}}return{length:0,reasonWhy:s,publicText:"",sensitiveText:"",problemText:""}},e.blacklist=function(e){for(var t=PasswordMeter.PasswordMeter.instance.getConfig(),s=PasswordMeter.PasswordMeter.instance.getHelper(),r=t.ignoredWords,a="",n="",o="",i="",l=e,c=[],h=new RegExp("[^A-Za-z]"),u=(e=(e=e.toLowerCase()).replace(/[-_ ]/g,"")).split(/[^a-z01345@$]+/),g=(u=u.filter(function(e){return e})).listSubstringsMinMax(1,void 0),d=0;d-1&&(c.push(g[d]),p=g[d])}if(p.length>0){for(0==o.length&&(o=g[d].escapeHTML()),f=0;f-1){u.splice(f,1,u[f].substring(0,b),u[f].substring(b+p.length)),u=u.filter(function(e){return e});break}}g=u.listSubstringsMinMax(1,p.length),p="",d=0}else d++}var v=0;if(c.length>0){for(a="Don't use site-specific terms in your password",d=0;d-1&&(l=l.substr(0,y)+l.substr(y+c[d].length))}n="Don't use site-specific terms ("+Helper.Helper.boldAll(c.removeDuplicates()).toHumanString()+")",i="Attackers target their attacks to words used on a particular service"}return{length:v,reasonWhy:i,publicText:a,sensitiveText:n,problemText:o,remaining:l}},e.combinedDictCheck=function(e){for(var t="",s="",r="",a="",n=100,o=new Array,i=new Array,l=new Array,c=new Array,h=new Array,u=PasswordMeter.PasswordMeter.instance,g=u.getDictionaries(),d=u.getHelper(),p=new Array,m=new Array,f=(e=e.replace(/[-_ ]/g,"")).split(/[^A-Za-z012345!&@$]+/),w=(f=f.filter(function(e){return e})).listSubstringsMinMax(4,void 0),b=0;b0){for(0==r.length&&(r=w[b].escapeHTML()),A=0;A-1){f.splice(A,1,f[A].substring(0,T),f[A].substring(T+v.length)),f=f.filter(function(e){return e});break}}w=f.listSubstringsMinMax(4,v.length),v="",b=0}else b++}var k=new Array,S=new Array,L=0,P=0,E=function(e,t){if(e.length>0){k.push(t);for(var s=0;s0&&(a="Attackers use software that automatically guesses millions of words commonly found in dictionaries, wordlists, or other people's passwords",t="Don't use ",s="Don't use ",n<100&&(a+=", including simple transformations of those words/phrases where they substitute digits and symbols for letters"),t+=k.join(" or "),s+=S.join(" or ")),{length:L,reasonWhy:a,publicText:t,sensitiveText:s,problemText:r,dictionaryTokens:P,substitutionCommonness:n=100-n}},e.identifyDates=function(e){var t=0,s="",r="",a="",n="",o=[],i=PasswordMeter.PasswordMeter.instance.getHelper(),l=[e],c=function(e){var s=i.matchHelper(l,e);s.score>0&&(t+=s.score,o=o.concat(s.matched.toString()),l=s.revisedParts)},h="([ .-/])",u="((0\\d|1[012])|\\d)",g="(january|february|march|april|may|june|july|august|september|october|november|december)",d="([012]\\d|3[01])",p="(\\d\\d)",m="(19\\d\\d|20[01234]\\d)";return c(new RegExp(u+h+d+h+m,"g")),c(new RegExp(d+h+u+h+m,"g")),c(new RegExp(u+h+d+h+p,"g")),c(new RegExp(d+h+u+h+p,"g")),c(new RegExp(u+d+m,"g")),c(new RegExp(d+u+m,"g")),c(new RegExp(g+m,"ig")),c(new RegExp(g+p,"ig")),c(new RegExp(u+h+d,"g")),c(new RegExp(d+h+u,"g")),c(new RegExp(m,"g")),t>0&&(s="Avoid using dates",r="Avoid using dates like "+Helper.Helper.boldAll(o).toHumanString(),n="Dates and years in any format are quite common in passwords",a=o[0].escapeHTML()),{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.alphabeticSequenceCheck=function(e){var t=0,s="",r="",a="",n="",o=[],i=[];o[0]=e.charCodeAt(0);for(var l=1;lh&&0!==g&&(c=u,h=l-u),u=l),1===(t=h)&&(t=0),t>=2&&t++,t>=4){var d=e.substr(c,c+h+1);a=d.escapeHTML();var p=new RegExp("^[0-9]+$");d.match(p)?(s="Avoid numerical patterns",r="Avoid numerical patterns like "+a+""):(s="Avoid patterns from the alphabet",r="Avoid patterns from the alphabet like "+a+""),n="Attackers know to guess sequences following the alphabet, in addition to repeated characters or patterns on your keyboard"}}return{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.structurePredictable=function(e){var t="",s="",r="",a=0,n=(e=(e=(e=(e=e.replace(/[A-Z]/g,"U")).replace(/[a-z]/g,"L")).replace(/[0-9]/g,"D")).replace(/[^A-Za-z0-9]/g,"S"),Constants.Constants.commonStructures.indexOf(e));if(n>=0){a=2124-n,r="One technique attackers use is to try all possible passwords within common structures, or arrangements of character classes (e.g., where lowercase letters and digits are located)",s=(t="The way you structure your password is predictable")+" (";for(var o=!0,i=0;i1&&(s+="s"),i+=l}s+=")"}return{score:a,reasonWhy:r,publicText:t,sensitiveText:s}}}(RuleFunctions=exports.RuleFunctions||(exports.RuleFunctions={})); +"use strict";exports.__esModule=!0;var RuleFunctions,PasswordMeter=require("./PasswordMeter"),Helper=require("./helper"),Constants=require("./constants"),NeuralNetwork=require("./nn-misc");!function(e){e.verifyMinimumRequirements=function(e,t){var s=PasswordMeter.PasswordMeter.instance,r=s.getConfig(),a=s.getDictionaries(),n=r.colors.compliant,o=r.colors.noncompliant,i=r.symbols.compliant,l=r.symbols.noncompliant,c={},h={};if(r.length.active){var u=r.length.minLength,d=r.length.maxLength,g=!1,p="";p=d>0?"Contain "+u.toString()+"-"+d.toString()+" characters":"Contain "+u.toString()+"+ characters",e.length>=u&&(e.length<=d||0===d)&&(g=!0),p=g?""+i+p:""+l+p,p+="",c.length=p,h.length=g}var m=!1,f=!1,w=!1,b=!1,v=0;if(e.match(Constants.Constants.LOWERCASE_LETTERS_GLOBAL)&&(v++,m=!0),e.match(Constants.Constants.UPPERCASE_LETTERS_GLOBAL)&&(v++,f=!0),e.match(Constants.Constants.DIGITS_GLOBAL)&&(v++,w=!0),e.match(Constants.Constants.SYMBOLS_GLOBAL)&&(v++,b=!0),r.classCount.active){var y=r.classCount.minCount,C=r.classCount.maxCount;p="",g=!1,p=4===C?"Use "+y.toString()+"+ of the following: ":"Use "+y.toString()+"-"+C.toString()+" of the following: ",r.randomizeOrderCharClassRequirement?p+=PasswordMeter.PasswordMeter.instance.getUI().getCharClassStringForCharClassCountReq():p+="uppercase letters; lowercase letters; digits; symbols",v>=y&&v<=C&&(g=!0),p=g?""+i+p:""+l+p,p=p+="",c.classCount=p,h.classCount=g}if(r.classRequire.active){var A=r.classRequire.upperCase,x=r.classRequire.lowerCase,M=r.classRequire.digits,T=r.classRequire.symbols;p="",g=!1,r.randomizeOrderCharClassRequirement?p+=PasswordMeter.PasswordMeter.instance.getUI().getCharClassStringForMandatoryCharClassReq():(x&&(p.length>0?p+=" and a lowercase letter":p="Contain a lowercase letter"),A&&(p.length>0?p+=" and an uppercase letter":p="Contain an uppercase letter"),M&&(p.length>0?p+=" and a digit":p="Contain a digit"),T&&(p.length>0?p+=" and a symbol":p="Contain a symbol")),x&&!m||A&&!f||M&&!w||T&&!b||(g=!0),p=g?""+i+p:""+l+p,p=p+="",c.classRequire=p,h.classRequire=g}if(r.classAllow.active){var k=r.classAllow.upperCase,S=r.classAllow.lowerCase,L=r.classAllow.digits,P=r.classAllow.symbols;if(p="",g=!1,S||(p.length>0?p+=" or lowercase letters":p="Not include lowercase letters"),k||(p.length>0?p+=" or uppercase letters":p="Not include uppercase letters"),L||(p.length>0?p+=" or digits":p="Not include digits"),P||(p.length>0?p+=" or symbols":p="Not include symbols"),!S&&m||!k&&f||!L&&w||!P&&b||(g=!0),g)p=""+i+p;else{var E=[];!S&&m&&(E=E.concat(e.match(Constants.Constants.LOWERCASE_LETTERS))),!k&&f&&(E=E.concat(e.match(Constants.Constants.UPPERCASE_LETTERS))),!L&&w&&(E=E.concat(e.match(Constants.Constants.DIGITS))),!P&&b&&(E=E.concat(e.match(Constants.Constants.SYMBOLS)));var R=(E=E.removeDuplicates()).indexOf(" ");R>-1&&(E[R]="[space]"),p=""+l+(p+=" (You used "+E.join(", ")+")")}p=p+="",c.classAllow=p,h.classAllow=g}if(r.blacklist.active){p="",g=!1,p="Not be an extremely common password";var H=!1;if(e.length>0){var N=e;r.blacklist.stripDigitsSymbolsFromPassword&&(N=N.replace(/[^a-zA-Z]/gi,"")),r.blacklist.caseSensitive||(N=N.toLowerCase()),H=a.blacklistRejects(N)}(g=!H||0===e.length||-1!=r.blacklist.lengthException&&e.length>=r.blacklist.lengthException)||(p=""+l+p+""),g||(c.blacklist=p),h.blacklist=g}if(r.forbidChars.active){var D=r.forbidChars.list;p="",g=!1,p="Not include the following characters: "+W;for(var O=e.removeDuplicateChars(),W="",q=0;qConstants.Constants.endASCII||D.indexOf(O.charAt(q))>=0)&&(W+=O.charAt(q));0===W.length&&(g=!0),g||(p=""+l+p+""),g||(c.forbidChars=p),h.forbidChars=g}if(r.repeatChars.active){var z=r.repeatChars.limit;p="",g=!1,p="Not repeat the same character "+z.toString()+"+ times in a row";for(var I=[],_=z-1;_"+i+p:""+l+(p+=" ("+I.removeDuplicates().join(", ")+")"),p+="",c.repeatChars=p,h.repeatChars=g}if(r.usernameDifference.active){var G=r.usernameDifference.limit;p="",g=!1,p="Not base your password around your username";for(var U=e.toLowerCase(),B=t.toLowerCase();B.length>0&&U.indexOf(B)>-1;)U=U.substr(0,U.indexOf(B))+U.substr(U.indexOf(B)+B.length);(0==B.length||0==e.length||U.length>=G)&&(g=!0),g||(p=""+l+p+""),g||(c.usernameDifference=p),h.usernameDifference=g}if(r.minLogNnGuessNum.active){g=!1,p="";var Z=r.minLogNnGuessNum.threshold,F=PasswordMeter.PasswordMeter.instance.getNN().getNeuralNetNum(e),Y=F+NeuralNetwork.NeuralNetwork.log10(r.neuralNetworkConfig.scaleFactor);F>=0&&(F>Z?(g=!0,console.log("high enough NN guess number: "+e+" ("+F+" > "+Z+") [unconservative NN guess number: "+Y+"]")):(console.log("too low NN guess number: "+e+" ("+F+" < "+Z+") [unconservative NN guess number: "+Y+"]"),p=""+l+r.minLogNnGuessNum.rejectionFeedback)),g||(c.minLogNnGuessNum=p),h.minLogNnGuessNum=g}if(r.sameChars.active){var $=r.sameChars.limit;p="",g=!1,e.length>=r.sameChars.lengthException||function(e,t){for(var s={},r=0;rt)return!1}else s[a]=1}return!0}(e,$)?g=!0:p="Not contain the same character more than "+$.toString()+"+ times",g||(p=""+l+p+"",c.sameChars=p),h.sameChars=g}r.prohibitKnownLeaked.active&&(g=!1,p="",e.length"+l+"Not use a password found in previous security leaks",c.prohibitKnownLeaked=p),h.prohibitKnownLeaked=g);var K=!0;for(var J in h)if(!(K=K&&h[J]))break;return{compliant:K,detail:{compliance:h,explanation:c}}},e.pwLength=function(e){var t=e.length,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().length.maxLength;return t<16&&(0===n||t=65&&e.charCodeAt(i)<=90&&t++;if(t<.15*e.length&&o){s="Consider using more uppercase letters",r="Consider using ",r+=(t+1).toString()+" or more uppercase letters",a="Uppercase letters are surprisingly uncommon in passwords, which makes them hard to guess";var l=65+Math.floor(26*Math.random()),c=Math.floor(1+Math.random()*(e.length-1));n=e.slice(0,c)+String.fromCharCode(l)+e.slice(c)}return{count:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:n}},e.countLC=function(e){for(var t=0,s="",r="",a="",n="",o=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.lowerCase,i=0;i=97&&e.charCodeAt(i)<=122&&t++;if(t<.15*e.length&&o){a="Having variety in the types of characters you use makes your password harder to guess",s="Consider using more lowercase letters",r="Consider using ",r+=t+1+" or more lowercase letters";var l=97+Math.floor(26*Math.random()),c=Math.floor(1+Math.random()*(e.length-1));n=e.slice(0,c)+String.fromCharCode(l)+e.slice(c)}return{count:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:n}},e.countDIGS=function(e){for(var t=0,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.digits,o=0;o=48&&e.charCodeAt(o)<=57&&t++;return t<.15*e.length&&n&&(s="Consider using more digits",a="Most passwords contain no digits or digits in predictable places; doing otherwise makes your password harder to guess",r="Consider using ",r+=t+1+" or more digits"),{count:t,reasonWhy:a,publicText:s,sensitiveText:r}},e.countSYMS=function(e){var t=e.replace(/[A-Za-z0-9]/g,"").length,s="",r="",a="",n=PasswordMeter.PasswordMeter.instance.getConfig().classAllow.symbols;return t<.15*e.length&&n&&(s="Consider using more symbols",a="Few passwords contain symbols, which makes passwords with symbols harder to guess",r="Consider using ",r+=t+1+" or more symbols"),{count:t,reasonWhy:a,publicText:s,sensitiveText:r}},e.characterClasses=function(e){var t=0;e.match(Constants.Constants.LOWERCASE_LETTERS)&&t++,e.match(Constants.Constants.UPPERCASE_LETTERS)&&t++,e.match(Constants.Constants.DIGITS)&&t++,e.match(Constants.Constants.SYMBOLS)&&t++;var s=t,r="",a="",n="",o=PasswordMeter.PasswordMeter.instance.getConfig().classAllow;if(e.match(Constants.Constants.UPPERCASE_LETTERS)||e.match(Constants.Constants.DIGITS)||e.match(Constants.Constants.SYMBOLS))if(e.match(Constants.Constants.DIGITS)||e.match(Constants.Constants.SYMBOLS))e.match(Constants.Constants.UPPERCASE_LETTERS)||e.match(Constants.Constants.SYMBOLS)?e.match(Constants.Constants.SYMBOLS)||o.symbols&&(r="Add symbols in unpredictable locations",a="Add symbols in unpredictable locations",n="Because only 1% of passwords use symbols, adding them unpredictably strengthens your password"):(i=[],l="",o.symbols&&i.push("symbols"),o.upperCase&&i.push("uppercase letters"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="42% of passwords contain only lowercase letters and number, making them easy for attackers to guess");else{var i=[],l="";o.symbols&&i.push("symbols"),o.digits&&i.push("digits"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="42% of passwords contain only letters, making them easy for attackers to guess"}else{var i=[],l="";o.symbols&&i.push("symbols"),o.digits&&i.push("digits"),o.upperCase&&i.push("uppercase letters"),r="Add "+(l=i.toHumanString())+" in unpredictable locations",a="Add "+l+" in unpredictable locations",n="38% of passwords contain only lowercase letters, making them easy for attackers to guess"}return{count:s,reasonWhy:n,publicText:r,sensitiveText:a}},e.uppercasePredictable=function(e){var t=0,s="",r="",a="",n="",o="";if(e.charAt(0)===e.charAt(0).toUpperCase()&&e.charAt(0)!==e.charAt(0).toLowerCase()){var i=e.substr(1);if(i===i.toLowerCase()){t=1,s="Capitalize a letter in the middle",r="Capitalize a letter in the middle, rather than the first character",n=e.charAt(0).escapeHTML(),a="30% of people also capitalize only the first character";for(var l=new Array,c=0;c=97&&e.charCodeAt(c)<=122&&l.push(c);var h=Math.floor(Math.random()*l.length);o=e.substring(0,l[h]),o+=e.charAt(l[h]).toUpperCase(),o+=e.substring(l[h]+1)}}if(-1==e.search(/[a-z]/)){var u=e.replace(/[A-Z]/g,"");if(e.length>=u.length+3){t=1,s="Mix up your capitalization",r="Mix up your capitalization, rather than capitalizing everything",a="21% of passwords also contain only uppercase letters";var d=new Array;for(c=0;c=65&&e.charCodeAt(c)<=90&&d.push(c);var g=Math.floor(Math.random()*d.length);o=e.substring(0,d[g]),o+=e.charAt(d[g]).toLowerCase(),o+=e.substring(d[g]+1)}}return{score:t,reasonWhy:a,publicText:s,sensitiveText:r,fixedPw:o,problemText:n}},e.digitsPredictable=function(e){var t=0,s="",r="",a="",n="",o="",i=[],l=new RegExp("[^0-9]"),c=new RegExp("^[0-9]+[^0-9]+$"),h=new RegExp("^[^0-9]+[0-9]+$");if(e.length>=4&&!e.match(l)){t=1,s="Add more letters and symbols to your password",r="Add characters other than digits to your password",a=e.escapeHTML(),n="35% of people also use only digits";var u=58+Math.floor(68*Math.random()),d=Math.floor(1+Math.random()*(e.length-1));o=e.slice(0,d)+String.fromCharCode(u)+e.slice(d);for(var g=0;g=4&&e.match(c)){t=1,r="Consider inserting digits into the middle, not just at the beginning",s="Consider inserting digits into the middle",n="10% of people also put digits at the beginning of the password";for(var p=1;e.charCodeAt(p)>=48&&e.charCodeAt(p)<=57;)p++;for(a=e.slice(0,p).escapeHTML(),d=Math.floor(p+1+Math.random()*(e.length-p-1)),o=e.slice(p,d)+e.slice(0,p)+e.slice(d),g=0;g=4&&e.match(h)){t=1,r="Consider inserting digits into the middle, not just at the end",s="Consider inserting digits into the middle",n="38% of people also put digits at the end of the password";for(var m=e.length-2;e.charCodeAt(m)>=48&&e.charCodeAt(m)<=57;)m--;for(a=e.slice(m+1).escapeHTML(),d=Math.floor(1+Math.random()*(e.length-m-1)),o=e.slice(0,d)+e.slice(m+1)+e.slice(d,m+1),g=0;g=4&&e.match(l)){t=1,r="Move symbols and digits earlier, rather than just at the end",s="Move symbols and digits elsewhere in your password",a=e.match(h)[0].escapeHTML(),n="14% of people also use letters, followed by symbols, followed by digits";var u=e.search(h);a=e.slice(u).escapeHTML();var d=Math.floor(1+Math.random()*(u-1));o=e.slice(0,d)+e.slice(u)+e.slice(d,u);for(var g=0;g=4&&e.match(c)){for(t=1,r="Move your symbols earlier, rather than just at the end",s="Move symbols and digits elsewhere in your password",n="16% of people also put symbols only at the end of the password",u=e.search(h),a=e.slice(u).escapeHTML(),d=Math.floor(1+Math.random()*(u-1)),o=e.slice(0,d)+e.slice(u)+e.slice(d,u),g=0;g":[3,9],"/":[3,10],"?":[3,10]," ":[4,5]},s="",r=0;rl&&"0,0"!==h&&(i=c,l=r-c),c=r)}var u=l+1,d="",g="",p="",m="";return u>=4&&(d="Avoid using a pattern on your keyboard",g="Avoid using a pattern on your keyboard like "+(p=s.substring(i,i+l+1).escapeHTML())+"",m="Because keyboard patterns are very common in passwords, attackers know to guess them"),u<3&&(u=0),{score:u,reasonWhy:m,publicText:d,sensitiveText:g,problemText:p}},e.duplicatedCharacters=function(e){var t=e.split("").removeDuplicates(),s=e.length-t.length,r="",a="",n="",o="";if(t.length<=.5*e.length&&t.length<=5){o="",r="Have more variety in the characters you choose";var i="";t.length>1&&(i="s"),a="Have more variety than repeating the same "+t.length+" character"+i+" ("+Helper.Helper.boldAll(t.sort()).toHumanString()+")",n="Passwords that use only a few different characters are easy for attackers to guess"}return{count:s,reasonWhy:n,publicText:r,sensitiveText:a,problemText:o}},e.repeatedSections=function(e){for(var t=0,s="",r="",a="",n="",o=!1,i=(e=e.toLowerCase()).length,l=Math.floor(i/2);l>=3;l--){for(var c=0;c<=i-l;c++){for(var h=e.substring(c,c+l),u=h.split("").reverse().join(""),d=0;d+l<=c;d++)e.substring(d,d+l)===h?(t+=l,a=h.escapeHTML()):e.substring(d,d+l)===u&&(t+=l,a=h.escapeHTML(),o=!0);for(d=c+l;d+l<=i;d++)e.substring(d,d+l)===h?(t+=l,a=h.escapeHTML()):e.substring(d,d+l)===u&&(t+=l,a=h.escapeHTML(),o=!0);if(t>=3){t>=4?(s="Avoid repeating sections",r="Avoid repeating sections ("+a+")",n="In their guessing, attackers know to try duplicating parts of the password",o&&(s+=", forwards or backwards",r+=", forwards or backwards")):a="";break}}if(t>0)break}return{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.repeats=function(e){for(var t=e.length,s=1,r=1,a="",n="",o="",i="",l="",c=1;cs&&(s=r,a=e[c]):r=1;var h=s;if(s>=3){n="Don't repeat the same character many times in a row";for(var u=0;u"+(i=i.escapeHTML())+") many times in a row",l="Hitting the same key over and over adds little to your password's strength"}return 1===h&&(h=0),{count:h,reasonWhy:l,publicText:n,sensitiveText:o,problemText:i}},e.contextual=function(e,t){for(var s=0,r="",a="",n="",o="",i=e,l=0;l=5){s=u.length,r="Don't use your account information in your password",a="Don't use your account information ("+(n=u.escapeHTML())+") in your password",o="Attackers know to guess your username and email address as part of your password";var d=e.indexOf(u);d>-1&&(i=e.substr(0,d)+e.substr(d+u.length))}return{count:s,reasonWhy:o,publicText:r,sensitiveText:a,problemText:n,remaining:i}},e.commonSubstringCheck=function(e){var t=0,s="",r="",a="",n="",o=new Array;e=e.toLowerCase();for(var i=Constants.Constants.blacklistedSubstrings,l=0;l0){s="Avoid strings of characters commonly found in passwords",r="Avoid strings of characters commonly found in passwords like "+o.join(" and ")+"",n="Even if they don't make sense, these strings of characters show up in many passwords, which makes them bad to use in yours.",a=o[0].escapeHTML();for(var c=0;c as part of your own password",n=e[r].escapeHTML();return{length:e[r].length,reasonWhy:s,publicText:"Avoid using very common passwords as part of your own password",sensitiveText:a,problemText:n}}return{length:0,reasonWhy:s,publicText:"",sensitiveText:"",problemText:""}},e.blacklist=function(e){for(var t=PasswordMeter.PasswordMeter.instance.getConfig(),s=PasswordMeter.PasswordMeter.instance.getHelper(),r=t.ignoredWords,a="",n="",o="",i="",l=e,c=[],h=new RegExp("[^A-Za-z]"),u=(e=(e=e.toLowerCase()).replace(/[-_ ]/g,"")).split(/[^a-z01345@$]+/),d=(u=u.filter(function(e){return e})).listSubstringsMinMax(1,void 0),g=0;g-1&&(c.push(d[g]),p=d[g])}if(p.length>0){for(0==o.length&&(o=d[g].escapeHTML()),f=0;f-1){u.splice(f,1,u[f].substring(0,b),u[f].substring(b+p.length)),u=u.filter(function(e){return e});break}}d=u.listSubstringsMinMax(1,p.length),p="",g=0}else g++}var v=0;if(c.length>0){for(a="Don't use site-specific terms in your password",g=0;g-1&&(l=l.substr(0,y)+l.substr(y+c[g].length))}n="Don't use site-specific terms ("+Helper.Helper.boldAll(c.removeDuplicates()).toHumanString()+")",i="Attackers target their attacks to words used on a particular service"}return{length:v,reasonWhy:i,publicText:a,sensitiveText:n,problemText:o,remaining:l}},e.combinedDictCheck=function(e){for(var t="",s="",r="",a="",n=100,o=new Array,i=new Array,l=new Array,c=new Array,h=new Array,u=PasswordMeter.PasswordMeter.instance,d=u.getDictionaries(),g=u.getHelper(),p=new Array,m=new Array,f=(e=e.replace(/[-_ ]/g,"")).split(/[^A-Za-z012345!&@$]+/),w=(f=f.filter(function(e){return e})).listSubstringsMinMax(4,void 0),b=0;b0){for(0==r.length&&(r=w[b].escapeHTML()),A=0;A-1){f.splice(A,1,f[A].substring(0,T),f[A].substring(T+v.length)),f=f.filter(function(e){return e});break}}w=f.listSubstringsMinMax(4,v.length),v="",b=0}else b++}var k=new Array,S=new Array,L=0,P=0,E=function(e,t){if(e.length>0){k.push(t);for(var s=0;s0&&(a="Attackers use software that automatically guesses millions of words commonly found in dictionaries, wordlists, or other people's passwords",t="Don't use ",s="Don't use ",n<100&&(a+=", including simple transformations of those words/phrases where they substitute digits and symbols for letters"),t+=k.join(" or "),s+=S.join(" or ")),{length:L,reasonWhy:a,publicText:t,sensitiveText:s,problemText:r,dictionaryTokens:P,substitutionCommonness:n=100-n}},e.identifyDates=function(e){var t=0,s="",r="",a="",n="",o=[],i=PasswordMeter.PasswordMeter.instance.getHelper(),l=[e],c=function(e){var s=i.matchHelper(l,e);s.score>0&&(t+=s.score,o=o.concat(s.matched.toString()),l=s.revisedParts)},h="([ .-/])",u="((0\\d|1[012])|\\d)",d="(january|february|march|april|may|june|july|august|september|october|november|december)",g="([012]\\d|3[01])",p="(\\d\\d)",m="(19\\d\\d|20[01234]\\d)";return c(new RegExp(u+h+g+h+m,"g")),c(new RegExp(g+h+u+h+m,"g")),c(new RegExp(u+h+g+h+p,"g")),c(new RegExp(g+h+u+h+p,"g")),c(new RegExp(u+g+m,"g")),c(new RegExp(g+u+m,"g")),c(new RegExp(d+m,"ig")),c(new RegExp(d+p,"ig")),c(new RegExp(u+h+g,"g")),c(new RegExp(g+h+u,"g")),c(new RegExp(m,"g")),t>0&&(s="Avoid using dates",r="Avoid using dates like "+Helper.Helper.boldAll(o).toHumanString(),n="Dates and years in any format are quite common in passwords",a=o[0].escapeHTML()),{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.alphabeticSequenceCheck=function(e){var t=0,s="",r="",a="",n="",o=[],i=[];o[0]=e.charCodeAt(0);for(var l=1;lh&&0!==d&&(c=u,h=l-u),u=l),1===(t=h)&&(t=0),t>=2&&t++,t>=4){var g=e.substr(c,c+h+1);a=g.escapeHTML();var p=new RegExp("^[0-9]+$");g.match(p)?(s="Avoid numerical patterns",r="Avoid numerical patterns like "+a+""):(s="Avoid patterns from the alphabet",r="Avoid patterns from the alphabet like "+a+""),n="Attackers know to guess sequences following the alphabet, in addition to repeated characters or patterns on your keyboard"}}return{count:t,reasonWhy:n,publicText:s,sensitiveText:r,problemText:a}},e.structurePredictable=function(e){var t="",s="",r="",a=0,n=(e=(e=(e=(e=e.replace(/[A-Z]/g,"U")).replace(/[a-z]/g,"L")).replace(/[0-9]/g,"D")).replace(/[^A-Za-z0-9]/g,"S"),Constants.Constants.commonStructures.indexOf(e));if(n>=0){a=2124-n,r="One technique attackers use is to try all possible passwords within common structures, or arrangements of character classes (e.g., where lowercase letters and digits are located)",s=(t="The way you structure your password is predictable")+" (";for(var o=!0,i=0;i1&&(s+="s"),i+=l}s+=")"}return{score:a,reasonWhy:r,publicText:t,sensitiveText:s}}}(RuleFunctions=exports.RuleFunctions||(exports.RuleFunctions={})); },{"./PasswordMeter":3,"./constants":6,"./helper":8,"./nn-misc":9}],11:[function(require,module,exports){ String.prototype.replaceAt=function(r,t){return this.substr(0,r)+t+this.substr(r+1)},String.prototype.listSubstringsNoFilter=function(r){for(var t=new Array,e=this.toLowerCase(),n=e.length,i=n;i>=r-1;i--)for(var o=0;i+o/g,">")},String.prototype.listSubstrings=function(r){for(var t,e=new Array,n=(t=(t=this.toLowerCase()).replace(/[^a-z]/g,"")).length,i=n;i>=r-1;i--)for(var o=0;i+o0?t+=" and an uppercase letter":t="Contain an uppercase letter");break;case"lowercase letter":e.classRequire.lowerCase&&(t.length>0?t+=" and a lowercase letter":t="Contain a lowercase letter");break;case"digit":e.classRequire.digits&&(t.length>0?t+=" and a digit":t="Contain a digit");break;case"symbol":e.classRequire.symbols&&(t.length>0?t+=" and a symbol":t="Contain a symbol")}}return t},e.prototype.onReady=function(){this.$(".pop").fadeIn(),this.$("#showHidePWNonModal").prop("checked",!1),this.toggleShowHideNonModal(),this.spawnRating()},e.prototype.toggleShowHideNonModal=function(){this.$("#showHidePWNonModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWModal").prop("checked",!1)),this.spawnRating()},e.prototype.toggleShowHideModal=function(){this.$("#showHidePWModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWNonModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWNonModal").prop("checked",!1)),this.spawnRating()},e.prototype.storepw=function(){var e=this.$("#pwbox").val();this.pwWhenModalOpened=e,this.$("#pwboxModal").val(e)},e.prototype.enableDiscard=function(){this.$("#pwboxModal").val()===this.pwWhenModalOpened?(this.$("#discardButton").hide(),this.$("#keepButton").html("OK")):(this.$("#discardButton").show(),this.$("#keepButton").html("Keep Changes"))},e.prototype.keeppw=function(){this.$("#pwbox").val(this.$("#pwboxModal").val())},e.prototype.discardpw=function(){this.$("#pwbox").val(this.pwWhenModalOpened)},e.prototype.fixPWNonModal=function(){this.tookSuggestion=!0;var e=this.$("#nonmodalFixedPW").text();this.$("#pwbox").val(e),this.spawnRating()},e.prototype.fixPWModal=function(){this.tookSuggestion=!0;var e=this.$("#modalFixedPW").text();this.$("#pwboxModal").val(e),this.spawnRating(),this.enableDiscard()},e.prototype.showModal=function(){this.storepw(),this.$("#discardButton").hide(),this.$("#keepButton").html("OK"),this.$("#myModal").modal("show")},e.prototype.mayberate=function(){this.$("#pwbox").val()!==this.previouslyRated&&(this.previouslyRated=this.$("#pwbox").val(),this.spawnRating())},e.prototype.continueCheck=function(e){var t=!0;e&&(this.$("#usernamebox").val().length<1?(this.$("#usernameTooShort").show(),t=!1):this.$("#usernameTooShort").hide());this.inCompliance?(this.$("#feedbackHeaderText").css({color:"","font-weight":""}),this.$("#passwordNonCompliant").hide()):(t=!1,this.$("#confirmDoesNotMatch").hide(),e&&(this.$("#feedbackHeaderText").css({color:"red","font-weight":"bold"}),this.$("#passwordNonCompliant").show())),this.$("#pwbox").val()!==this.$("#confirmbox").val()?(t=!1,e&&this.inCompliance&&this.$("#confirmDoesNotMatch").show()):this.$("#confirmDoesNotMatch").hide(),e&&t&&alert("this would be submitted")},e.prototype.scaleGuessNumByMeterStringencyFactor=function(e){return e>0?e*Constants.Constants.METER_STRINGENCY_SCALE_FACTOR:e},e.prototype.spawnRating=function(){var e="",t=PasswordMeter.PasswordMeter.instance.getNN();e=this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown?this.$("#pwboxModal").val():this.$("#pwbox").val();var s=this.$("#usernamebox").val(),i=0,o=t.getNeuralNetNum(e);void 0===o?(t.setNeuralNetNum(e,-1),t.queryGuessNumber(e,!1)):o>=0&&i++,void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!0):this.heuristicMapping[e]>=0&&i++,0!==e.length&&t.heardFromNn()&&2!==i||this.displayRating(e)},e.prototype.generateCandidateFixed=function(e,t,s){if(!PasswordMeter.PasswordMeter.instance.getConfig().provideConcretePasswordSuggestions)return 1;var i=[];if(void 0===this.deltaHighlighted[e])for(var o=0;o=65&&n.charCodeAt(r)<=90?(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)+32)),i[r]=1):n.charCodeAt(r)>=97&&n.charCodeAt(r)<=122&&(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)-32)),i[r]=1)}else if(2===a||3===a){var l=32+Math.floor(95*Math.random()),d=Math.floor(n.length*Math.random());n.charCodeAt(d)!==l&&(i[d]=1),n=n.replaceAt(d,String.fromCharCode(l))}else if(a>=4){l=32+Math.floor(95*Math.random()),d=Math.floor((n.length+1)*Math.random());n=n.slice(0,d)+String.fromCharCode(l)+n.slice(d),i=i.slice(0,d).concat(1,i.slice(d))}var p=PasswordMeter.PasswordMeter.instance.getNN();void 0===p.getNeuralNetNum(n)&&(p.setNeuralNetNum(n,-1),p.queryGuessNumber(n,!0));var u=this.$("#usernamebox").val();return void 0===this.heuristicMapping[n]&&this.queryHeuristicGuessNumber(n,u,!1),RuleFunctions.RuleFunctions.verifyMinimumRequirements(n,u).compliant?(this.recommendedFixes[s]=n,this.deltaHighlighted[n]=i,this.verboseMode&&console.log("identified "+n+" as a potential fix for "+s),void 0===this.recommendedFixesTries[s]?this.recommendedFixesTries[s]=1:this.recommendedFixesTries[s]=this.recommendedFixesTries[s]+1,this.spawnFixedRating(n)):++t<8&&this.generateCandidateFixed(e,t,s),1},e.prototype.spawnFixedRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=this.$("#usernamebox").val();void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!1):t.getNeuralNetNum(e)>=0&&this.heuristicMapping[e]>=0&&this.synthesizeFixed(e)},e.prototype.synthesizeFixed=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0,o=!1;void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(i++,s=this.heuristicMapping[e]);var n=t.getNeuralNetNum(e),a=this.scaleGuessNumByMeterStringencyFactor(n);if(void 0!==n&&a>=0&&isFinite(a)&&(i++,(0===s||s>0&&a=67){for(var h in this.verboseMode&&console.log(e+" is a plausible fix above the 2/3rds threshold"),this.recommendedFixes)if(this.recommendedFixes[h]===e&&void 0===this.fixedpwMapping[h]){var r=0;void 0!==this.heuristicMapping[h]&&this.heuristicMapping[h]>=0&&(r=this.heuristicMapping[h]);var l=t.getNeuralNetNum(h),d=this.scaleGuessNumByMeterStringencyFactor(l);void 0!==l&&d>=0&&isFinite(d)&&(0===r||r>0&&dr+15?(this.fixedpwMapping[h]=e,console.log("mapping "+h+" to "+e),this.verboseMode&&console.log("mapping "+h+" to "+e),o=!0):(console.log("not mapping "+h+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s),this.verboseMode&&console.log("not mapping "+h+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s))}return o&&this.spawnRating(),1}var p=this.$("#pwbox").val();return this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown&&(p=this.$("#pwboxModal").val()),this.recommendedFixes[p]===e&&2===i&&void 0===this.fixedpwMapping[p]&&void 0!==this.recommendedFixesTries[p]&&this.recommendedFixesTries[p]<8&&(this.verboseMode&&console.log("trying again on "+e+" as current password is "+p),console.log("trying again on "+e+" as current password is "+p),this.generateCandidateFixed(e,0,p)),1},e.prototype.redundant=function(e,t){e=e.toLowerCase();for(var s=0;s0&&e.length>0&&(t[s].indexOf(e)>=0&&e.length>=.7*t[s].length||e.indexOf(t[s])>=0&&t[s].length>=.7*e.length))return!0;return!1},e.prototype.queryHeuristicGuessNumber=function(e,t,s){var i=e,o=[],n=[],a=[],h=[],r=RuleFunctions.RuleFunctions.contextual(e,[t]);void 0===(e=r.remaining)&&(e="");var l=RuleFunctions.RuleFunctions.blacklist(e);void 0===(e=l.remaining)&&(e="");for(var d=RuleFunctions.RuleFunctions.pwLength(e),p=RuleFunctions.RuleFunctions.characterClasses(e),u=RuleFunctions.RuleFunctions.duplicatedCharacters(e),c=RuleFunctions.RuleFunctions.repeats(e),m=RuleFunctions.RuleFunctions.keyboardPatterns(e),g=RuleFunctions.RuleFunctions.repeatedSections(e),w=RuleFunctions.RuleFunctions.structurePredictable(e),b=RuleFunctions.RuleFunctions.uppercasePredictable(e),x=RuleFunctions.RuleFunctions.digitsPredictable(e),y=RuleFunctions.RuleFunctions.symbolsPredictable(e),$=RuleFunctions.RuleFunctions.countUC(e),v=RuleFunctions.RuleFunctions.countLC(e),M=RuleFunctions.RuleFunctions.countDIGS(e),f=RuleFunctions.RuleFunctions.countSYMS(e),T=RuleFunctions.RuleFunctions.identifyDates(e),R=(RuleFunctions.RuleFunctions.verifyMinimumRequirements(e,t),RuleFunctions.RuleFunctions.alphabeticSequenceCheck(e)),C=RuleFunctions.RuleFunctions.commonSubstringCheck(e),F=RuleFunctions.RuleFunctions.combinedDictCheck(e),N=e.listSubstringsNoFilter(4),k=RuleFunctions.RuleFunctions.commonPwCheck(N),W=[1.53,.3129,.9912,.04637,-.03885,-.1172,-.2976,-8581e-7,-.3008,-.5566,0,.9108,.7369,.7578,0,-.1213,-.2402,-.1364,-.5534,1.927,.001496,-.3946],P=[1,d.length,p.count,u.count,c.count,m.score,g.count,w.score,b.score,x.score,y.score,$.count,v.count,M.count,f.count,T.count,R.count,C.count,F.length,F.dictionaryTokens,F.substitutionCommonness,k.length],S=W[0],H=1;H100&&(S=100),r.publicText.length>0&&(o.push(r.publicText),n.push(r.sensitiveText),a.push(r.reasonWhy),h.push(r.problemText)),l.publicText.length>0&&(o.push(l.publicText),n.push(l.sensitiveText),a.push(l.reasonWhy),h.push(l.problemText)),F.publicText.length>0&&!this.redundant(F.problemText,h)&&(o.push(F.publicText),n.push(F.sensitiveText),a.push(F.reasonWhy),h.push(F.problemText)),m.publicText.length>0&&(o.push(m.publicText),n.push(m.sensitiveText),a.push(m.reasonWhy),h.push(m.problemText)),c.publicText.length>0&&(o.push(c.publicText),n.push(c.sensitiveText),a.push(c.reasonWhy),h.push(c.problemText)),T.publicText.length>0&&(o.push(T.publicText),n.push(T.sensitiveText),a.push(T.reasonWhy),h.push(T.problemText)),g.publicText.length>0&&(o.push(g.publicText),n.push(g.sensitiveText),a.push(g.reasonWhy),h.push(g.problemText)),R.publicText.length>0&&(o.push(R.publicText),n.push(R.sensitiveText),a.push(R.reasonWhy),h.push(R.problemText)),k.publicText.length>0&&!this.redundant(k.problemText,h)&&(o.push(k.publicText),n.push(k.sensitiveText),a.push(k.reasonWhy),h.push(k.problemText)),b.publicText.length>0&&(o.push(b.publicText),n.push(b.sensitiveText),a.push(b.reasonWhy),h.push(b.problemText)),x.publicText.length>0&&(o.push(x.publicText),n.push(x.sensitiveText),a.push(x.reasonWhy),h.push(x.problemText)),y.publicText.length>0&&(o.push(y.publicText),n.push(y.sensitiveText),a.push(y.reasonWhy),h.push(y.problemText)),u.publicText.length>0&&(o.push(u.publicText),n.push(u.sensitiveText),a.push(u.reasonWhy),h.push(u.problemText)),d.publicText.length>0&&(o.push(d.publicText),n.push(d.sensitiveText),a.push(d.reasonWhy)),f.publicText.length>0&&(o.push(f.publicText),n.push(f.sensitiveText),a.push(f.reasonWhy)),$.publicText.length>0&&(o.push($.publicText),n.push($.sensitiveText),a.push($.reasonWhy)),M.publicText.length>0&&(o.push(M.publicText),n.push(M.sensitiveText),a.push(M.reasonWhy)),v.publicText.length>0&&(o.push(v.publicText),n.push(v.sensitiveText),a.push(v.reasonWhy)),C.publicText.length>0&&!this.redundant(C.problemText,h)&&(o.push(C.publicText),n.push(C.sensitiveText),a.push(C.reasonWhy)),w.publicText.length>0&&(o.push(w.publicText),n.push(w.sensitiveText),a.push(w.reasonWhy)),this.heuristicMapping[i]=S,this.feedbackMapping[i]=JSON.stringify({publictips1:o[0],publictips2:o[1],publictips3:o[2],sensitivetips1:n[0],sensitivetips2:n[1],sensitivetips3:n[2],reasonWhy1:a[0],reasonWhy2:a[1],reasonWhy3:a[2]}),s?(this.displayRating(i),x.fixedPw.length>0?(this.previousCandidate[i]=x.fixedPw,this.deltaHighlighted[x.fixedPw]=x.deltas):y.fixedPw.length>0&&(this.previousCandidate[i]=y.fixedPw,this.deltaHighlighted[y.fixedPw]=y.deltas)):this.synthesizeFixed(i)},e.prototype.displayRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0;if(e.length>0){void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(s=this.heuristicMapping[e],i++);var o=t.getNeuralNetNum(e),n=this.scaleGuessNumByMeterStringencyFactor(o);void 0!==o&&n>=0&&isFinite(n)&&(i++,(0==s||s>0&&n(Why?)"),d+="

 

To make it even better:",this.$("#feedbackHeaderText").html(d),this.$("#feedbackHeaderTextModal").html(d)}else{var p="Your password appears strong.";h.remindAgainstReuse&&(p+=" Make sure you use it only for this account. (Why?)"),this.$("#feedbackHeaderText").html(p),this.$("#feedbackHeaderTextModal").html(p)}if(this.$(".nonmodalColorCell").show(),this.$(".modalColorCell").show(),this.$(".modalColorCellSpacer").show(),this.$(".recommended").show(),!0===this.$("#showHidePWNonModal").prop("checked")?(this.$(".fixedPWavailablePortal").hide(),this.$(".concreteSuggestionDiv").show(),this.$("#tipText1").html(a.sensitivetips1),this.$("#tipText2").html(a.sensitivetips2),this.$("#tipText3").html(a.sensitivetips3),this.$("#suggestion1").html(a.sensitivetips1),this.$("#suggestion2").html(a.sensitivetips2),this.$("#suggestion3").html(a.sensitivetips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)):(this.$(".fixedPWavailablePortal").show(),this.$(".concreteSuggestionDiv").hide(),this.$("#tipText1").html(a.publictips1),this.$("#tipText2").html(a.publictips2),this.$("#tipText3").html(a.publictips3),this.$("#suggestion1").html(a.publictips1),this.$("#suggestion2").html(a.publictips2),this.$("#suggestion3").html(a.publictips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)),h.provideConcretePasswordSuggestions&&void 0!==this.fixedpwMapping[e]){for(var u="",c=this.deltaHighlighted[this.fixedpwMapping[e]],m=this.fixedpwMapping[e],g=0;g"+m[g].escapeHTML()+"
":u+=m[g].escapeHTML();this.$(".fixedPW").html(u)}else this.$(".recommended").hide();s<=66?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show()):s<100?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show(),this.tookSuggestion&&(console.log("already took suggestion for "+e+" so hiding recs"),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())):(console.log("overall score is above 66 so for "+e+" so hiding recs"),this.$("#nonmodalFeedbackTable").hide(),this.$("#modalFeedbackTable").hide(),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())}else{this.inCompliance=!1,0!==e.length&&t.heardFromNn()&&2!==i||this.displayBar(s,!1),this.$("#confirmpw").hide(),this.$(".detailedFeedback").hide(),this.$(".portalToGenericAdviceModal").show(),this.$(".explainWhy").hide();var w="";(h=PasswordMeter.PasswordMeter.instance.getConfig()).remindAgainstReuse&&(w="Don't reuse a password from another account! (Why?)

 

");var b="Your password must:";this.$("#feedbackHeaderText").html(w+b),this.$("#feedbackHeaderTextModal").html(w+b),this.$("#nonmodalFeedbackTable").show(),this.$(".recommended").hide();var x=[],y=l.detail;for(var $ in y.compliance)y.compliance[$]||x.push(y.explanation[$]);this.$(".nonmodalColorCell").hide(),this.$(".modalColorCell").hide(),this.$(".modalColorCellSpacer").hide(),this.$(".nonmodalRow").hide(),this.$(".modalRow").hide();for(var v=0;v100&&(e=100);var s=e/100,i="rgb(160,160,160)";t&&s<.45?i="rgb("+Math.round(255)+","+Math.round(s/.45*140)+",0)":t&&s>=.45&&s<.65?i="rgb("+Math.round(255)+","+Math.round((s-.45)/.2*75+140)+",0)":t&&(i="rgb("+Math.round(255-(s-.65)/.35*205)+","+Math.round(215-(s-.65)/.035)+",0)"),this.$("#cups-passwordmeter-span").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span").css("background-color",i),this.$("#cups-passwordmeter-span-modal").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span-modal").css("background-color",i)},e.prototype.getMaxOfArray=function(e){return Math.max.apply(null,e)},e.prototype.expandHelpBut=function(){this.$("#expandHelpDiv").show(),this.$("#helpButton").hide()},e.prototype.modalShowCheck=function(){"text"==this.$("#pwbox").prop("type")?(this.$("#myModal").show(),this.storepw()):this.$("#expandHelpDiv").is(":visible")?(this.$("#myModal").show(),this.storepw()):this.expandHelpBut()},e.prototype.closeDiv=function(e){this.$(e).hide()},e.prototype.deselect=function(e){null==this.$.fn.slideFadeToggle&&(this.$.fn.slideFadeToggle=function(e,t){return this.animate({opacity:"toggle",height:"toggle"},"fast",e,t)}),this.$(".pop").slideFadeToggle(function(){e.removeClass("selected")})},e}();e.UIMisc=o,t=PasswordMeter.PasswordMeter.instance,s=t.getJquery(),i=new o(!1),t.setUI(i),s(document).ready(function(){s("#showpassword").prop("checked",!1),s("#showpassword").click(function(){document.getElementById("hide-show-label").textContent="Hide Password",s("#cbbutton").css("background-color","#f5f5f5"),"password"==s("#pwbox").prop("type")?s("#pwbox").prop("type","text"):(s("#pwbox").prop("type","password"),document.getElementById("hide-show-label").textContent="Show Password",s("#cbbutton").css("background-color","#f5f5f5"))})}),s(document).ready(function(){var e=s("#pwboxModal");s("#tip1, #sensText1").mouseover(function(){e.addClass("problemColor")}),s("#tip2, #sensText2").mouseover(function(){e.addClass("problemColor")}),s("#tip3, #sensText3").mouseover(function(){e.addClass("problemColor")})}),s(document).ready(function(){i.onReady()})}(UIMisc=exports.UIMisc||(exports.UIMisc={})); +"use strict";exports.__esModule=!0;var UIMisc,PasswordMeter=require("./PasswordMeter"),RuleFunctions=require("./rulefunctions"),Constants=require("./constants");!function(e){var t,s,i,o=function(){function e(e){this.pwWhenModalOpened="",this.tookSuggestion=!1,this.previouslyRated="",this.heuristicMapping={},this.feedbackMapping={},this.recommendedFixes={},this.recommendedFixesTries={},this.previousCandidate={},this.fixedpwMapping={},this.deltaHighlighted={},this.inCompliance=!1,this.randomlyOrderedCharClasses=[];var t=PasswordMeter.PasswordMeter.instance;this.helper=t.getHelper(),this.$=t.getJquery(),this.verboseMode=e;this.randomlyOrderedCharClasses=function(e){for(var t,s,i=e.length;0!==i;)s=Math.floor(Math.random()*i),t=e[i-=1],e[i]=e[s],e[s]=t;return e}(["uppercase letter","lowercase letter","digit","symbol"])}return e.prototype.getCharClassStringForCharClassCountReq=function(){return this.randomlyOrderedCharClasses.map(function(e){return e+"s"}).join("; ")},e.prototype.getCharClassStringForMandatoryCharClassReq=function(){for(var e=PasswordMeter.PasswordMeter.instance.getConfig(),t="",s=0;s0?t+=" and an uppercase letter":t="Contain an uppercase letter");break;case"lowercase letter":e.classRequire.lowerCase&&(t.length>0?t+=" and a lowercase letter":t="Contain a lowercase letter");break;case"digit":e.classRequire.digits&&(t.length>0?t+=" and a digit":t="Contain a digit");break;case"symbol":e.classRequire.symbols&&(t.length>0?t+=" and a symbol":t="Contain a symbol")}}return t},e.prototype.onReady=function(){this.$(".pop").fadeIn(),this.$("#showHidePWNonModal").prop("checked",!1),this.toggleShowHideNonModal(),this.spawnRating()},e.prototype.toggleShowHideNonModal=function(){this.$("#showHidePWNonModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWModal").prop("checked",!1)),this.spawnRating()},e.prototype.toggleShowHideModal=function(){this.$("#showHidePWModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWNonModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWNonModal").prop("checked",!1)),this.spawnRating()},e.prototype.storepw=function(){var e=this.$("#pwbox").val();this.pwWhenModalOpened=e,this.$("#pwboxModal").val(e)},e.prototype.enableDiscard=function(){this.$("#pwboxModal").val()===this.pwWhenModalOpened?(this.$("#discardButton").hide(),this.$("#keepButton").html("OK")):(this.$("#discardButton").show(),this.$("#keepButton").html("Keep Changes"))},e.prototype.keeppw=function(){this.$("#pwbox").val(this.$("#pwboxModal").val())},e.prototype.discardpw=function(){this.$("#pwbox").val(this.pwWhenModalOpened)},e.prototype.fixPWNonModal=function(){this.tookSuggestion=!0;var e=this.$("#nonmodalFixedPW").text();this.$("#pwbox").val(e),this.spawnRating()},e.prototype.fixPWModal=function(){this.tookSuggestion=!0;var e=this.$("#modalFixedPW").text();this.$("#pwboxModal").val(e),this.spawnRating(),this.enableDiscard()},e.prototype.showModal=function(){this.storepw(),this.$("#discardButton").hide(),this.$("#keepButton").html("OK"),this.$("#myModal").modal("show")},e.prototype.mayberate=function(){this.$("#pwbox").val()!==this.previouslyRated&&(this.previouslyRated=this.$("#pwbox").val(),this.spawnRating())},e.prototype.continueCheck=function(e){var t=!0;e&&(this.$("#usernamebox").val().length<1?(this.$("#usernameTooShort").show(),t=!1):this.$("#usernameTooShort").hide());this.inCompliance?(this.$("#feedbackHeaderText").css({color:"","font-weight":""}),this.$("#passwordNonCompliant").hide()):(t=!1,this.$("#confirmDoesNotMatch").hide(),e&&(this.$("#feedbackHeaderText").css({color:"red","font-weight":"bold"}),this.$("#passwordNonCompliant").show())),this.$("#pwbox").val()!==this.$("#confirmbox").val()?(t=!1,e&&this.inCompliance&&this.$("#confirmDoesNotMatch").show()):this.$("#confirmDoesNotMatch").hide(),e&&t&&alert("this would be submitted")},e.prototype.scaleGuessNumByMeterStringencyFactor=function(e){return e>0?e*Constants.Constants.METER_STRINGENCY_SCALE_FACTOR:e},e.prototype.spawnRating=function(){var e="",t=PasswordMeter.PasswordMeter.instance.getNN();e=this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown?this.$("#pwboxModal").val():this.$("#pwbox").val();var s=this.$("#usernamebox").val(),i=0,o=t.getNeuralNetNum(e);void 0===o?(t.setNeuralNetNum(e,-1),t.queryGuessNumber(e,!1)):o>=0&&i++,void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!0):this.heuristicMapping[e]>=0&&i++,0!==e.length&&t.heardFromNn()&&2!==i||this.displayRating(e)},e.prototype.generateCandidateFixed=function(e,t,s){if(!PasswordMeter.PasswordMeter.instance.getConfig().provideConcretePasswordSuggestions)return 1;var i=[];if(void 0===this.deltaHighlighted[e])for(var o=0;o=65&&n.charCodeAt(r)<=90?(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)+32)),i[r]=1):n.charCodeAt(r)>=97&&n.charCodeAt(r)<=122&&(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)-32)),i[r]=1)}else if(2===a||3===a){var l=32+Math.floor(95*Math.random()),d=Math.floor(n.length*Math.random());n.charCodeAt(d)!==l&&(i[d]=1),n=n.replaceAt(d,String.fromCharCode(l))}else if(a>=4){l=32+Math.floor(95*Math.random()),d=Math.floor((n.length+1)*Math.random());n=n.slice(0,d)+String.fromCharCode(l)+n.slice(d),i=i.slice(0,d).concat(1,i.slice(d))}var p=PasswordMeter.PasswordMeter.instance.getNN();void 0===p.getNeuralNetNum(n)&&(p.setNeuralNetNum(n,-1),p.queryGuessNumber(n,!0));var u=this.$("#usernamebox").val();return void 0===this.heuristicMapping[n]&&this.queryHeuristicGuessNumber(n,u,!1),RuleFunctions.RuleFunctions.verifyMinimumRequirements(n,u).compliant?(this.recommendedFixes[s]=n,this.deltaHighlighted[n]=i,this.verboseMode&&console.log("identified "+n+" as a potential fix for "+s),void 0===this.recommendedFixesTries[s]?this.recommendedFixesTries[s]=1:this.recommendedFixesTries[s]=this.recommendedFixesTries[s]+1,this.spawnFixedRating(n)):++t<8&&this.generateCandidateFixed(e,t,s),1},e.prototype.spawnFixedRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=this.$("#usernamebox").val();void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!1):t.getNeuralNetNum(e)>=0&&this.heuristicMapping[e]>=0&&this.synthesizeFixed(e)},e.prototype.synthesizeFixed=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0,o=!1;void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(i++,s=this.heuristicMapping[e]);var n=t.getNeuralNetNum(e),a=this.scaleGuessNumByMeterStringencyFactor(n);if(void 0!==n&&a>=0&&isFinite(a)&&(i++,(0===s||s>0&&a=67){for(var h in this.verboseMode&&console.log(e+" is a plausible fix above the 2/3rds threshold"),this.recommendedFixes)if(this.recommendedFixes[h]===e&&void 0===this.fixedpwMapping[h]){var r=0;void 0!==this.heuristicMapping[h]&&this.heuristicMapping[h]>=0&&(r=this.heuristicMapping[h]);var l=t.getNeuralNetNum(h),d=this.scaleGuessNumByMeterStringencyFactor(l);void 0!==l&&d>=0&&isFinite(d)&&(0===r||r>0&&dr+15?(this.fixedpwMapping[h]=e,this.verboseMode&&console.log("mapping "+h+" to "+e),o=!0):this.verboseMode&&console.log("not mapping "+h+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s)}return o&&this.spawnRating(),1}var p=this.$("#pwbox").val();return this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown&&(p=this.$("#pwboxModal").val()),this.recommendedFixes[p]===e&&2===i&&void 0===this.fixedpwMapping[p]&&void 0!==this.recommendedFixesTries[p]&&this.recommendedFixesTries[p]<8&&(this.verboseMode&&console.log("trying again on "+e+" as current password is "+p),this.generateCandidateFixed(e,0,p)),1},e.prototype.redundant=function(e,t){e=e.toLowerCase();for(var s=0;s0&&e.length>0&&(t[s].indexOf(e)>=0&&e.length>=.7*t[s].length||e.indexOf(t[s])>=0&&t[s].length>=.7*e.length))return!0;return!1},e.prototype.queryHeuristicGuessNumber=function(e,t,s){var i=e,o=[],n=[],a=[],h=[],r=RuleFunctions.RuleFunctions.contextual(e,[t]);void 0===(e=r.remaining)&&(e="");var l=RuleFunctions.RuleFunctions.blacklist(e);void 0===(e=l.remaining)&&(e="");for(var d=RuleFunctions.RuleFunctions.pwLength(e),p=RuleFunctions.RuleFunctions.characterClasses(e),u=RuleFunctions.RuleFunctions.duplicatedCharacters(e),c=RuleFunctions.RuleFunctions.repeats(e),m=RuleFunctions.RuleFunctions.keyboardPatterns(e),g=RuleFunctions.RuleFunctions.repeatedSections(e),w=RuleFunctions.RuleFunctions.structurePredictable(e),x=RuleFunctions.RuleFunctions.uppercasePredictable(e),b=RuleFunctions.RuleFunctions.digitsPredictable(e),$=RuleFunctions.RuleFunctions.symbolsPredictable(e),y=RuleFunctions.RuleFunctions.countUC(e),v=RuleFunctions.RuleFunctions.countLC(e),M=RuleFunctions.RuleFunctions.countDIGS(e),f=RuleFunctions.RuleFunctions.countSYMS(e),T=RuleFunctions.RuleFunctions.identifyDates(e),R=(RuleFunctions.RuleFunctions.verifyMinimumRequirements(e,t),RuleFunctions.RuleFunctions.alphabeticSequenceCheck(e)),C=RuleFunctions.RuleFunctions.commonSubstringCheck(e),F=RuleFunctions.RuleFunctions.combinedDictCheck(e),N=e.listSubstringsNoFilter(4),k=RuleFunctions.RuleFunctions.commonPwCheck(N),W=[1.53,.3129,.9912,.04637,-.03885,-.1172,-.2976,-8581e-7,-.3008,-.5566,0,.9108,.7369,.7578,0,-.1213,-.2402,-.1364,-.5534,1.927,.001496,-.3946],P=[1,d.length,p.count,u.count,c.count,m.score,g.count,w.score,x.score,b.score,$.score,y.count,v.count,M.count,f.count,T.count,R.count,C.count,F.length,F.dictionaryTokens,F.substitutionCommonness,k.length],S=W[0],H=1;H100&&(S=100),r.publicText.length>0&&(o.push(r.publicText),n.push(r.sensitiveText),a.push(r.reasonWhy),h.push(r.problemText)),l.publicText.length>0&&(o.push(l.publicText),n.push(l.sensitiveText),a.push(l.reasonWhy),h.push(l.problemText)),F.publicText.length>0&&!this.redundant(F.problemText,h)&&(o.push(F.publicText),n.push(F.sensitiveText),a.push(F.reasonWhy),h.push(F.problemText)),m.publicText.length>0&&(o.push(m.publicText),n.push(m.sensitiveText),a.push(m.reasonWhy),h.push(m.problemText)),c.publicText.length>0&&(o.push(c.publicText),n.push(c.sensitiveText),a.push(c.reasonWhy),h.push(c.problemText)),T.publicText.length>0&&(o.push(T.publicText),n.push(T.sensitiveText),a.push(T.reasonWhy),h.push(T.problemText)),g.publicText.length>0&&(o.push(g.publicText),n.push(g.sensitiveText),a.push(g.reasonWhy),h.push(g.problemText)),R.publicText.length>0&&(o.push(R.publicText),n.push(R.sensitiveText),a.push(R.reasonWhy),h.push(R.problemText)),k.publicText.length>0&&!this.redundant(k.problemText,h)&&(o.push(k.publicText),n.push(k.sensitiveText),a.push(k.reasonWhy),h.push(k.problemText)),x.publicText.length>0&&(o.push(x.publicText),n.push(x.sensitiveText),a.push(x.reasonWhy),h.push(x.problemText)),b.publicText.length>0&&(o.push(b.publicText),n.push(b.sensitiveText),a.push(b.reasonWhy),h.push(b.problemText)),$.publicText.length>0&&(o.push($.publicText),n.push($.sensitiveText),a.push($.reasonWhy),h.push($.problemText)),u.publicText.length>0&&(o.push(u.publicText),n.push(u.sensitiveText),a.push(u.reasonWhy),h.push(u.problemText)),d.publicText.length>0&&(o.push(d.publicText),n.push(d.sensitiveText),a.push(d.reasonWhy)),f.publicText.length>0&&(o.push(f.publicText),n.push(f.sensitiveText),a.push(f.reasonWhy)),y.publicText.length>0&&(o.push(y.publicText),n.push(y.sensitiveText),a.push(y.reasonWhy)),M.publicText.length>0&&(o.push(M.publicText),n.push(M.sensitiveText),a.push(M.reasonWhy)),v.publicText.length>0&&(o.push(v.publicText),n.push(v.sensitiveText),a.push(v.reasonWhy)),C.publicText.length>0&&!this.redundant(C.problemText,h)&&(o.push(C.publicText),n.push(C.sensitiveText),a.push(C.reasonWhy)),w.publicText.length>0&&(o.push(w.publicText),n.push(w.sensitiveText),a.push(w.reasonWhy)),this.heuristicMapping[i]=S,this.feedbackMapping[i]=JSON.stringify({publictips1:o[0],publictips2:o[1],publictips3:o[2],sensitivetips1:n[0],sensitivetips2:n[1],sensitivetips3:n[2],reasonWhy1:a[0],reasonWhy2:a[1],reasonWhy3:a[2]}),s?(this.displayRating(i),b.fixedPw.length>0?(this.previousCandidate[i]=b.fixedPw,this.deltaHighlighted[b.fixedPw]=b.deltas):$.fixedPw.length>0&&(this.previousCandidate[i]=$.fixedPw,this.deltaHighlighted[$.fixedPw]=$.deltas)):this.synthesizeFixed(i)},e.prototype.displayRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0;if(e.length>0){void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(s=this.heuristicMapping[e],i++);var o=t.getNeuralNetNum(e),n=this.scaleGuessNumByMeterStringencyFactor(o);void 0!==o&&n>=0&&isFinite(n)&&(i++,(0==s||s>0&&n(Why?)
"),d+="

 

To make it even better:",this.$("#feedbackHeaderText").html(d),this.$("#feedbackHeaderTextModal").html(d)}else{var p="Your password appears strong.";h.remindAgainstReuse&&(p+=" Make sure you use it only for this account. (Why?)"),this.$("#feedbackHeaderText").html(p),this.$("#feedbackHeaderTextModal").html(p)}if(this.$(".nonmodalColorCell").show(),this.$(".modalColorCell").show(),this.$(".modalColorCellSpacer").show(),this.$(".recommended").show(),!0===this.$("#showHidePWNonModal").prop("checked")?(this.$(".fixedPWavailablePortal").hide(),this.$(".concreteSuggestionDiv").show(),this.$("#tipText1").html(a.sensitivetips1),this.$("#tipText2").html(a.sensitivetips2),this.$("#tipText3").html(a.sensitivetips3),this.$("#suggestion1").html(a.sensitivetips1),this.$("#suggestion2").html(a.sensitivetips2),this.$("#suggestion3").html(a.sensitivetips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)):(this.$(".fixedPWavailablePortal").show(),this.$(".concreteSuggestionDiv").hide(),this.$("#tipText1").html(a.publictips1),this.$("#tipText2").html(a.publictips2),this.$("#tipText3").html(a.publictips3),this.$("#suggestion1").html(a.publictips1),this.$("#suggestion2").html(a.publictips2),this.$("#suggestion3").html(a.publictips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)),h.provideConcretePasswordSuggestions&&void 0!==this.fixedpwMapping[e]){for(var u="",c=this.deltaHighlighted[this.fixedpwMapping[e]],m=this.fixedpwMapping[e],g=0;g"+m[g].escapeHTML()+"
":u+=m[g].escapeHTML();this.$(".fixedPW").html(u)}else this.$(".recommended").hide();s<=66?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show()):s<100?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show(),this.tookSuggestion&&(this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())):(this.$("#nonmodalFeedbackTable").hide(),this.$("#modalFeedbackTable").hide(),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())}else{this.inCompliance=!1,0!==e.length&&t.heardFromNn()&&2!==i||this.displayBar(s,!1),this.$("#confirmpw").hide(),this.$(".detailedFeedback").hide(),this.$(".portalToGenericAdviceModal").show(),this.$(".explainWhy").hide();var w="";(h=PasswordMeter.PasswordMeter.instance.getConfig()).remindAgainstReuse&&(w="Don't reuse a password from another account! (Why?)

 

");var x="Your password must:";this.$("#feedbackHeaderText").html(w+x),this.$("#feedbackHeaderTextModal").html(w+x),this.$("#nonmodalFeedbackTable").show(),this.$(".recommended").hide();var b=[],$=l.detail;for(var y in $.compliance)$.compliance[y]||b.push($.explanation[y]);this.$(".nonmodalColorCell").hide(),this.$(".modalColorCell").hide(),this.$(".modalColorCellSpacer").hide(),this.$(".nonmodalRow").hide(),this.$(".modalRow").hide();for(var v=0;v100&&(e=100);var s=e/100,i="rgb(160,160,160)";t&&s<.45?i="rgb("+Math.round(255)+","+Math.round(s/.45*140)+",0)":t&&s>=.45&&s<.65?i="rgb("+Math.round(255)+","+Math.round((s-.45)/.2*75+140)+",0)":t&&(i="rgb("+Math.round(255-(s-.65)/.35*205)+","+Math.round(215-(s-.65)/.035)+",0)"),this.$("#cups-passwordmeter-span").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span").css("background-color",i),this.$("#cups-passwordmeter-span-modal").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span-modal").css("background-color",i)},e.prototype.getMaxOfArray=function(e){return Math.max.apply(null,e)},e.prototype.expandHelpBut=function(){this.$("#expandHelpDiv").show(),this.$("#helpButton").hide()},e.prototype.modalShowCheck=function(){"text"==this.$("#pwbox").prop("type")?(this.$("#myModal").show(),this.storepw()):this.$("#expandHelpDiv").is(":visible")?(this.$("#myModal").show(),this.storepw()):this.expandHelpBut()},e.prototype.closeDiv=function(e){this.$(e).hide()},e.prototype.deselect=function(e){null==this.$.fn.slideFadeToggle&&(this.$.fn.slideFadeToggle=function(e,t){return this.animate({opacity:"toggle",height:"toggle"},"fast",e,t)}),this.$(".pop").slideFadeToggle(function(){e.removeClass("selected")})},e}();e.UIMisc=o,t=PasswordMeter.PasswordMeter.instance,s=t.getJquery(),i=new o(!1),t.setUI(i),s(document).ready(function(){s("#showpassword").prop("checked",!1),s("#showpassword").click(function(){document.getElementById("hide-show-label").textContent="Hide Password",s("#cbbutton").css("background-color","#f5f5f5"),"password"==s("#pwbox").prop("type")?s("#pwbox").prop("type","text"):(s("#pwbox").prop("type","password"),document.getElementById("hide-show-label").textContent="Show Password",s("#cbbutton").css("background-color","#f5f5f5"))})}),s(document).ready(function(){var e=s("#pwboxModal");s("#tip1, #sensText1").mouseover(function(){e.addClass("problemColor")}),s("#tip2, #sensText2").mouseover(function(){e.addClass("problemColor")}),s("#tip3, #sensText3").mouseover(function(){e.addClass("problemColor")})}),s(document).ready(function(){i.onReady()})}(UIMisc=exports.UIMisc||(exports.UIMisc={})); },{"./PasswordMeter":3,"./constants":6,"./rulefunctions":10}]},{},[3,4,5,6,7,8,9,10,11,12]); From f94e4bbe41f917b6967613593d17a36b481a4331 Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Wed, 6 Mar 2019 17:53:47 -0500 Subject: [PATCH 15/45] Added ID fields and event triggers needed for userstudy instrumentation. --- src/PasswordMeter.js | 2 +- src/ts/ui-misc.ts | 26 +++++++++++++++++--------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/PasswordMeter.js b/src/PasswordMeter.js index 50b004f..646e74d 100644 --- a/src/PasswordMeter.js +++ b/src/PasswordMeter.js @@ -32,6 +32,6 @@ Array.prototype.toHumanString=function(){var t=this.length;if(0==t)return"(empty String.prototype.replaceAt=function(r,t){return this.substr(0,r)+t+this.substr(r+1)},String.prototype.listSubstringsNoFilter=function(r){for(var t=new Array,e=this.toLowerCase(),n=e.length,i=n;i>=r-1;i--)for(var o=0;i+o/g,">")},String.prototype.listSubstrings=function(r){for(var t,e=new Array,n=(t=(t=this.toLowerCase()).replace(/[^a-z]/g,"")).length,i=n;i>=r-1;i--)for(var o=0;i+o0?t+=" and an uppercase letter":t="Contain an uppercase letter");break;case"lowercase letter":e.classRequire.lowerCase&&(t.length>0?t+=" and a lowercase letter":t="Contain a lowercase letter");break;case"digit":e.classRequire.digits&&(t.length>0?t+=" and a digit":t="Contain a digit");break;case"symbol":e.classRequire.symbols&&(t.length>0?t+=" and a symbol":t="Contain a symbol")}}return t},e.prototype.onReady=function(){this.$(".pop").fadeIn(),this.$("#showHidePWNonModal").prop("checked",!1),this.toggleShowHideNonModal(),this.spawnRating()},e.prototype.toggleShowHideNonModal=function(){this.$("#showHidePWNonModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWModal").prop("checked",!1)),this.spawnRating()},e.prototype.toggleShowHideModal=function(){this.$("#showHidePWModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWNonModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWNonModal").prop("checked",!1)),this.spawnRating()},e.prototype.storepw=function(){var e=this.$("#pwbox").val();this.pwWhenModalOpened=e,this.$("#pwboxModal").val(e)},e.prototype.enableDiscard=function(){this.$("#pwboxModal").val()===this.pwWhenModalOpened?(this.$("#discardButton").hide(),this.$("#keepButton").html("OK")):(this.$("#discardButton").show(),this.$("#keepButton").html("Keep Changes"))},e.prototype.keeppw=function(){this.$("#pwbox").val(this.$("#pwboxModal").val())},e.prototype.discardpw=function(){this.$("#pwbox").val(this.pwWhenModalOpened)},e.prototype.fixPWNonModal=function(){this.tookSuggestion=!0;var e=this.$("#nonmodalFixedPW").text();this.$("#pwbox").val(e),this.spawnRating()},e.prototype.fixPWModal=function(){this.tookSuggestion=!0;var e=this.$("#modalFixedPW").text();this.$("#pwboxModal").val(e),this.spawnRating(),this.enableDiscard()},e.prototype.showModal=function(){this.storepw(),this.$("#discardButton").hide(),this.$("#keepButton").html("OK"),this.$("#myModal").modal("show")},e.prototype.mayberate=function(){this.$("#pwbox").val()!==this.previouslyRated&&(this.previouslyRated=this.$("#pwbox").val(),this.spawnRating())},e.prototype.continueCheck=function(e){var t=!0;e&&(this.$("#usernamebox").val().length<1?(this.$("#usernameTooShort").show(),t=!1):this.$("#usernameTooShort").hide());this.inCompliance?(this.$("#feedbackHeaderText").css({color:"","font-weight":""}),this.$("#passwordNonCompliant").hide()):(t=!1,this.$("#confirmDoesNotMatch").hide(),e&&(this.$("#feedbackHeaderText").css({color:"red","font-weight":"bold"}),this.$("#passwordNonCompliant").show())),this.$("#pwbox").val()!==this.$("#confirmbox").val()?(t=!1,e&&this.inCompliance&&this.$("#confirmDoesNotMatch").show()):this.$("#confirmDoesNotMatch").hide(),e&&t&&alert("this would be submitted")},e.prototype.scaleGuessNumByMeterStringencyFactor=function(e){return e>0?e*Constants.Constants.METER_STRINGENCY_SCALE_FACTOR:e},e.prototype.spawnRating=function(){var e="",t=PasswordMeter.PasswordMeter.instance.getNN();e=this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown?this.$("#pwboxModal").val():this.$("#pwbox").val();var s=this.$("#usernamebox").val(),i=0,o=t.getNeuralNetNum(e);void 0===o?(t.setNeuralNetNum(e,-1),t.queryGuessNumber(e,!1)):o>=0&&i++,void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!0):this.heuristicMapping[e]>=0&&i++,0!==e.length&&t.heardFromNn()&&2!==i||this.displayRating(e)},e.prototype.generateCandidateFixed=function(e,t,s){if(!PasswordMeter.PasswordMeter.instance.getConfig().provideConcretePasswordSuggestions)return 1;var i=[];if(void 0===this.deltaHighlighted[e])for(var o=0;o=65&&n.charCodeAt(r)<=90?(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)+32)),i[r]=1):n.charCodeAt(r)>=97&&n.charCodeAt(r)<=122&&(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)-32)),i[r]=1)}else if(2===a||3===a){var l=32+Math.floor(95*Math.random()),d=Math.floor(n.length*Math.random());n.charCodeAt(d)!==l&&(i[d]=1),n=n.replaceAt(d,String.fromCharCode(l))}else if(a>=4){l=32+Math.floor(95*Math.random()),d=Math.floor((n.length+1)*Math.random());n=n.slice(0,d)+String.fromCharCode(l)+n.slice(d),i=i.slice(0,d).concat(1,i.slice(d))}var p=PasswordMeter.PasswordMeter.instance.getNN();void 0===p.getNeuralNetNum(n)&&(p.setNeuralNetNum(n,-1),p.queryGuessNumber(n,!0));var u=this.$("#usernamebox").val();return void 0===this.heuristicMapping[n]&&this.queryHeuristicGuessNumber(n,u,!1),RuleFunctions.RuleFunctions.verifyMinimumRequirements(n,u).compliant?(this.recommendedFixes[s]=n,this.deltaHighlighted[n]=i,this.verboseMode&&console.log("identified "+n+" as a potential fix for "+s),void 0===this.recommendedFixesTries[s]?this.recommendedFixesTries[s]=1:this.recommendedFixesTries[s]=this.recommendedFixesTries[s]+1,this.spawnFixedRating(n)):++t<8&&this.generateCandidateFixed(e,t,s),1},e.prototype.spawnFixedRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=this.$("#usernamebox").val();void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!1):t.getNeuralNetNum(e)>=0&&this.heuristicMapping[e]>=0&&this.synthesizeFixed(e)},e.prototype.synthesizeFixed=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0,o=!1;void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(i++,s=this.heuristicMapping[e]);var n=t.getNeuralNetNum(e),a=this.scaleGuessNumByMeterStringencyFactor(n);if(void 0!==n&&a>=0&&isFinite(a)&&(i++,(0===s||s>0&&a=67){for(var h in this.verboseMode&&console.log(e+" is a plausible fix above the 2/3rds threshold"),this.recommendedFixes)if(this.recommendedFixes[h]===e&&void 0===this.fixedpwMapping[h]){var r=0;void 0!==this.heuristicMapping[h]&&this.heuristicMapping[h]>=0&&(r=this.heuristicMapping[h]);var l=t.getNeuralNetNum(h),d=this.scaleGuessNumByMeterStringencyFactor(l);void 0!==l&&d>=0&&isFinite(d)&&(0===r||r>0&&dr+15?(this.fixedpwMapping[h]=e,this.verboseMode&&console.log("mapping "+h+" to "+e),o=!0):this.verboseMode&&console.log("not mapping "+h+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s)}return o&&this.spawnRating(),1}var p=this.$("#pwbox").val();return this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown&&(p=this.$("#pwboxModal").val()),this.recommendedFixes[p]===e&&2===i&&void 0===this.fixedpwMapping[p]&&void 0!==this.recommendedFixesTries[p]&&this.recommendedFixesTries[p]<8&&(this.verboseMode&&console.log("trying again on "+e+" as current password is "+p),this.generateCandidateFixed(e,0,p)),1},e.prototype.redundant=function(e,t){e=e.toLowerCase();for(var s=0;s0&&e.length>0&&(t[s].indexOf(e)>=0&&e.length>=.7*t[s].length||e.indexOf(t[s])>=0&&t[s].length>=.7*e.length))return!0;return!1},e.prototype.queryHeuristicGuessNumber=function(e,t,s){var i=e,o=[],n=[],a=[],h=[],r=RuleFunctions.RuleFunctions.contextual(e,[t]);void 0===(e=r.remaining)&&(e="");var l=RuleFunctions.RuleFunctions.blacklist(e);void 0===(e=l.remaining)&&(e="");for(var d=RuleFunctions.RuleFunctions.pwLength(e),p=RuleFunctions.RuleFunctions.characterClasses(e),u=RuleFunctions.RuleFunctions.duplicatedCharacters(e),c=RuleFunctions.RuleFunctions.repeats(e),m=RuleFunctions.RuleFunctions.keyboardPatterns(e),g=RuleFunctions.RuleFunctions.repeatedSections(e),w=RuleFunctions.RuleFunctions.structurePredictable(e),x=RuleFunctions.RuleFunctions.uppercasePredictable(e),b=RuleFunctions.RuleFunctions.digitsPredictable(e),$=RuleFunctions.RuleFunctions.symbolsPredictable(e),y=RuleFunctions.RuleFunctions.countUC(e),v=RuleFunctions.RuleFunctions.countLC(e),M=RuleFunctions.RuleFunctions.countDIGS(e),f=RuleFunctions.RuleFunctions.countSYMS(e),T=RuleFunctions.RuleFunctions.identifyDates(e),R=(RuleFunctions.RuleFunctions.verifyMinimumRequirements(e,t),RuleFunctions.RuleFunctions.alphabeticSequenceCheck(e)),C=RuleFunctions.RuleFunctions.commonSubstringCheck(e),F=RuleFunctions.RuleFunctions.combinedDictCheck(e),N=e.listSubstringsNoFilter(4),k=RuleFunctions.RuleFunctions.commonPwCheck(N),W=[1.53,.3129,.9912,.04637,-.03885,-.1172,-.2976,-8581e-7,-.3008,-.5566,0,.9108,.7369,.7578,0,-.1213,-.2402,-.1364,-.5534,1.927,.001496,-.3946],P=[1,d.length,p.count,u.count,c.count,m.score,g.count,w.score,x.score,b.score,$.score,y.count,v.count,M.count,f.count,T.count,R.count,C.count,F.length,F.dictionaryTokens,F.substitutionCommonness,k.length],S=W[0],H=1;H100&&(S=100),r.publicText.length>0&&(o.push(r.publicText),n.push(r.sensitiveText),a.push(r.reasonWhy),h.push(r.problemText)),l.publicText.length>0&&(o.push(l.publicText),n.push(l.sensitiveText),a.push(l.reasonWhy),h.push(l.problemText)),F.publicText.length>0&&!this.redundant(F.problemText,h)&&(o.push(F.publicText),n.push(F.sensitiveText),a.push(F.reasonWhy),h.push(F.problemText)),m.publicText.length>0&&(o.push(m.publicText),n.push(m.sensitiveText),a.push(m.reasonWhy),h.push(m.problemText)),c.publicText.length>0&&(o.push(c.publicText),n.push(c.sensitiveText),a.push(c.reasonWhy),h.push(c.problemText)),T.publicText.length>0&&(o.push(T.publicText),n.push(T.sensitiveText),a.push(T.reasonWhy),h.push(T.problemText)),g.publicText.length>0&&(o.push(g.publicText),n.push(g.sensitiveText),a.push(g.reasonWhy),h.push(g.problemText)),R.publicText.length>0&&(o.push(R.publicText),n.push(R.sensitiveText),a.push(R.reasonWhy),h.push(R.problemText)),k.publicText.length>0&&!this.redundant(k.problemText,h)&&(o.push(k.publicText),n.push(k.sensitiveText),a.push(k.reasonWhy),h.push(k.problemText)),x.publicText.length>0&&(o.push(x.publicText),n.push(x.sensitiveText),a.push(x.reasonWhy),h.push(x.problemText)),b.publicText.length>0&&(o.push(b.publicText),n.push(b.sensitiveText),a.push(b.reasonWhy),h.push(b.problemText)),$.publicText.length>0&&(o.push($.publicText),n.push($.sensitiveText),a.push($.reasonWhy),h.push($.problemText)),u.publicText.length>0&&(o.push(u.publicText),n.push(u.sensitiveText),a.push(u.reasonWhy),h.push(u.problemText)),d.publicText.length>0&&(o.push(d.publicText),n.push(d.sensitiveText),a.push(d.reasonWhy)),f.publicText.length>0&&(o.push(f.publicText),n.push(f.sensitiveText),a.push(f.reasonWhy)),y.publicText.length>0&&(o.push(y.publicText),n.push(y.sensitiveText),a.push(y.reasonWhy)),M.publicText.length>0&&(o.push(M.publicText),n.push(M.sensitiveText),a.push(M.reasonWhy)),v.publicText.length>0&&(o.push(v.publicText),n.push(v.sensitiveText),a.push(v.reasonWhy)),C.publicText.length>0&&!this.redundant(C.problemText,h)&&(o.push(C.publicText),n.push(C.sensitiveText),a.push(C.reasonWhy)),w.publicText.length>0&&(o.push(w.publicText),n.push(w.sensitiveText),a.push(w.reasonWhy)),this.heuristicMapping[i]=S,this.feedbackMapping[i]=JSON.stringify({publictips1:o[0],publictips2:o[1],publictips3:o[2],sensitivetips1:n[0],sensitivetips2:n[1],sensitivetips3:n[2],reasonWhy1:a[0],reasonWhy2:a[1],reasonWhy3:a[2]}),s?(this.displayRating(i),b.fixedPw.length>0?(this.previousCandidate[i]=b.fixedPw,this.deltaHighlighted[b.fixedPw]=b.deltas):$.fixedPw.length>0&&(this.previousCandidate[i]=$.fixedPw,this.deltaHighlighted[$.fixedPw]=$.deltas)):this.synthesizeFixed(i)},e.prototype.displayRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0;if(e.length>0){void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(s=this.heuristicMapping[e],i++);var o=t.getNeuralNetNum(e),n=this.scaleGuessNumByMeterStringencyFactor(o);void 0!==o&&n>=0&&isFinite(n)&&(i++,(0==s||s>0&&n(Why?)
"),d+="

 

To make it even better:",this.$("#feedbackHeaderText").html(d),this.$("#feedbackHeaderTextModal").html(d)}else{var p="Your password appears strong.";h.remindAgainstReuse&&(p+=" Make sure you use it only for this account. (Why?)"),this.$("#feedbackHeaderText").html(p),this.$("#feedbackHeaderTextModal").html(p)}if(this.$(".nonmodalColorCell").show(),this.$(".modalColorCell").show(),this.$(".modalColorCellSpacer").show(),this.$(".recommended").show(),!0===this.$("#showHidePWNonModal").prop("checked")?(this.$(".fixedPWavailablePortal").hide(),this.$(".concreteSuggestionDiv").show(),this.$("#tipText1").html(a.sensitivetips1),this.$("#tipText2").html(a.sensitivetips2),this.$("#tipText3").html(a.sensitivetips3),this.$("#suggestion1").html(a.sensitivetips1),this.$("#suggestion2").html(a.sensitivetips2),this.$("#suggestion3").html(a.sensitivetips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)):(this.$(".fixedPWavailablePortal").show(),this.$(".concreteSuggestionDiv").hide(),this.$("#tipText1").html(a.publictips1),this.$("#tipText2").html(a.publictips2),this.$("#tipText3").html(a.publictips3),this.$("#suggestion1").html(a.publictips1),this.$("#suggestion2").html(a.publictips2),this.$("#suggestion3").html(a.publictips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)),h.provideConcretePasswordSuggestions&&void 0!==this.fixedpwMapping[e]){for(var u="",c=this.deltaHighlighted[this.fixedpwMapping[e]],m=this.fixedpwMapping[e],g=0;g"+m[g].escapeHTML()+"
":u+=m[g].escapeHTML();this.$(".fixedPW").html(u)}else this.$(".recommended").hide();s<=66?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show()):s<100?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show(),this.tookSuggestion&&(this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())):(this.$("#nonmodalFeedbackTable").hide(),this.$("#modalFeedbackTable").hide(),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())}else{this.inCompliance=!1,0!==e.length&&t.heardFromNn()&&2!==i||this.displayBar(s,!1),this.$("#confirmpw").hide(),this.$(".detailedFeedback").hide(),this.$(".portalToGenericAdviceModal").show(),this.$(".explainWhy").hide();var w="";(h=PasswordMeter.PasswordMeter.instance.getConfig()).remindAgainstReuse&&(w="Don't reuse a password from another account! (Why?)

 

");var x="Your password must:";this.$("#feedbackHeaderText").html(w+x),this.$("#feedbackHeaderTextModal").html(w+x),this.$("#nonmodalFeedbackTable").show(),this.$(".recommended").hide();var b=[],$=l.detail;for(var y in $.compliance)$.compliance[y]||b.push($.explanation[y]);this.$(".nonmodalColorCell").hide(),this.$(".modalColorCell").hide(),this.$(".modalColorCellSpacer").hide(),this.$(".nonmodalRow").hide(),this.$(".modalRow").hide();for(var v=0;v100&&(e=100);var s=e/100,i="rgb(160,160,160)";t&&s<.45?i="rgb("+Math.round(255)+","+Math.round(s/.45*140)+",0)":t&&s>=.45&&s<.65?i="rgb("+Math.round(255)+","+Math.round((s-.45)/.2*75+140)+",0)":t&&(i="rgb("+Math.round(255-(s-.65)/.35*205)+","+Math.round(215-(s-.65)/.035)+",0)"),this.$("#cups-passwordmeter-span").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span").css("background-color",i),this.$("#cups-passwordmeter-span-modal").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span-modal").css("background-color",i)},e.prototype.getMaxOfArray=function(e){return Math.max.apply(null,e)},e.prototype.expandHelpBut=function(){this.$("#expandHelpDiv").show(),this.$("#helpButton").hide()},e.prototype.modalShowCheck=function(){"text"==this.$("#pwbox").prop("type")?(this.$("#myModal").show(),this.storepw()):this.$("#expandHelpDiv").is(":visible")?(this.$("#myModal").show(),this.storepw()):this.expandHelpBut()},e.prototype.closeDiv=function(e){this.$(e).hide()},e.prototype.deselect=function(e){null==this.$.fn.slideFadeToggle&&(this.$.fn.slideFadeToggle=function(e,t){return this.animate({opacity:"toggle",height:"toggle"},"fast",e,t)}),this.$(".pop").slideFadeToggle(function(){e.removeClass("selected")})},e}();e.UIMisc=o,t=PasswordMeter.PasswordMeter.instance,s=t.getJquery(),i=new o(!1),t.setUI(i),s(document).ready(function(){s("#showpassword").prop("checked",!1),s("#showpassword").click(function(){document.getElementById("hide-show-label").textContent="Hide Password",s("#cbbutton").css("background-color","#f5f5f5"),"password"==s("#pwbox").prop("type")?s("#pwbox").prop("type","text"):(s("#pwbox").prop("type","password"),document.getElementById("hide-show-label").textContent="Show Password",s("#cbbutton").css("background-color","#f5f5f5"))})}),s(document).ready(function(){var e=s("#pwboxModal");s("#tip1, #sensText1").mouseover(function(){e.addClass("problemColor")}),s("#tip2, #sensText2").mouseover(function(){e.addClass("problemColor")}),s("#tip3, #sensText3").mouseover(function(){e.addClass("problemColor")})}),s(document).ready(function(){i.onReady()})}(UIMisc=exports.UIMisc||(exports.UIMisc={})); +"use strict";exports.__esModule=!0;var UIMisc,PasswordMeter=require("./PasswordMeter"),RuleFunctions=require("./rulefunctions"),Constants=require("./constants");!function(e){var t,s,i,o=function(){function e(e){this.pwWhenModalOpened="",this.tookSuggestion=!1,this.previouslyRated="",this.heuristicMapping={},this.feedbackMapping={},this.recommendedFixes={},this.recommendedFixesTries={},this.previousCandidate={},this.fixedpwMapping={},this.deltaHighlighted={},this.inCompliance=!1,this.randomlyOrderedCharClasses=[];var t=PasswordMeter.PasswordMeter.instance;this.helper=t.getHelper(),this.$=t.getJquery(),this.verboseMode=e;this.randomlyOrderedCharClasses=function(e){for(var t,s,i=e.length;0!==i;)s=Math.floor(Math.random()*i),t=e[i-=1],e[i]=e[s],e[s]=t;return e}(["uppercase letter","lowercase letter","digit","symbol"])}return e.prototype.getCharClassStringForCharClassCountReq=function(){return this.randomlyOrderedCharClasses.map(function(e){return e+"s"}).join("; ")},e.prototype.getCharClassStringForMandatoryCharClassReq=function(){for(var e=PasswordMeter.PasswordMeter.instance.getConfig(),t="",s=0;s0?t+=" and an uppercase letter":t="Contain an uppercase letter");break;case"lowercase letter":e.classRequire.lowerCase&&(t.length>0?t+=" and a lowercase letter":t="Contain a lowercase letter");break;case"digit":e.classRequire.digits&&(t.length>0?t+=" and a digit":t="Contain a digit");break;case"symbol":e.classRequire.symbols&&(t.length>0?t+=" and a symbol":t="Contain a symbol")}}return t},e.prototype.onReady=function(){this.$(".pop").fadeIn(),this.$("#showHidePWNonModal").prop("checked",!1),this.toggleShowHideNonModal(),this.spawnRating()},e.prototype.toggleShowHideNonModal=function(){this.$("#showHidePWNonModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWModal").prop("checked",!1)),this.spawnRating()},e.prototype.toggleShowHideModal=function(){this.$("#showHidePWModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWNonModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWNonModal").prop("checked",!1)),this.spawnRating()},e.prototype.storepw=function(){var e=this.$("#pwbox").val();this.pwWhenModalOpened=e,this.$("#pwboxModal").val(e)},e.prototype.enableDiscard=function(){this.$("#pwboxModal").val()===this.pwWhenModalOpened?(this.$("#discardButton").hide(),this.$("#keepButton").html("OK")):(this.$("#discardButton").show(),this.$("#keepButton").html("Keep Changes"))},e.prototype.keeppw=function(){this.$("#pwbox").val(this.$("#pwboxModal").val())},e.prototype.discardpw=function(){this.$("#pwbox").val(this.pwWhenModalOpened)},e.prototype.fixPWNonModal=function(){this.tookSuggestion=!0;var e=this.$("#nonmodalFixedPW").text();this.$("#pwbox").val(e),this.spawnRating()},e.prototype.fixPWModal=function(){this.tookSuggestion=!0;var e=this.$("#modalFixedPW").text();this.$("#pwboxModal").val(e),this.spawnRating(),this.enableDiscard()},e.prototype.showModal=function(){this.storepw(),this.$("#discardButton").hide(),this.$("#keepButton").html("OK"),this.$("#myModal").modal("show")},e.prototype.mayberate=function(){this.$("#pwbox").val()!==this.previouslyRated&&(this.previouslyRated=this.$("#pwbox").val(),this.spawnRating())},e.prototype.continueCheck=function(e){var t=!0;e&&(this.$("#usernamebox").val().length<1?(this.$("#usernameTooShort").show(),t=!1):this.$("#usernameTooShort").hide());this.inCompliance?(this.$("#feedbackHeaderText").css({color:"","font-weight":""}),this.$("#passwordNonCompliant").hide()):(t=!1,this.$("#confirmDoesNotMatch").hide(),e&&(this.$("#feedbackHeaderText").css({color:"red","font-weight":"bold"}),this.$("#passwordNonCompliant").show())),this.$("#pwbox").val()!==this.$("#confirmbox").val()?(t=!1,e&&this.inCompliance&&this.$("#confirmDoesNotMatch").show()):this.$("#confirmDoesNotMatch").hide(),e&&t&&continueSubmit()},e.prototype.scaleGuessNumByMeterStringencyFactor=function(e){return e>0?e*Constants.Constants.METER_STRINGENCY_SCALE_FACTOR:e},e.prototype.spawnRating=function(){var e="",t=PasswordMeter.PasswordMeter.instance.getNN();e=this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown?this.$("#pwboxModal").val():this.$("#pwbox").val();var s=this.$("#usernamebox").val(),i=0,o=t.getNeuralNetNum(e);void 0===o?(t.setNeuralNetNum(e,-1),t.queryGuessNumber(e,!1)):o>=0&&i++,void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!0):this.heuristicMapping[e]>=0&&i++,0!==e.length&&t.heardFromNn()&&2!==i||this.displayRating(e)},e.prototype.generateCandidateFixed=function(e,t,s){if(!PasswordMeter.PasswordMeter.instance.getConfig().provideConcretePasswordSuggestions)return 1;var i=[];if(void 0===this.deltaHighlighted[e])for(var o=0;o=65&&n.charCodeAt(r)<=90?(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)+32)),i[r]=1):n.charCodeAt(r)>=97&&n.charCodeAt(r)<=122&&(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)-32)),i[r]=1)}else if(2===a||3===a){var l=32+Math.floor(95*Math.random()),d=Math.floor(n.length*Math.random());n.charCodeAt(d)!==l&&(i[d]=1),n=n.replaceAt(d,String.fromCharCode(l))}else if(a>=4){l=32+Math.floor(95*Math.random()),d=Math.floor((n.length+1)*Math.random());n=n.slice(0,d)+String.fromCharCode(l)+n.slice(d),i=i.slice(0,d).concat(1,i.slice(d))}var p=PasswordMeter.PasswordMeter.instance.getNN();void 0===p.getNeuralNetNum(n)&&(p.setNeuralNetNum(n,-1),p.queryGuessNumber(n,!0));var u=this.$("#usernamebox").val();return void 0===this.heuristicMapping[n]&&this.queryHeuristicGuessNumber(n,u,!1),RuleFunctions.RuleFunctions.verifyMinimumRequirements(n,u).compliant?(this.recommendedFixes[s]=n,this.deltaHighlighted[n]=i,this.verboseMode&&console.log("identified "+n+" as a potential fix for "+s),void 0===this.recommendedFixesTries[s]?this.recommendedFixesTries[s]=1:this.recommendedFixesTries[s]=this.recommendedFixesTries[s]+1,this.spawnFixedRating(n)):++t<8&&this.generateCandidateFixed(e,t,s),1},e.prototype.spawnFixedRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=this.$("#usernamebox").val();void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!1):t.getNeuralNetNum(e)>=0&&this.heuristicMapping[e]>=0&&this.synthesizeFixed(e)},e.prototype.synthesizeFixed=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0,o=!1;void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(i++,s=this.heuristicMapping[e]);var n=t.getNeuralNetNum(e),a=this.scaleGuessNumByMeterStringencyFactor(n);if(void 0!==n&&a>=0&&isFinite(a)&&(i++,(0===s||s>0&&a=67){for(var h in this.verboseMode&&console.log(e+" is a plausible fix above the 2/3rds threshold"),this.recommendedFixes)if(this.recommendedFixes[h]===e&&void 0===this.fixedpwMapping[h]){var r=0;void 0!==this.heuristicMapping[h]&&this.heuristicMapping[h]>=0&&(r=this.heuristicMapping[h]);var l=t.getNeuralNetNum(h),d=this.scaleGuessNumByMeterStringencyFactor(l);void 0!==l&&d>=0&&isFinite(d)&&(0===r||r>0&&dr+15?(this.fixedpwMapping[h]=e,this.verboseMode&&console.log("mapping "+h+" to "+e),o=!0):this.verboseMode&&console.log("not mapping "+h+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s)}return o&&this.spawnRating(),1}var p=this.$("#pwbox").val();return this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown&&(p=this.$("#pwboxModal").val()),this.recommendedFixes[p]===e&&2===i&&void 0===this.fixedpwMapping[p]&&void 0!==this.recommendedFixesTries[p]&&this.recommendedFixesTries[p]<8&&(this.verboseMode&&console.log("trying again on "+e+" as current password is "+p),this.generateCandidateFixed(e,0,p)),1},e.prototype.redundant=function(e,t){e=e.toLowerCase();for(var s=0;s0&&e.length>0&&(t[s].indexOf(e)>=0&&e.length>=.7*t[s].length||e.indexOf(t[s])>=0&&t[s].length>=.7*e.length))return!0;return!1},e.prototype.queryHeuristicGuessNumber=function(e,t,s){var i=e,o=[],n=[],a=[],h=[],r=RuleFunctions.RuleFunctions.contextual(e,[t]);void 0===(e=r.remaining)&&(e="");var l=RuleFunctions.RuleFunctions.blacklist(e);void 0===(e=l.remaining)&&(e="");for(var d=RuleFunctions.RuleFunctions.pwLength(e),p=RuleFunctions.RuleFunctions.characterClasses(e),u=RuleFunctions.RuleFunctions.duplicatedCharacters(e),c=RuleFunctions.RuleFunctions.repeats(e),m=RuleFunctions.RuleFunctions.keyboardPatterns(e),g=RuleFunctions.RuleFunctions.repeatedSections(e),w=RuleFunctions.RuleFunctions.structurePredictable(e),x=RuleFunctions.RuleFunctions.uppercasePredictable(e),b=RuleFunctions.RuleFunctions.digitsPredictable(e),y=RuleFunctions.RuleFunctions.symbolsPredictable(e),$=RuleFunctions.RuleFunctions.countUC(e),v=RuleFunctions.RuleFunctions.countLC(e),M=RuleFunctions.RuleFunctions.countDIGS(e),f=RuleFunctions.RuleFunctions.countSYMS(e),T=RuleFunctions.RuleFunctions.identifyDates(e),R=(RuleFunctions.RuleFunctions.verifyMinimumRequirements(e,t),RuleFunctions.RuleFunctions.alphabeticSequenceCheck(e)),C=RuleFunctions.RuleFunctions.commonSubstringCheck(e),F=RuleFunctions.RuleFunctions.combinedDictCheck(e),N=e.listSubstringsNoFilter(4),k=RuleFunctions.RuleFunctions.commonPwCheck(N),P=[1.53,.3129,.9912,.04637,-.03885,-.1172,-.2976,-8581e-7,-.3008,-.5566,0,.9108,.7369,.7578,0,-.1213,-.2402,-.1364,-.5534,1.927,.001496,-.3946],W=[1,d.length,p.count,u.count,c.count,m.score,g.count,w.score,x.score,b.score,y.score,$.count,v.count,M.count,f.count,T.count,R.count,C.count,F.length,F.dictionaryTokens,F.substitutionCommonness,k.length],S=P[0],H=1;H100&&(S=100),r.publicText.length>0&&(o.push(r.publicText),n.push(r.sensitiveText),a.push(r.reasonWhy),h.push(r.problemText)),l.publicText.length>0&&(o.push(l.publicText),n.push(l.sensitiveText),a.push(l.reasonWhy),h.push(l.problemText)),F.publicText.length>0&&!this.redundant(F.problemText,h)&&(o.push(F.publicText),n.push(F.sensitiveText),a.push(F.reasonWhy),h.push(F.problemText)),m.publicText.length>0&&(o.push(m.publicText),n.push(m.sensitiveText),a.push(m.reasonWhy),h.push(m.problemText)),c.publicText.length>0&&(o.push(c.publicText),n.push(c.sensitiveText),a.push(c.reasonWhy),h.push(c.problemText)),T.publicText.length>0&&(o.push(T.publicText),n.push(T.sensitiveText),a.push(T.reasonWhy),h.push(T.problemText)),g.publicText.length>0&&(o.push(g.publicText),n.push(g.sensitiveText),a.push(g.reasonWhy),h.push(g.problemText)),R.publicText.length>0&&(o.push(R.publicText),n.push(R.sensitiveText),a.push(R.reasonWhy),h.push(R.problemText)),k.publicText.length>0&&!this.redundant(k.problemText,h)&&(o.push(k.publicText),n.push(k.sensitiveText),a.push(k.reasonWhy),h.push(k.problemText)),x.publicText.length>0&&(o.push(x.publicText),n.push(x.sensitiveText),a.push(x.reasonWhy),h.push(x.problemText)),b.publicText.length>0&&(o.push(b.publicText),n.push(b.sensitiveText),a.push(b.reasonWhy),h.push(b.problemText)),y.publicText.length>0&&(o.push(y.publicText),n.push(y.sensitiveText),a.push(y.reasonWhy),h.push(y.problemText)),u.publicText.length>0&&(o.push(u.publicText),n.push(u.sensitiveText),a.push(u.reasonWhy),h.push(u.problemText)),d.publicText.length>0&&(o.push(d.publicText),n.push(d.sensitiveText),a.push(d.reasonWhy)),f.publicText.length>0&&(o.push(f.publicText),n.push(f.sensitiveText),a.push(f.reasonWhy)),$.publicText.length>0&&(o.push($.publicText),n.push($.sensitiveText),a.push($.reasonWhy)),M.publicText.length>0&&(o.push(M.publicText),n.push(M.sensitiveText),a.push(M.reasonWhy)),v.publicText.length>0&&(o.push(v.publicText),n.push(v.sensitiveText),a.push(v.reasonWhy)),C.publicText.length>0&&!this.redundant(C.problemText,h)&&(o.push(C.publicText),n.push(C.sensitiveText),a.push(C.reasonWhy)),w.publicText.length>0&&(o.push(w.publicText),n.push(w.sensitiveText),a.push(w.reasonWhy)),this.heuristicMapping[i]=S,this.feedbackMapping[i]=JSON.stringify({publictips1:o[0],publictips2:o[1],publictips3:o[2],sensitivetips1:n[0],sensitivetips2:n[1],sensitivetips3:n[2],reasonWhy1:a[0],reasonWhy2:a[1],reasonWhy3:a[2]}),s?(this.displayRating(i),b.fixedPw.length>0?(this.previousCandidate[i]=b.fixedPw,this.deltaHighlighted[b.fixedPw]=b.deltas):y.fixedPw.length>0&&(this.previousCandidate[i]=y.fixedPw,this.deltaHighlighted[y.fixedPw]=y.deltas)):this.synthesizeFixed(i)},e.prototype.displayRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0;if(e.length>0){void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(s=this.heuristicMapping[e],i++);var o=t.getNeuralNetNum(e),n=this.scaleGuessNumByMeterStringencyFactor(o);void 0!==o&&n>=0&&isFinite(n)&&(i++,(0==s||s>0&&n(Why?)
"),d+="

 

To make it even better:",this.$("#feedbackHeaderText").html(d),this.$("#feedbackHeaderTextModal").html(d)}else{var p="Your password appears strong.";h.remindAgainstReuse&&(p+=" Make sure you use it only for this account. (Why?)"),this.$("#feedbackHeaderText").html(p),this.$("#feedbackHeaderTextModal").html(p)}if(this.$(".nonmodalColorCell").show(),this.$(".modalColorCell").show(),this.$(".modalColorCellSpacer").show(),this.$(".recommended").show(),!0===this.$("#showHidePWNonModal").prop("checked")?(this.$(".fixedPWavailablePortal").hide(),this.$(".concreteSuggestionDiv").show(),this.$("#tipText1").html(a.sensitivetips1),this.$("#tipText2").html(a.sensitivetips2),this.$("#tipText3").html(a.sensitivetips3),this.$("#suggestion1").html(a.sensitivetips1),this.$("#suggestion2").html(a.sensitivetips2),this.$("#suggestion3").html(a.sensitivetips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)):(this.$(".fixedPWavailablePortal").show(),this.$(".concreteSuggestionDiv").hide(),this.$("#tipText1").html(a.publictips1),this.$("#tipText2").html(a.publictips2),this.$("#tipText3").html(a.publictips3),this.$("#suggestion1").html(a.publictips1),this.$("#suggestion2").html(a.publictips2),this.$("#suggestion3").html(a.publictips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)),h.provideConcretePasswordSuggestions&&void 0!==this.fixedpwMapping[e]){for(var u="",c=this.deltaHighlighted[this.fixedpwMapping[e]],m=this.fixedpwMapping[e],g=0;g"+m[g].escapeHTML()+"
":u+=m[g].escapeHTML();this.$(".fixedPW").html(u).trigger("change")}else this.$(".recommended").hide();s<=66?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show()):s<100?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show(),this.tookSuggestion&&(this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())):(this.$("#nonmodalFeedbackTable").hide(),this.$("#modalFeedbackTable").hide(),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())}else{this.inCompliance=!1,0!==e.length&&t.heardFromNn()&&2!==i||this.displayBar(s,!1,e),this.$("#confirmpw").hide(),this.$(".detailedFeedback").hide(),this.$(".portalToGenericAdviceModal").show(),this.$(".explainWhy").hide();var w="";(h=PasswordMeter.PasswordMeter.instance.getConfig()).remindAgainstReuse&&(w="Don't reuse a password from another account! (Why?)

 

");var x="Your password must:";this.$("#feedbackHeaderText").html(w+x),this.$("#feedbackHeaderTextModal").html(w+x),this.$("#nonmodalFeedbackTable").show(),this.$(".recommended").hide();var b=[],y=l.detail;for(var $ in y.compliance)y.compliance[$]||b.push(y.explanation[$]);this.$(".nonmodalColorCell").hide(),this.$(".modalColorCell").hide(),this.$(".modalColorCellSpacer").hide(),this.$(".nonmodalRow").hide(),this.$(".modalRow").hide();for(var v=0;v100&&(e=100);var i=e/100,o="rgb(160,160,160)";t&&i<.45?o="rgb("+Math.round(255)+","+Math.round(i/.45*140)+",0)":t&&i>=.45&&i<.65?o="rgb("+Math.round(255)+","+Math.round((i-.45)/.2*75+140)+",0)":t&&(o="rgb("+Math.round(255-(i-.65)/.35*205)+","+Math.round(215-(i-.65)/.035)+",0)");var n=PasswordMeter.PasswordMeter.instance.getNN(),a=this.scaleGuessNumByMeterStringencyFactor(n.getNeuralNetNum(s)),h=this.heuristicMapping[s];this.$("#cups-passwordmeter-span").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span").css("background-color",o).trigger("change",[e.toString(),h,a]),this.$("#cups-passwordmeter-span-modal").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span-modal").css("background-color",o)},e.prototype.getMaxOfArray=function(e){return Math.max.apply(null,e)},e.prototype.expandHelpBut=function(){this.$("#expandHelpDiv").show(),this.$("#helpButton").hide()},e.prototype.modalShowCheck=function(){"text"==this.$("#pwbox").prop("type")?(this.$("#myModal").show(),this.storepw()):this.$("#expandHelpDiv").is(":visible")?(this.$("#myModal").show(),this.storepw()):this.expandHelpBut()},e.prototype.closeDiv=function(e){this.$(e).hide()},e.prototype.deselect=function(e){null==this.$.fn.slideFadeToggle&&(this.$.fn.slideFadeToggle=function(e,t){return this.animate({opacity:"toggle",height:"toggle"},"fast",e,t)}),this.$(".pop").slideFadeToggle(function(){e.removeClass("selected")})},e}();e.UIMisc=o,t=PasswordMeter.PasswordMeter.instance,s=t.getJquery(),i=new o(!1),t.setUI(i),s(document).ready(function(){s("#showpassword").prop("checked",!1),s("#showpassword").click(function(){document.getElementById("hide-show-label").textContent="Hide Password",s("#cbbutton").css("background-color","#f5f5f5"),"password"==s("#pwbox").prop("type")?s("#pwbox").prop("type","text"):(s("#pwbox").prop("type","password"),document.getElementById("hide-show-label").textContent="Show Password",s("#cbbutton").css("background-color","#f5f5f5"))})}),s(document).ready(function(){var e=s("#pwboxModal");s("#tip1, #sensText1").mouseover(function(){e.addClass("problemColor")}),s("#tip2, #sensText2").mouseover(function(){e.addClass("problemColor")}),s("#tip3, #sensText3").mouseover(function(){e.addClass("problemColor")})}),s(document).ready(function(){i.onReady()})}(UIMisc=exports.UIMisc||(exports.UIMisc={})); },{"./PasswordMeter":3,"./constants":6,"./rulefunctions":10}]},{},[3,4,5,6,7,8,9,10,11,12]); diff --git a/src/ts/ui-misc.ts b/src/ts/ui-misc.ts index 743b4b3..3277a79 100644 --- a/src/ts/ui-misc.ts +++ b/src/ts/ui-misc.ts @@ -312,7 +312,9 @@ export module UIMisc { } // If meets policy, matches confirm, and they hit submit, let them if (triedToSubmit && compliantOverall) { - alert("this would be submitted"); + + // @ts-ignore + continueSubmit(); } } @@ -879,7 +881,7 @@ export module UIMisc { if (minReqObj.compliant) { this.inCompliance = true; if (pw.length === 0 || !nni.heardFromNn() || numberOfScores === 2) { - this.displayBar(overallScore, true); + this.displayBar(overallScore, true, pw); } this.$(".detailedFeedback").show(); @@ -939,7 +941,7 @@ export module UIMisc { } else if (overallScore < 100) { var feedbackHighMedium = "Your password is pretty good."; if (config.remindAgainstReuse) { - feedbackHighMedium += " Use it only for this account. (Why?)"; + feedbackHighMedium += " Use it only for this account. (Why?)"; } feedbackHighMedium += "

 

To make it even better:"; this.$("#feedbackHeaderText").html(feedbackHighMedium); @@ -947,7 +949,7 @@ export module UIMisc { } else { var feedbackStrong = "Your password appears strong."; if (config.remindAgainstReuse) { - feedbackStrong += " Make sure you use it only for this account. (Why?)"; + feedbackStrong += " Make sure you use it only for this account. (Why?)"; } this.$("#feedbackHeaderText").html(feedbackStrong); this.$("#feedbackHeaderTextModal").html(feedbackStrong); @@ -1004,7 +1006,8 @@ export module UIMisc { coloredFixedPW += proposedPassword[j].escapeHTML(); } } - this.$(".fixedPW").html(coloredFixedPW); + + this.$(".fixedPW").html(coloredFixedPW).trigger("change"); // If we don't yet have a concrete suggestion } else { this.$(".recommended").hide(); @@ -1035,7 +1038,7 @@ export module UIMisc { } else { this.inCompliance = false; if (pw.length === 0 || !nni.heardFromNn() || numberOfScores === 2) { - this.displayBar(overallScore, false); + this.displayBar(overallScore, false, pw); } // Don't let them confirm a non-compliant password this.$("#confirmpw").hide(); @@ -1048,7 +1051,7 @@ export module UIMisc { var requirementsHeader = ""; var config: Config.Config.Config = PasswordMeter.PasswordMeter.instance.getConfig(); if (config.remindAgainstReuse) { - requirementsHeader = "Don't reuse a password from another account! (Why?)

 

"; + requirementsHeader = "Don't reuse a password from another account! (Why?)

 

"; } var nonCompliantAdmonition = "Your password must:"; this.$("#feedbackHeaderText").html(requirementsHeader + nonCompliantAdmonition); @@ -1100,7 +1103,7 @@ export module UIMisc { // (expected range 0-100) and a boolean metRequirements indicating yes (true) // to display the bar in color or no (false) to display the bar in grayscale // until the requirements have been met. - displayBar(score: number, metRequirements: boolean): void { + displayBar(score: number, metRequirements: boolean, pw: string): void { // Adjust score if outside the range if (score < 0) { score = 0; @@ -1126,9 +1129,14 @@ export module UIMisc { + "," + Math.round(215 - (scoreProportion - 0.65) / 0.035) + ",0)"; } + // gather info needed for 'change' event + var nni = PasswordMeter.PasswordMeter.instance.getNN(); + var nnNumScore = this.scaleGuessNumByMeterStringencyFactor(nni.getNeuralNetNum(pw)); + var heuristicScore = this.heuristicMapping[pw]; + // Display bar in main window this.$("#cups-passwordmeter-span").css("width", Math.round(298 * score / 100).toString() + "px"); - this.$("#cups-passwordmeter-span").css("background-color", barcolor); + this.$("#cups-passwordmeter-span").css("background-color", barcolor).trigger("change", [score.toString(), heuristicScore, nnNumScore]); // display bar in modal this.$("#cups-passwordmeter-span-modal").css("width", Math.round(298 * score / 100).toString() + "px"); From 08218a4bf05aa10521a05d4e13e45cbdd09752f7 Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Fri, 8 Mar 2019 14:08:54 -0500 Subject: [PATCH 16/45] Changes to facilitate user study instrumentation. --- src/PasswordMeter.js | 2 +- src/ts/ui-misc.ts | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/PasswordMeter.js b/src/PasswordMeter.js index 646e74d..32b2e75 100644 --- a/src/PasswordMeter.js +++ b/src/PasswordMeter.js @@ -32,6 +32,6 @@ Array.prototype.toHumanString=function(){var t=this.length;if(0==t)return"(empty String.prototype.replaceAt=function(r,t){return this.substr(0,r)+t+this.substr(r+1)},String.prototype.listSubstringsNoFilter=function(r){for(var t=new Array,e=this.toLowerCase(),n=e.length,i=n;i>=r-1;i--)for(var o=0;i+o/g,">")},String.prototype.listSubstrings=function(r){for(var t,e=new Array,n=(t=(t=this.toLowerCase()).replace(/[^a-z]/g,"")).length,i=n;i>=r-1;i--)for(var o=0;i+o0?t+=" and an uppercase letter":t="Contain an uppercase letter");break;case"lowercase letter":e.classRequire.lowerCase&&(t.length>0?t+=" and a lowercase letter":t="Contain a lowercase letter");break;case"digit":e.classRequire.digits&&(t.length>0?t+=" and a digit":t="Contain a digit");break;case"symbol":e.classRequire.symbols&&(t.length>0?t+=" and a symbol":t="Contain a symbol")}}return t},e.prototype.onReady=function(){this.$(".pop").fadeIn(),this.$("#showHidePWNonModal").prop("checked",!1),this.toggleShowHideNonModal(),this.spawnRating()},e.prototype.toggleShowHideNonModal=function(){this.$("#showHidePWNonModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWModal").prop("checked",!1)),this.spawnRating()},e.prototype.toggleShowHideModal=function(){this.$("#showHidePWModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWNonModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWNonModal").prop("checked",!1)),this.spawnRating()},e.prototype.storepw=function(){var e=this.$("#pwbox").val();this.pwWhenModalOpened=e,this.$("#pwboxModal").val(e)},e.prototype.enableDiscard=function(){this.$("#pwboxModal").val()===this.pwWhenModalOpened?(this.$("#discardButton").hide(),this.$("#keepButton").html("OK")):(this.$("#discardButton").show(),this.$("#keepButton").html("Keep Changes"))},e.prototype.keeppw=function(){this.$("#pwbox").val(this.$("#pwboxModal").val())},e.prototype.discardpw=function(){this.$("#pwbox").val(this.pwWhenModalOpened)},e.prototype.fixPWNonModal=function(){this.tookSuggestion=!0;var e=this.$("#nonmodalFixedPW").text();this.$("#pwbox").val(e),this.spawnRating()},e.prototype.fixPWModal=function(){this.tookSuggestion=!0;var e=this.$("#modalFixedPW").text();this.$("#pwboxModal").val(e),this.spawnRating(),this.enableDiscard()},e.prototype.showModal=function(){this.storepw(),this.$("#discardButton").hide(),this.$("#keepButton").html("OK"),this.$("#myModal").modal("show")},e.prototype.mayberate=function(){this.$("#pwbox").val()!==this.previouslyRated&&(this.previouslyRated=this.$("#pwbox").val(),this.spawnRating())},e.prototype.continueCheck=function(e){var t=!0;e&&(this.$("#usernamebox").val().length<1?(this.$("#usernameTooShort").show(),t=!1):this.$("#usernameTooShort").hide());this.inCompliance?(this.$("#feedbackHeaderText").css({color:"","font-weight":""}),this.$("#passwordNonCompliant").hide()):(t=!1,this.$("#confirmDoesNotMatch").hide(),e&&(this.$("#feedbackHeaderText").css({color:"red","font-weight":"bold"}),this.$("#passwordNonCompliant").show())),this.$("#pwbox").val()!==this.$("#confirmbox").val()?(t=!1,e&&this.inCompliance&&this.$("#confirmDoesNotMatch").show()):this.$("#confirmDoesNotMatch").hide(),e&&t&&continueSubmit()},e.prototype.scaleGuessNumByMeterStringencyFactor=function(e){return e>0?e*Constants.Constants.METER_STRINGENCY_SCALE_FACTOR:e},e.prototype.spawnRating=function(){var e="",t=PasswordMeter.PasswordMeter.instance.getNN();e=this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown?this.$("#pwboxModal").val():this.$("#pwbox").val();var s=this.$("#usernamebox").val(),i=0,o=t.getNeuralNetNum(e);void 0===o?(t.setNeuralNetNum(e,-1),t.queryGuessNumber(e,!1)):o>=0&&i++,void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!0):this.heuristicMapping[e]>=0&&i++,0!==e.length&&t.heardFromNn()&&2!==i||this.displayRating(e)},e.prototype.generateCandidateFixed=function(e,t,s){if(!PasswordMeter.PasswordMeter.instance.getConfig().provideConcretePasswordSuggestions)return 1;var i=[];if(void 0===this.deltaHighlighted[e])for(var o=0;o=65&&n.charCodeAt(r)<=90?(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)+32)),i[r]=1):n.charCodeAt(r)>=97&&n.charCodeAt(r)<=122&&(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)-32)),i[r]=1)}else if(2===a||3===a){var l=32+Math.floor(95*Math.random()),d=Math.floor(n.length*Math.random());n.charCodeAt(d)!==l&&(i[d]=1),n=n.replaceAt(d,String.fromCharCode(l))}else if(a>=4){l=32+Math.floor(95*Math.random()),d=Math.floor((n.length+1)*Math.random());n=n.slice(0,d)+String.fromCharCode(l)+n.slice(d),i=i.slice(0,d).concat(1,i.slice(d))}var p=PasswordMeter.PasswordMeter.instance.getNN();void 0===p.getNeuralNetNum(n)&&(p.setNeuralNetNum(n,-1),p.queryGuessNumber(n,!0));var u=this.$("#usernamebox").val();return void 0===this.heuristicMapping[n]&&this.queryHeuristicGuessNumber(n,u,!1),RuleFunctions.RuleFunctions.verifyMinimumRequirements(n,u).compliant?(this.recommendedFixes[s]=n,this.deltaHighlighted[n]=i,this.verboseMode&&console.log("identified "+n+" as a potential fix for "+s),void 0===this.recommendedFixesTries[s]?this.recommendedFixesTries[s]=1:this.recommendedFixesTries[s]=this.recommendedFixesTries[s]+1,this.spawnFixedRating(n)):++t<8&&this.generateCandidateFixed(e,t,s),1},e.prototype.spawnFixedRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=this.$("#usernamebox").val();void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!1):t.getNeuralNetNum(e)>=0&&this.heuristicMapping[e]>=0&&this.synthesizeFixed(e)},e.prototype.synthesizeFixed=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0,o=!1;void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(i++,s=this.heuristicMapping[e]);var n=t.getNeuralNetNum(e),a=this.scaleGuessNumByMeterStringencyFactor(n);if(void 0!==n&&a>=0&&isFinite(a)&&(i++,(0===s||s>0&&a=67){for(var h in this.verboseMode&&console.log(e+" is a plausible fix above the 2/3rds threshold"),this.recommendedFixes)if(this.recommendedFixes[h]===e&&void 0===this.fixedpwMapping[h]){var r=0;void 0!==this.heuristicMapping[h]&&this.heuristicMapping[h]>=0&&(r=this.heuristicMapping[h]);var l=t.getNeuralNetNum(h),d=this.scaleGuessNumByMeterStringencyFactor(l);void 0!==l&&d>=0&&isFinite(d)&&(0===r||r>0&&dr+15?(this.fixedpwMapping[h]=e,this.verboseMode&&console.log("mapping "+h+" to "+e),o=!0):this.verboseMode&&console.log("not mapping "+h+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s)}return o&&this.spawnRating(),1}var p=this.$("#pwbox").val();return this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown&&(p=this.$("#pwboxModal").val()),this.recommendedFixes[p]===e&&2===i&&void 0===this.fixedpwMapping[p]&&void 0!==this.recommendedFixesTries[p]&&this.recommendedFixesTries[p]<8&&(this.verboseMode&&console.log("trying again on "+e+" as current password is "+p),this.generateCandidateFixed(e,0,p)),1},e.prototype.redundant=function(e,t){e=e.toLowerCase();for(var s=0;s0&&e.length>0&&(t[s].indexOf(e)>=0&&e.length>=.7*t[s].length||e.indexOf(t[s])>=0&&t[s].length>=.7*e.length))return!0;return!1},e.prototype.queryHeuristicGuessNumber=function(e,t,s){var i=e,o=[],n=[],a=[],h=[],r=RuleFunctions.RuleFunctions.contextual(e,[t]);void 0===(e=r.remaining)&&(e="");var l=RuleFunctions.RuleFunctions.blacklist(e);void 0===(e=l.remaining)&&(e="");for(var d=RuleFunctions.RuleFunctions.pwLength(e),p=RuleFunctions.RuleFunctions.characterClasses(e),u=RuleFunctions.RuleFunctions.duplicatedCharacters(e),c=RuleFunctions.RuleFunctions.repeats(e),m=RuleFunctions.RuleFunctions.keyboardPatterns(e),g=RuleFunctions.RuleFunctions.repeatedSections(e),w=RuleFunctions.RuleFunctions.structurePredictable(e),x=RuleFunctions.RuleFunctions.uppercasePredictable(e),b=RuleFunctions.RuleFunctions.digitsPredictable(e),y=RuleFunctions.RuleFunctions.symbolsPredictable(e),$=RuleFunctions.RuleFunctions.countUC(e),v=RuleFunctions.RuleFunctions.countLC(e),M=RuleFunctions.RuleFunctions.countDIGS(e),f=RuleFunctions.RuleFunctions.countSYMS(e),T=RuleFunctions.RuleFunctions.identifyDates(e),R=(RuleFunctions.RuleFunctions.verifyMinimumRequirements(e,t),RuleFunctions.RuleFunctions.alphabeticSequenceCheck(e)),C=RuleFunctions.RuleFunctions.commonSubstringCheck(e),F=RuleFunctions.RuleFunctions.combinedDictCheck(e),N=e.listSubstringsNoFilter(4),k=RuleFunctions.RuleFunctions.commonPwCheck(N),P=[1.53,.3129,.9912,.04637,-.03885,-.1172,-.2976,-8581e-7,-.3008,-.5566,0,.9108,.7369,.7578,0,-.1213,-.2402,-.1364,-.5534,1.927,.001496,-.3946],W=[1,d.length,p.count,u.count,c.count,m.score,g.count,w.score,x.score,b.score,y.score,$.count,v.count,M.count,f.count,T.count,R.count,C.count,F.length,F.dictionaryTokens,F.substitutionCommonness,k.length],S=P[0],H=1;H100&&(S=100),r.publicText.length>0&&(o.push(r.publicText),n.push(r.sensitiveText),a.push(r.reasonWhy),h.push(r.problemText)),l.publicText.length>0&&(o.push(l.publicText),n.push(l.sensitiveText),a.push(l.reasonWhy),h.push(l.problemText)),F.publicText.length>0&&!this.redundant(F.problemText,h)&&(o.push(F.publicText),n.push(F.sensitiveText),a.push(F.reasonWhy),h.push(F.problemText)),m.publicText.length>0&&(o.push(m.publicText),n.push(m.sensitiveText),a.push(m.reasonWhy),h.push(m.problemText)),c.publicText.length>0&&(o.push(c.publicText),n.push(c.sensitiveText),a.push(c.reasonWhy),h.push(c.problemText)),T.publicText.length>0&&(o.push(T.publicText),n.push(T.sensitiveText),a.push(T.reasonWhy),h.push(T.problemText)),g.publicText.length>0&&(o.push(g.publicText),n.push(g.sensitiveText),a.push(g.reasonWhy),h.push(g.problemText)),R.publicText.length>0&&(o.push(R.publicText),n.push(R.sensitiveText),a.push(R.reasonWhy),h.push(R.problemText)),k.publicText.length>0&&!this.redundant(k.problemText,h)&&(o.push(k.publicText),n.push(k.sensitiveText),a.push(k.reasonWhy),h.push(k.problemText)),x.publicText.length>0&&(o.push(x.publicText),n.push(x.sensitiveText),a.push(x.reasonWhy),h.push(x.problemText)),b.publicText.length>0&&(o.push(b.publicText),n.push(b.sensitiveText),a.push(b.reasonWhy),h.push(b.problemText)),y.publicText.length>0&&(o.push(y.publicText),n.push(y.sensitiveText),a.push(y.reasonWhy),h.push(y.problemText)),u.publicText.length>0&&(o.push(u.publicText),n.push(u.sensitiveText),a.push(u.reasonWhy),h.push(u.problemText)),d.publicText.length>0&&(o.push(d.publicText),n.push(d.sensitiveText),a.push(d.reasonWhy)),f.publicText.length>0&&(o.push(f.publicText),n.push(f.sensitiveText),a.push(f.reasonWhy)),$.publicText.length>0&&(o.push($.publicText),n.push($.sensitiveText),a.push($.reasonWhy)),M.publicText.length>0&&(o.push(M.publicText),n.push(M.sensitiveText),a.push(M.reasonWhy)),v.publicText.length>0&&(o.push(v.publicText),n.push(v.sensitiveText),a.push(v.reasonWhy)),C.publicText.length>0&&!this.redundant(C.problemText,h)&&(o.push(C.publicText),n.push(C.sensitiveText),a.push(C.reasonWhy)),w.publicText.length>0&&(o.push(w.publicText),n.push(w.sensitiveText),a.push(w.reasonWhy)),this.heuristicMapping[i]=S,this.feedbackMapping[i]=JSON.stringify({publictips1:o[0],publictips2:o[1],publictips3:o[2],sensitivetips1:n[0],sensitivetips2:n[1],sensitivetips3:n[2],reasonWhy1:a[0],reasonWhy2:a[1],reasonWhy3:a[2]}),s?(this.displayRating(i),b.fixedPw.length>0?(this.previousCandidate[i]=b.fixedPw,this.deltaHighlighted[b.fixedPw]=b.deltas):y.fixedPw.length>0&&(this.previousCandidate[i]=y.fixedPw,this.deltaHighlighted[y.fixedPw]=y.deltas)):this.synthesizeFixed(i)},e.prototype.displayRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0;if(e.length>0){void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(s=this.heuristicMapping[e],i++);var o=t.getNeuralNetNum(e),n=this.scaleGuessNumByMeterStringencyFactor(o);void 0!==o&&n>=0&&isFinite(n)&&(i++,(0==s||s>0&&n(Why?)
"),d+="

 

To make it even better:",this.$("#feedbackHeaderText").html(d),this.$("#feedbackHeaderTextModal").html(d)}else{var p="Your password appears strong.";h.remindAgainstReuse&&(p+=" Make sure you use it only for this account. (Why?)"),this.$("#feedbackHeaderText").html(p),this.$("#feedbackHeaderTextModal").html(p)}if(this.$(".nonmodalColorCell").show(),this.$(".modalColorCell").show(),this.$(".modalColorCellSpacer").show(),this.$(".recommended").show(),!0===this.$("#showHidePWNonModal").prop("checked")?(this.$(".fixedPWavailablePortal").hide(),this.$(".concreteSuggestionDiv").show(),this.$("#tipText1").html(a.sensitivetips1),this.$("#tipText2").html(a.sensitivetips2),this.$("#tipText3").html(a.sensitivetips3),this.$("#suggestion1").html(a.sensitivetips1),this.$("#suggestion2").html(a.sensitivetips2),this.$("#suggestion3").html(a.sensitivetips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)):(this.$(".fixedPWavailablePortal").show(),this.$(".concreteSuggestionDiv").hide(),this.$("#tipText1").html(a.publictips1),this.$("#tipText2").html(a.publictips2),this.$("#tipText3").html(a.publictips3),this.$("#suggestion1").html(a.publictips1),this.$("#suggestion2").html(a.publictips2),this.$("#suggestion3").html(a.publictips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)),h.provideConcretePasswordSuggestions&&void 0!==this.fixedpwMapping[e]){for(var u="",c=this.deltaHighlighted[this.fixedpwMapping[e]],m=this.fixedpwMapping[e],g=0;g"+m[g].escapeHTML()+"
":u+=m[g].escapeHTML();this.$(".fixedPW").html(u).trigger("change")}else this.$(".recommended").hide();s<=66?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show()):s<100?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show(),this.tookSuggestion&&(this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())):(this.$("#nonmodalFeedbackTable").hide(),this.$("#modalFeedbackTable").hide(),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())}else{this.inCompliance=!1,0!==e.length&&t.heardFromNn()&&2!==i||this.displayBar(s,!1,e),this.$("#confirmpw").hide(),this.$(".detailedFeedback").hide(),this.$(".portalToGenericAdviceModal").show(),this.$(".explainWhy").hide();var w="";(h=PasswordMeter.PasswordMeter.instance.getConfig()).remindAgainstReuse&&(w="Don't reuse a password from another account! (Why?)

 

");var x="Your password must:";this.$("#feedbackHeaderText").html(w+x),this.$("#feedbackHeaderTextModal").html(w+x),this.$("#nonmodalFeedbackTable").show(),this.$(".recommended").hide();var b=[],y=l.detail;for(var $ in y.compliance)y.compliance[$]||b.push(y.explanation[$]);this.$(".nonmodalColorCell").hide(),this.$(".modalColorCell").hide(),this.$(".modalColorCellSpacer").hide(),this.$(".nonmodalRow").hide(),this.$(".modalRow").hide();for(var v=0;v100&&(e=100);var i=e/100,o="rgb(160,160,160)";t&&i<.45?o="rgb("+Math.round(255)+","+Math.round(i/.45*140)+",0)":t&&i>=.45&&i<.65?o="rgb("+Math.round(255)+","+Math.round((i-.45)/.2*75+140)+",0)":t&&(o="rgb("+Math.round(255-(i-.65)/.35*205)+","+Math.round(215-(i-.65)/.035)+",0)");var n=PasswordMeter.PasswordMeter.instance.getNN(),a=this.scaleGuessNumByMeterStringencyFactor(n.getNeuralNetNum(s)),h=this.heuristicMapping[s];this.$("#cups-passwordmeter-span").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span").css("background-color",o).trigger("change",[e.toString(),h,a]),this.$("#cups-passwordmeter-span-modal").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span-modal").css("background-color",o)},e.prototype.getMaxOfArray=function(e){return Math.max.apply(null,e)},e.prototype.expandHelpBut=function(){this.$("#expandHelpDiv").show(),this.$("#helpButton").hide()},e.prototype.modalShowCheck=function(){"text"==this.$("#pwbox").prop("type")?(this.$("#myModal").show(),this.storepw()):this.$("#expandHelpDiv").is(":visible")?(this.$("#myModal").show(),this.storepw()):this.expandHelpBut()},e.prototype.closeDiv=function(e){this.$(e).hide()},e.prototype.deselect=function(e){null==this.$.fn.slideFadeToggle&&(this.$.fn.slideFadeToggle=function(e,t){return this.animate({opacity:"toggle",height:"toggle"},"fast",e,t)}),this.$(".pop").slideFadeToggle(function(){e.removeClass("selected")})},e}();e.UIMisc=o,t=PasswordMeter.PasswordMeter.instance,s=t.getJquery(),i=new o(!1),t.setUI(i),s(document).ready(function(){s("#showpassword").prop("checked",!1),s("#showpassword").click(function(){document.getElementById("hide-show-label").textContent="Hide Password",s("#cbbutton").css("background-color","#f5f5f5"),"password"==s("#pwbox").prop("type")?s("#pwbox").prop("type","text"):(s("#pwbox").prop("type","password"),document.getElementById("hide-show-label").textContent="Show Password",s("#cbbutton").css("background-color","#f5f5f5"))})}),s(document).ready(function(){var e=s("#pwboxModal");s("#tip1, #sensText1").mouseover(function(){e.addClass("problemColor")}),s("#tip2, #sensText2").mouseover(function(){e.addClass("problemColor")}),s("#tip3, #sensText3").mouseover(function(){e.addClass("problemColor")})}),s(document).ready(function(){i.onReady()})}(UIMisc=exports.UIMisc||(exports.UIMisc={})); +"use strict";exports.__esModule=!0;var UIMisc,PasswordMeter=require("./PasswordMeter"),RuleFunctions=require("./rulefunctions"),Constants=require("./constants");!function(e){var t,s,i,o=function(){function e(e){this.pwWhenModalOpened="",this.tookSuggestion=!1,this.previouslyRated="",this.heuristicMapping={},this.feedbackMapping={},this.recommendedFixes={},this.recommendedFixesTries={},this.previousCandidate={},this.fixedpwMapping={},this.deltaHighlighted={},this.inCompliance=!1,this.randomlyOrderedCharClasses=[];var t=PasswordMeter.PasswordMeter.instance;this.helper=t.getHelper(),this.$=t.getJquery(),this.verboseMode=e;this.randomlyOrderedCharClasses=function(e){for(var t,s,i=e.length;0!==i;)s=Math.floor(Math.random()*i),t=e[i-=1],e[i]=e[s],e[s]=t;return e}(["uppercase letter","lowercase letter","digit","symbol"])}return e.prototype.getRandomlyOrderedCharClasses=function(){return this.randomlyOrderedCharClasses},e.prototype.getCharClassStringForCharClassCountReq=function(){return this.randomlyOrderedCharClasses.map(function(e){return e+"s"}).join("; ")},e.prototype.getCharClassStringForMandatoryCharClassReq=function(){for(var e=PasswordMeter.PasswordMeter.instance.getConfig(),t="",s=0;s0?t+=" and an uppercase letter":t="Contain an uppercase letter");break;case"lowercase letter":e.classRequire.lowerCase&&(t.length>0?t+=" and a lowercase letter":t="Contain a lowercase letter");break;case"digit":e.classRequire.digits&&(t.length>0?t+=" and a digit":t="Contain a digit");break;case"symbol":e.classRequire.symbols&&(t.length>0?t+=" and a symbol":t="Contain a symbol")}}return t},e.prototype.onReady=function(){this.$(".pop").fadeIn(),this.$("#showHidePWNonModal").prop("checked",!1),this.toggleShowHideNonModal(),this.spawnRating()},e.prototype.toggleShowHideNonModal=function(){this.$("#showHidePWNonModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWModal").prop("checked",!1)),this.spawnRating()},e.prototype.toggleShowHideModal=function(){this.$("#showHidePWModal").prop("checked")?(this.$("#pwbox").prop("type","text"),this.$("#pwboxModal").prop("type","text"),this.$("#showHidePWNonModal").prop("checked",!0)):(this.$("#pwbox").prop("type","password"),this.$("#pwboxModal").prop("type","password"),this.$("#showHidePWNonModal").prop("checked",!1)),this.spawnRating()},e.prototype.storepw=function(){var e=this.$("#pwbox").val();this.pwWhenModalOpened=e,this.$("#pwboxModal").val(e)},e.prototype.enableDiscard=function(){this.$("#pwboxModal").val()===this.pwWhenModalOpened?(this.$("#discardButton").hide(),this.$("#keepButton").html("OK")):(this.$("#discardButton").show(),this.$("#keepButton").html("Keep Changes"))},e.prototype.keeppw=function(){this.$("#pwbox").val(this.$("#pwboxModal").val())},e.prototype.discardpw=function(){this.$("#pwbox").val(this.pwWhenModalOpened)},e.prototype.fixPWNonModal=function(){this.tookSuggestion=!0;var e=this.$("#nonmodalFixedPW").text();this.$("#pwbox").val(e),this.spawnRating()},e.prototype.fixPWModal=function(){this.tookSuggestion=!0;var e=this.$("#modalFixedPW").text();this.$("#pwboxModal").val(e),this.spawnRating(),this.enableDiscard()},e.prototype.showModal=function(){this.storepw(),this.$("#discardButton").hide(),this.$("#keepButton").html("OK"),this.$("#myModal").modal("show")},e.prototype.mayberate=function(){this.$("#pwbox").val()!==this.previouslyRated&&(this.previouslyRated=this.$("#pwbox").val(),this.spawnRating())},e.prototype.continueCheck=function(e){var t=!0;e&&(this.$("#usernamebox").val().length<1?(this.$("#usernameTooShort").show(),t=!1):this.$("#usernameTooShort").hide());this.inCompliance?(this.$("#feedbackHeaderText").css({color:"","font-weight":""}),this.$("#passwordNonCompliant").hide()):(t=!1,this.$("#confirmDoesNotMatch").hide(),e&&(this.$("#feedbackHeaderText").css({color:"red","font-weight":"bold"}),this.$("#passwordNonCompliant").show())),this.$("#pwbox").val()!==this.$("#confirmbox").val()?(t=!1,e&&this.inCompliance&&this.$("#confirmDoesNotMatch").show()):this.$("#confirmDoesNotMatch").hide(),e&&t&&continueSubmit()},e.prototype.scaleGuessNumByMeterStringencyFactor=function(e){return e>0?e*Constants.Constants.METER_STRINGENCY_SCALE_FACTOR:e},e.prototype.spawnRating=function(){var e="",t=PasswordMeter.PasswordMeter.instance.getNN();e=this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown?this.$("#pwboxModal").val():this.$("#pwbox").val();var s=this.$("#usernamebox").val(),i=0,o=t.getNeuralNetNum(e);void 0===o?(t.setNeuralNetNum(e,-1),t.queryGuessNumber(e,!1)):o>=0&&i++,void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!0):this.heuristicMapping[e]>=0&&i++,0!==e.length&&t.heardFromNn()&&2!==i||this.displayRating(e)},e.prototype.generateCandidateFixed=function(e,t,s){if(!PasswordMeter.PasswordMeter.instance.getConfig().provideConcretePasswordSuggestions)return 1;var i=[];if(void 0===this.deltaHighlighted[e])for(var o=0;o=65&&n.charCodeAt(r)<=90?(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)+32)),i[r]=1):n.charCodeAt(r)>=97&&n.charCodeAt(r)<=122&&(n=n.replaceAt(r,String.fromCharCode(n.charCodeAt(r)-32)),i[r]=1)}else if(2===a||3===a){var l=32+Math.floor(95*Math.random()),d=Math.floor(n.length*Math.random());n.charCodeAt(d)!==l&&(i[d]=1),n=n.replaceAt(d,String.fromCharCode(l))}else if(a>=4){l=32+Math.floor(95*Math.random()),d=Math.floor((n.length+1)*Math.random());n=n.slice(0,d)+String.fromCharCode(l)+n.slice(d),i=i.slice(0,d).concat(1,i.slice(d))}var p=PasswordMeter.PasswordMeter.instance.getNN();void 0===p.getNeuralNetNum(n)&&(p.setNeuralNetNum(n,-1),p.queryGuessNumber(n,!0));var u=this.$("#usernamebox").val();return void 0===this.heuristicMapping[n]&&this.queryHeuristicGuessNumber(n,u,!1),RuleFunctions.RuleFunctions.verifyMinimumRequirements(n,u).compliant?(this.recommendedFixes[s]=n,this.deltaHighlighted[n]=i,this.verboseMode&&console.log("identified "+n+" as a potential fix for "+s),void 0===this.recommendedFixesTries[s]?this.recommendedFixesTries[s]=1:this.recommendedFixesTries[s]=this.recommendedFixesTries[s]+1,this.spawnFixedRating(n)):++t<8&&this.generateCandidateFixed(e,t,s),1},e.prototype.spawnFixedRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=this.$("#usernamebox").val();void 0===this.heuristicMapping[e]?this.queryHeuristicGuessNumber(e,s,!1):t.getNeuralNetNum(e)>=0&&this.heuristicMapping[e]>=0&&this.synthesizeFixed(e)},e.prototype.synthesizeFixed=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0,o=!1;void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(i++,s=this.heuristicMapping[e]);var n=t.getNeuralNetNum(e),a=this.scaleGuessNumByMeterStringencyFactor(n);if(void 0!==n&&a>=0&&isFinite(a)&&(i++,(0===s||s>0&&a=67){for(var h in this.verboseMode&&console.log(e+" is a plausible fix above the 2/3rds threshold"),this.recommendedFixes)if(this.recommendedFixes[h]===e&&void 0===this.fixedpwMapping[h]){var r=0;void 0!==this.heuristicMapping[h]&&this.heuristicMapping[h]>=0&&(r=this.heuristicMapping[h]);var l=t.getNeuralNetNum(h),d=this.scaleGuessNumByMeterStringencyFactor(l);void 0!==l&&d>=0&&isFinite(d)&&(0===r||r>0&&dr+15?(this.fixedpwMapping[h]=e,this.verboseMode&&console.log("mapping "+h+" to "+e),o=!0):this.verboseMode&&console.log("not mapping "+h+" to "+e+" because it is not enough of an improvement "+r+" --\x3e "+s)}return o&&this.spawnRating(),1}var p=this.$("#pwbox").val();return this.$("#myModal").data("bs.modal")&&this.$("#myModal").data("bs.modal").isShown&&(p=this.$("#pwboxModal").val()),this.recommendedFixes[p]===e&&2===i&&void 0===this.fixedpwMapping[p]&&void 0!==this.recommendedFixesTries[p]&&this.recommendedFixesTries[p]<8&&(this.verboseMode&&console.log("trying again on "+e+" as current password is "+p),this.generateCandidateFixed(e,0,p)),1},e.prototype.redundant=function(e,t){e=e.toLowerCase();for(var s=0;s0&&e.length>0&&(t[s].indexOf(e)>=0&&e.length>=.7*t[s].length||e.indexOf(t[s])>=0&&t[s].length>=.7*e.length))return!0;return!1},e.prototype.queryHeuristicGuessNumber=function(e,t,s){var i=e,o=[],n=[],a=[],h=[],r=RuleFunctions.RuleFunctions.contextual(e,[t]);void 0===(e=r.remaining)&&(e="");var l=RuleFunctions.RuleFunctions.blacklist(e);void 0===(e=l.remaining)&&(e="");for(var d=RuleFunctions.RuleFunctions.pwLength(e),p=RuleFunctions.RuleFunctions.characterClasses(e),u=RuleFunctions.RuleFunctions.duplicatedCharacters(e),c=RuleFunctions.RuleFunctions.repeats(e),m=RuleFunctions.RuleFunctions.keyboardPatterns(e),g=RuleFunctions.RuleFunctions.repeatedSections(e),w=RuleFunctions.RuleFunctions.structurePredictable(e),x=RuleFunctions.RuleFunctions.uppercasePredictable(e),b=RuleFunctions.RuleFunctions.digitsPredictable(e),y=RuleFunctions.RuleFunctions.symbolsPredictable(e),$=RuleFunctions.RuleFunctions.countUC(e),M=RuleFunctions.RuleFunctions.countLC(e),v=RuleFunctions.RuleFunctions.countDIGS(e),f=RuleFunctions.RuleFunctions.countSYMS(e),T=RuleFunctions.RuleFunctions.identifyDates(e),C=(RuleFunctions.RuleFunctions.verifyMinimumRequirements(e,t),RuleFunctions.RuleFunctions.alphabeticSequenceCheck(e)),R=RuleFunctions.RuleFunctions.commonSubstringCheck(e),F=RuleFunctions.RuleFunctions.combinedDictCheck(e),N=e.listSubstringsNoFilter(4),k=RuleFunctions.RuleFunctions.commonPwCheck(N),P=[1.53,.3129,.9912,.04637,-.03885,-.1172,-.2976,-8581e-7,-.3008,-.5566,0,.9108,.7369,.7578,0,-.1213,-.2402,-.1364,-.5534,1.927,.001496,-.3946],W=[1,d.length,p.count,u.count,c.count,m.score,g.count,w.score,x.score,b.score,y.score,$.count,M.count,v.count,f.count,T.count,C.count,R.count,F.length,F.dictionaryTokens,F.substitutionCommonness,k.length],S=P[0],H=1;H100&&(S=100),r.publicText.length>0&&(o.push(r.publicText),n.push(r.sensitiveText),a.push(r.reasonWhy),h.push(r.problemText)),l.publicText.length>0&&(o.push(l.publicText),n.push(l.sensitiveText),a.push(l.reasonWhy),h.push(l.problemText)),F.publicText.length>0&&!this.redundant(F.problemText,h)&&(o.push(F.publicText),n.push(F.sensitiveText),a.push(F.reasonWhy),h.push(F.problemText)),m.publicText.length>0&&(o.push(m.publicText),n.push(m.sensitiveText),a.push(m.reasonWhy),h.push(m.problemText)),c.publicText.length>0&&(o.push(c.publicText),n.push(c.sensitiveText),a.push(c.reasonWhy),h.push(c.problemText)),T.publicText.length>0&&(o.push(T.publicText),n.push(T.sensitiveText),a.push(T.reasonWhy),h.push(T.problemText)),g.publicText.length>0&&(o.push(g.publicText),n.push(g.sensitiveText),a.push(g.reasonWhy),h.push(g.problemText)),C.publicText.length>0&&(o.push(C.publicText),n.push(C.sensitiveText),a.push(C.reasonWhy),h.push(C.problemText)),k.publicText.length>0&&!this.redundant(k.problemText,h)&&(o.push(k.publicText),n.push(k.sensitiveText),a.push(k.reasonWhy),h.push(k.problemText)),x.publicText.length>0&&(o.push(x.publicText),n.push(x.sensitiveText),a.push(x.reasonWhy),h.push(x.problemText)),b.publicText.length>0&&(o.push(b.publicText),n.push(b.sensitiveText),a.push(b.reasonWhy),h.push(b.problemText)),y.publicText.length>0&&(o.push(y.publicText),n.push(y.sensitiveText),a.push(y.reasonWhy),h.push(y.problemText)),u.publicText.length>0&&(o.push(u.publicText),n.push(u.sensitiveText),a.push(u.reasonWhy),h.push(u.problemText)),d.publicText.length>0&&(o.push(d.publicText),n.push(d.sensitiveText),a.push(d.reasonWhy)),f.publicText.length>0&&(o.push(f.publicText),n.push(f.sensitiveText),a.push(f.reasonWhy)),$.publicText.length>0&&(o.push($.publicText),n.push($.sensitiveText),a.push($.reasonWhy)),v.publicText.length>0&&(o.push(v.publicText),n.push(v.sensitiveText),a.push(v.reasonWhy)),M.publicText.length>0&&(o.push(M.publicText),n.push(M.sensitiveText),a.push(M.reasonWhy)),R.publicText.length>0&&!this.redundant(R.problemText,h)&&(o.push(R.publicText),n.push(R.sensitiveText),a.push(R.reasonWhy)),w.publicText.length>0&&(o.push(w.publicText),n.push(w.sensitiveText),a.push(w.reasonWhy)),this.heuristicMapping[i]=S,this.feedbackMapping[i]=JSON.stringify({publictips1:o[0],publictips2:o[1],publictips3:o[2],sensitivetips1:n[0],sensitivetips2:n[1],sensitivetips3:n[2],reasonWhy1:a[0],reasonWhy2:a[1],reasonWhy3:a[2]}),s?(this.displayRating(i),b.fixedPw.length>0?(this.previousCandidate[i]=b.fixedPw,this.deltaHighlighted[b.fixedPw]=b.deltas):y.fixedPw.length>0&&(this.previousCandidate[i]=y.fixedPw,this.deltaHighlighted[y.fixedPw]=y.deltas)):this.synthesizeFixed(i)},e.prototype.displayRating=function(e){var t=PasswordMeter.PasswordMeter.instance.getNN(),s=0,i=0;if(e.length>0){void 0!==this.heuristicMapping[e]&&this.heuristicMapping[e]>=0&&(s=this.heuristicMapping[e],i++);var o=t.getNeuralNetNum(e),n=this.scaleGuessNumByMeterStringencyFactor(o);void 0!==o&&n>=0&&isFinite(n)&&(i++,(0==s||s>0&&n(Why?)
"),d+="

 

To make it even better:",this.$("#feedbackHeaderText").html(d),this.$("#feedbackHeaderTextModal").html(d)}else{var p="Your password appears strong.";h.remindAgainstReuse&&(p+=" Make sure you use it only for this account. (Why?)"),this.$("#feedbackHeaderText").html(p),this.$("#feedbackHeaderTextModal").html(p)}if(this.$(".nonmodalColorCell").show(),this.$(".modalColorCell").show(),this.$(".modalColorCellSpacer").show(),this.$(".recommended").show(),!0===this.$("#showHidePWNonModal").prop("checked")?(this.$(".fixedPWavailablePortal").hide(),this.$(".concreteSuggestionDiv").show(),this.$("#tipText1").html(a.sensitivetips1),this.$("#tipText2").html(a.sensitivetips2),this.$("#tipText3").html(a.sensitivetips3),this.$("#suggestion1").html(a.sensitivetips1),this.$("#suggestion2").html(a.sensitivetips2),this.$("#suggestion3").html(a.sensitivetips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)):(this.$(".fixedPWavailablePortal").show(),this.$(".concreteSuggestionDiv").hide(),this.$("#tipText1").html(a.publictips1),this.$("#tipText2").html(a.publictips2),this.$("#tipText3").html(a.publictips3),this.$("#suggestion1").html(a.publictips1),this.$("#suggestion2").html(a.publictips2),this.$("#suggestion3").html(a.publictips3),this.$("#sensText1").html(a.reasonWhy1),this.$("#sensText2").html(a.reasonWhy2),this.$("#sensText3").html(a.reasonWhy3)),h.provideConcretePasswordSuggestions&&void 0!==this.fixedpwMapping[e]){for(var u="",c=this.deltaHighlighted[this.fixedpwMapping[e]],m=this.fixedpwMapping[e],g=0;g"+m[g].escapeHTML()+"
":u+=m[g].escapeHTML();!0===this.$("#showHidePWNonModal").prop("checked")&&this.$(".fixedPW").html(u).trigger("change")}else this.$(".recommended").hide();s<=66?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show()):s<100?(this.$("#nonmodalFeedbackTable").show(),this.$("#modalFeedbackTable").show(),this.$(".portalToGenericAdviceModal").show(),this.tookSuggestion&&(this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())):(this.$("#nonmodalFeedbackTable").hide(),this.$("#modalFeedbackTable").hide(),this.$(".recommended").hide(),this.$(".portalToGenericAdviceModal").hide())}else{this.inCompliance=!1,0!==e.length&&t.heardFromNn()&&2!==i||this.displayBar(s,!1,e),this.$("#confirmpw").hide(),this.$(".detailedFeedback").hide(),this.$(".portalToGenericAdviceModal").show(),this.$(".explainWhy").hide();var w="";(h=PasswordMeter.PasswordMeter.instance.getConfig()).remindAgainstReuse&&(w="Don't reuse a password from another account! (Why?)

 

");var x="Your password must:";this.$("#feedbackHeaderText").html(w+x),this.$("#feedbackHeaderTextModal").html(w+x),this.$("#nonmodalFeedbackTable").show(),this.$(".recommended").hide();var b=[],y=l.detail;for(var $ in y.compliance)y.compliance[$]||b.push(y.explanation[$]);this.$(".nonmodalColorCell").hide(),this.$(".modalColorCell").hide(),this.$(".modalColorCellSpacer").hide(),this.$(".nonmodalRow").hide(),this.$(".modalRow").hide();for(var M=0;M100&&(e=100);var i=e/100,o="rgb(160,160,160)";t&&i<.45?o="rgb("+Math.round(255)+","+Math.round(i/.45*140)+",0)":t&&i>=.45&&i<.65?o="rgb("+Math.round(255)+","+Math.round((i-.45)/.2*75+140)+",0)":t&&(o="rgb("+Math.round(255-(i-.65)/.35*205)+","+Math.round(215-(i-.65)/.035)+",0)");var n=PasswordMeter.PasswordMeter.instance.getNN(),a=this.scaleGuessNumByMeterStringencyFactor(n.getNeuralNetNum(s)),h=this.heuristicMapping[s];this.$("#cups-passwordmeter-span").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span").css("background-color",o).trigger("change",[e.toString(),h,a]),this.$("#cups-passwordmeter-span-modal").css("width",Math.round(298*e/100).toString()+"px"),this.$("#cups-passwordmeter-span-modal").css("background-color",o)},e.prototype.getMaxOfArray=function(e){return Math.max.apply(null,e)},e.prototype.expandHelpBut=function(){this.$("#expandHelpDiv").show(),this.$("#helpButton").hide()},e.prototype.modalShowCheck=function(){"text"==this.$("#pwbox").prop("type")?(this.$("#myModal").show(),this.storepw()):this.$("#expandHelpDiv").is(":visible")?(this.$("#myModal").show(),this.storepw()):this.expandHelpBut()},e.prototype.closeDiv=function(e){this.$(e).hide()},e.prototype.deselect=function(e){null==this.$.fn.slideFadeToggle&&(this.$.fn.slideFadeToggle=function(e,t){return this.animate({opacity:"toggle",height:"toggle"},"fast",e,t)}),this.$(".pop").slideFadeToggle(function(){e.removeClass("selected")})},e}();e.UIMisc=o,t=PasswordMeter.PasswordMeter.instance,s=t.getJquery(),i=new o(!1),t.setUI(i),s(document).ready(function(){s("#showpassword").prop("checked",!1),s("#showpassword").click(function(){document.getElementById("hide-show-label").textContent="Hide Password",s("#cbbutton").css("background-color","#f5f5f5"),"password"==s("#pwbox").prop("type")?s("#pwbox").prop("type","text"):(s("#pwbox").prop("type","password"),document.getElementById("hide-show-label").textContent="Show Password",s("#cbbutton").css("background-color","#f5f5f5"))})}),s(document).ready(function(){var e=s("#pwboxModal");s("#tip1, #sensText1").mouseover(function(){e.addClass("problemColor")}),s("#tip2, #sensText2").mouseover(function(){e.addClass("problemColor")}),s("#tip3, #sensText3").mouseover(function(){e.addClass("problemColor")})}),s(document).ready(function(){i.onReady()})}(UIMisc=exports.UIMisc||(exports.UIMisc={})); },{"./PasswordMeter":3,"./constants":6,"./rulefunctions":10}]},{},[3,4,5,6,7,8,9,10,11,12]); diff --git a/src/ts/ui-misc.ts b/src/ts/ui-misc.ts index 3277a79..9713167 100644 --- a/src/ts/ui-misc.ts +++ b/src/ts/ui-misc.ts @@ -97,6 +97,10 @@ export module UIMisc { this.randomlyOrderedCharClasses = shuffle(charClasses); } + getRandomlyOrderedCharClasses() { + return this.randomlyOrderedCharClasses; + } + // return randomly-ordered list of all 4 character classes, as string getCharClassStringForCharClassCountReq(): string { var pluralalizedCharClasses = this.randomlyOrderedCharClasses.map(x => x + "s"); @@ -1007,7 +1011,12 @@ export module UIMisc { } } - this.$(".fixedPW").html(coloredFixedPW).trigger("change"); + // if we have actually showed the user a concrete password suggestion + // (if they clicked 'show password with our improvements' or clicked to show + // their password in plaintext on the screen), then trigger an event + if (this.$("#showHidePWNonModal").prop("checked") === true) { + this.$(".fixedPW").html(coloredFixedPW).trigger("change"); + } // If we don't yet have a concrete suggestion } else { this.$(".recommended").hide(); From ef77b4efcea141ceeb882e96467359e10441de52 Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Fri, 8 Mar 2019 14:50:02 -0500 Subject: [PATCH 17/45] Fixed bug where bar would not revert to reflect pre-concrete-password-enhancement, in the case when a user modifies their password in the modal but then chooses to discard that password when returning to the main meter password box. --- example/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/index.html b/example/index.html index af81ecc..44d81c0 100644 --- a/example/index.html +++ b/example/index.html @@ -326,7 +326,7 @@
Ways to Improve Your Password
From 7d1d74c05bd4f62e01412abda621cb7b9f65ce92 Mon Sep 17 00:00:00 2001 From: Josh Tan Date: Fri, 8 Mar 2019 15:23:40 -0500 Subject: [PATCH 18/45] Updated password meter config in example html file. --- example/index.html | 48 ++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/example/index.html b/example/index.html index 44d81c0..2b89590 100644 --- a/example/index.html +++ b/example/index.html @@ -48,6 +48,8 @@ @@ -237,10 +251,10 @@ - +
 
@@ -276,7 +290,7 @@
Ways to Improve Your Password
Show Password & Detailed Feedback