Fork me on GitHub

Password Score



Score

The Score class is used to calculate entropy scores of passwords. The entropy score is directly proportional to the strength of a password. The score can be calculated using a naive approach - mostly overestimating the strength of simple passwords - or using a more sophisticated approach - aiming to underestimate passwords such that users are encouraged to choose stronger passwords.

The class can easily be used to build a strength meter as for example Bootstrap Strength Meter.

Constructor

new Score(password);
Parameters
password
The non-empty password to score.

Score.calculateEntropyScore

This method is used to calculate a realistic entropy score of the password. This score can be used to reliably estimate the strength of a password.

score = new Score(password);
score.calculateEntropyScore()
score.calculateEntropyScore(options);
score.calculateEnoptryScore(options, append);
Parameters
options

The optiosn to configure how to calculate the score. If not provided, the default options are used, see below. For details on the available options see the Documentation.

var defaultOptions = [
    {
        'type': 'dictionary',
        'leet': true,
        'key': 'en',
        'dictionary': {"you":1,"the":2,"to":3, /* see data/json/last.json ... */}
    },
    {
        'type': 'dictionary',
        'leet': true,
        'key': 'de',
        'dictionary': {"ich":1,"sie":2,"das":3, /* see data/json/last.json ... */}
    },
    {
        'type': 'dictionary',
        'leet': true,
        'key': 'countries_en',
        'dictionary': {"afghanistan":1,"albania":2,"algeria":3, /* see data/json/countries-en.json ... */}
    },
    {
        'type': 'dictionary',
        'leet': true,
        'key': 'countries_de',
        'dictionary': {"afghanistan":1,"alandinseln":2,"albanien":3, /* see data/json/countries-de.json ... */}
    },
    {
        'type': 'dictionary',
        'leet': true,
        'key': 'cities',
        'dictionary': {"Shanghai":1,"Mumbai":2,"Mexico City":3, /* see data/json/cities.json ... */}
    },
    {
        'type': 'dictionary',
        'leet': true,
        'key': 'last',
        'dictionary': {"smith":1,"johnson":2,"williams":3, /* see data/json/last.json ... */}
    },
    {
        'type': 'dictionary',
        'leet': true,
        'key': 'female',
        'dictionary': {"mary":1,"patricia":2,"linda":3,  /* see data/json/last.json ... */}
    },
    {
        'type': 'dictionary',
        'leet': true,
        'key': 'male',
        'dictionary': {"james":1,"john":2,"robert":3, /* see data/json/last.json ... */}
    },
    {
        'type': 'dictionary',
        'leet': true,
        'key': 'passwords',
        'dictionary': {"password":1,"123456":2,"12345678":3, /* see data/json/last.json ... */}
    },
    {
        'type': 'keyboard',
        'key': 'qwerty',
        'keyboard': this.keyboards.QWERTY
    },
    {
        'type': 'keyboard',
        'key': 'qwertz',
        'keyboard': this.keyboards.QWERTZ
    },
    {
        'type': 'keyboard',
        'key': 'qwerty_numpad',
        'keyboard': this.keyboards.QWERTYNumpad
    },
    {
        'type': 'keyboard',
        'key': 'qwertz_numpad',
        'keyboard': this.keyboards.QWERTZNumpad
    },
    {
        'type': 'repetition',
        'key': 'repetition'
    },
    {
        'type': 'sequences',
        'key': 'sequences'
    },
    {
        'type': 'dates',
        'key': 'dates'
    }
];
append
The default options given above can be used as base such that additional dictionaries can easily be added using the options parameter. However, the default dictionaries can also be replaced by providing custom options and setting append to false, that is the provided options are not appended to the default ones.
Returns The method returns the calculated score which may range from zero to infinity. Check the demonstration to get a feeling for the calculated score.

Score.calculateBruteForceEntropy

This method is used to calculate a naive entropy score, that is the password is not searched for patterns or dictionary entries.

score = new Score(password);
score.calculateBruteForceEntropy();
Returns The method returns the naive entropy score.

Score.calculateAverageTimeToCrack

This method can be used to calculate the average number of seconds needed to crack a password with the given entropy score. The method assumes that it takes $0.005$ seconds to check a single password.

score = new Score(password);
var entropy = score.calculateBruteForceEntropy();
score.calculateAverageTimeToCrack(entropy, cores);
Parameters
entropy
The entropy of the password as calculated by calculateEntropyScore or calculateBruteForceEntropy.
cores
The number of cores used to crack the password.
Returns The method returns the number of seconds needed on average to crack the a password with the given entropy score.

Score.cache

Running calculateEntropyScore or calculateBruteForceEntropy will cause Password Score to save some details in Score.cache:

Score.cache.entropy The entropy score calculated by calculateEntropyScore.
Score.cache.minimumMatches The array of all patterns found by Password Score and corresponding to the calculated entropy score.
Score.cache[key]

key may be any string given during the configuration when using calculateEntropyScore, see the documentation of calculateEntropyScore or the following example:

// Remember the first dictionary of the default options:
var options = [
    {
        'type': 'dictionary',
        'leet': true,
        'key': 'en',
        'dictionary': {"you":1,"the":2,"to":3, /* see data/json/last.json ... */}
    },
];
// ...
score = new Score(password);
score.calculateEntropyScore();
console.log(score.cache['en']);
Score.cache.naiveEntropy The entropy calculated by calculateBruteForceEntropy.
Score.cache.clear This method clears the cache. However, it is not necessary ot use this while not changing the configuration as all relevant information is overwritten when running calculateEntropyScore or calculateBruteForceEntropy repeatedly.

Keyboard

The Keyboard class is used to represent a specific keyboard layout as undirected graph. This class is mainly used by the Score class to find keyboard patterns.

Constructor

new Keyboard(adjacencyList, averageDegree);
Parameters
adjacencyList

A keyboard is primarily defined by an adjacency list, that is each key on the keyboard has six neighbors. However, the adjacency list always includes the key itself. An example is shown below:

QWERTY: new Keyboard({
    '~': [null, null, null, '~`', '1!', null, null], // 1
    '`': [null, null, null, '~`', '1!', null, null], // 1
    '1': [null, null, '`~', '1!', '2@', null, 'qQ'], // 3
    '!': [null, null, '`~', '1!', '2@', null, 'qQ'], // 3
    '2': [null, null, '1!', '2@', '3#', 'qQ', 'wW'], // 4
    '@': [null, null, '1!', '2@', '3#', 'qQ', 'wW'], //4
    '3': [null, null, '2@', '3#', '4$', 'wW', 'eE'], //4
    '#': [null, null, '2@', '3#', '4$', 'wW', 'eE'], //4
    '4': [null, null, '3#', '4$', '5%', 'eE', 'rR'], //4
    '$': [null, null, '3#', '4$', '5%', 'eE', 'rR'], //4
    '5': [null, null, '4$', '5%', '6^', 'rR', 'tT'], //4
    '%': [null, null, '4$', '5%', '6^', 'rR', 'tT'], //4
    '6': [null, null, '5%', '6^', '7&', 'tT', 'yY'], //4
    '^': [null, null, '5%', '6^', '7&', 'tT', 'yY'], //4
    '7': [null, null, '6^', '7&', '8*', 'yY', 'uU'], //4
    '&': [null, null, '6^', '7&', '8*', 'yY', 'uU'], //4
    '8': [null, null, '7&', '8*', '9(', 'uU', 'iI'], // 4
    '*': [null, null, '7&', '8*', '9(', 'uU', 'iI'], // 4
    '9': [null, null, '8*', '9(', '0)', 'iI', 'oO'], // 4
    '(': [null, null, '8*', '9(', '0)', 'iI', 'oO'], // 4
    '0': [null, null, '9(', '0)', '-_', 'oO', 'pP'], // 4
    ')': [null, null, '9(', '0)', '-_', 'oO', 'pP'], // 4
    '-': [null, null, '0)', '-_', '=+', 'pP', '[{'], // 4
    '_': [null, null, '0)', '-_', '=+', 'pP', '[{'], // 4
    '=': [null, null, '-_', '=+', '\\|', '{[', '}]'], // 4
    '+': [null, null, '-_', '=+', '\\|', '{[', '}]'], // 4
    '\\': [null, null, '=+', '\\|', null, '}]', null], // 2
    '|': [null, null, '=+', '\\|', null, '}]', null], // 2
    'q': ['1!', '2@', null, 'qQ', 'wW', null, 'aA'], // 4
    'Q': ['1!', '2@', null, 'qQ', 'wW', null, 'aA'], // 4
    'w': ['2@', '3#', 'qQ', 'wW','eE', 'aA', 'sS'], // 6
    'W': ['2@', '3#', 'qQ', 'wW','eE', 'aA', 'sS'], // 6
    'e': ['3#', '4$', 'wW', 'eE', 'rR', 'sS', 'dD'], // 6
    'E': ['3#', '4$', 'wW', 'eE', 'rR', 'sS', 'dD'], // 6
    'r': ['4$', '5%', 'eE', 'rR', 'tT', 'dD', 'fF'], // 6
    'R': ['4$', '5%', 'eE', 'rR', 'tT', 'dD', 'fF'], // 6
    't': ['5%', '6^', 'rR', 'tT', 'yY', 'fF', 'gG'], // 6
    'T': ['5%', '6^', 'rR', 'tT', 'yY', 'fF', 'gG'], // 6
    'y': ['6^', '7&', 'tT', 'yY', 'uU', 'gG', 'hH'], // 6
    'Y': ['6^', '7&', 'tT', 'yY', 'uU', 'gG', 'hH'], // 6
    'u': ['7&', '8*', 'yY', 'uU', 'iI', 'hH', 'jJ'], // 6
    'U': ['7&', '8*', 'yY', 'uU', 'iI', 'hH', 'jJ'], // 6
    'i': ['8*', '9(', 'uU', 'iI', 'oO', 'jJ', 'kK'], // 6
    'I': ['8*', '9(', 'uU', 'iI', 'oO', 'jJ', 'kK'], // 6
    'o': ['9(', '0)', 'iI', 'oO', 'pP', 'kK', 'lL'], // 6
    'O': ['9(', '0)', 'iI', 'oO', 'pP', 'kK', 'lL'], // 6
    'p': ['0)', '-_', 'oO', 'pP', '[{', 'lL', ':;'], // 6
    'P': ['0)', '-_', 'oO', 'pP', '[{', 'lL', ':;'], // 6
    '[': ['-_', '=+', 'pP', '[{', ']}', ':;', '\'"'], // 6
    '{': ['-_', '=+', 'pP', '[{', ']}', ':;', '\'"'], // 6
    ']': ['=+', '\\|', '[{', ']}', null, '\'"', null], // 4
    '}': ['=+', '\\|', '[{', ']}', null, '\'"', null], // 4
    'a': ['qQ', 'wW', null, 'aA', 'sS', null, 'zZ'], // 4
    'A': ['qQ', 'wW', null, 'aA', 'sS', null, 'zZ'], // 4
    's': ['wW', 'eE', 'aA', 'sS', 'dD', 'zZ', 'xX'], // 6
    'S': ['wW', 'eE', 'aA', 'sS', 'dD', 'zZ', 'xX'], // 6
    'd': ['eE', 'rR', 'sS', 'dD', 'fF', 'xX', 'cC'], // 6
    'D': ['eE', 'rR', 'sS', 'dD', 'fF', 'xX', 'cC'], // 6
    'f': ['rR', 'tT', 'dD', 'fF', 'gG', 'cC', 'vV'], // 6
    'F': ['rR', 'tT', 'dD', 'fF', 'gG', 'cC', 'vV'], // 6
    'g': ['tT', 'yY', 'fF', 'gG', 'hH', 'vV', 'bB'], // 6
    'G': ['tT', 'yY', 'fF', 'gG', 'hH', 'vV', 'bB'], // 6
    'h': ['yY', 'uU', 'gG', 'hH', 'jJ', 'bB', 'nN'], // 6
    'H': ['yY', 'uU', 'gG', 'hH', 'jJ', 'bB', 'nN'], // 6
    'j': ['uU', 'iI', 'hH', 'jJ', 'kK', 'nN', 'mM'], // 6
    'J': ['uU', 'iI', 'hH', 'jJ', 'kK', 'nN', 'mM'], // 6
    'k': ['iI', 'oO', 'jJ', 'kK', 'lL', 'mM', ',;'], // 6
    'K': ['iI', 'oO', 'jJ', 'kK', 'lL', 'mM', ',;'], // 6
    'l': ['oO', 'pP', 'kK', 'lL', ':;', ',<', '.>'], // 6
    'L': ['oO', 'pP', 'kK', 'lL', ':;', ',<', '.>'], // 6
    ':': ['pP', '[{', 'lL', ':;', '\'"', '.>', '?/'], // 6
    ';': ['pP', '[{', 'lL', ':;', '\'"', '.>', '?/'], // 6
    '\'': ['[{', ']}', ':;', '\'"', null, '?/', null], // 5
    '"': ['[{', ']}', ':;', '\'"', null, '?/', null], // 5
    'z': ['aA', 'sS', null, 'zZ', 'xX', null, null], // 4
    'Z': ['aA', 'sS', null, 'zZ', 'xX', null, null], // 4
    'x': ['sS', 'dD', 'zZ', 'xX', 'cC', null, null], // 4
    'X': ['sS', 'dD', 'zZ', 'xX', 'cC', null, null], // 4
    'c': ['dD', 'fF', 'xX', 'cC', 'vV', null, null], // 4
    'C': ['dD', 'fF', 'xX', 'cC', 'vV', null, null], // 4
    'v': ['fF', 'gG', 'cC', 'vV', 'bB', null, null], // 4
    'V': ['fF', 'gG', 'cC', 'vV', 'bB', null, null], // 4
    'b': ['gG', 'hH', 'vV', 'bB', 'nN', null, null], // 4
    'B': ['gG', 'hH', 'vV', 'bB', 'nN', null, null], // 4
    'n': ['hH', 'jJ', 'bB', 'nN', 'mM', null, null], // 4
    'N': ['hH', 'jJ', 'bB', 'nN', 'mM', null, null], // 4
    'm': ['jJ', 'kK', 'nN', 'mM', ',<', null, null], // 4
    'M': ['jJ', 'kK', 'nN', 'mM', ',<', null, null], // 4
    ',': ['kK', 'lL', 'mM', ',<', '.>', null, null], // 4
    '<': ['kK', 'lL', 'mM', ',<', '.>', null, null], // 4
    '.': ['lL', ':;', ',<', '.>', '/?', null, null], // 4
    '>': ['lL', ':;', ',<', '.>', '/?', null, null], // 4
    '/': [':;', '\'"', '.>', '/?', null, null, null], // 3
    '?': [':;', '\'"', '.>', '/?', null, null, null] // 3
}, 4.571428571), // Average number of neighbors.
averageDegree
The average number of neighbors for each key (excluding the key itself).

Keyboard.areAdjacent

This method checks whether two key are adjacent in the keyboard.

keyboard = new Keyboard(adjacencyList, averageDegree);
keyboard.areAdjacent(a, b);
Parameters
a
The first character (a single character).
b
The second character (a single character).
Returns true if and only if the characters a and b are adjacent in the keyboard.

© 2013 - 2018 David Stutz - BSD 3-Clause License - Impressum - Datenschutz