All Downloads are FREE. Search and download functionalities are using the official Maven repository.

me.gosimple.nbvcxz.resources.ConfigurationBuilder Maven / Gradle / Ivy

Go to download

Nbvcxz takes heavy inspiration from the zxcvbn library built by Dropbox, and in a lot of ways is similar. I built this library to be heavily extensible for every use case, with sane defaults.

There is a newer version: 1.5.1
Show newest version
package me.gosimple.nbvcxz.resources;

import me.gosimple.nbvcxz.Nbvcxz;
import me.gosimple.nbvcxz.matching.DateMatcher;
import me.gosimple.nbvcxz.matching.DictionaryMatcher;
import me.gosimple.nbvcxz.matching.PasswordMatcher;
import me.gosimple.nbvcxz.matching.RepeatMatcher;
import me.gosimple.nbvcxz.matching.SeparatorMatcher;
import me.gosimple.nbvcxz.matching.SequenceMatcher;
import me.gosimple.nbvcxz.matching.SpacialMatcher;
import me.gosimple.nbvcxz.matching.YearMatcher;
import me.gosimple.nbvcxz.matching.match.Match;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Builder class for creating {@link Configuration}.
 *
 * @author Adam Brusselback.
 */
public class ConfigurationBuilder
{
    private static final double YEAR = 365.2422 * 24 * 60 * 60 * 1000; // Average year length
    private static final long START = 1533096000000L; // Date values were chosen: 2018-08-01

    private List passwordMatchers;
    private Map guessTypes;
    private List dictionaries;
    private List adjacencyGraphs;
    private Map leetTable;
    private Pattern yearPattern;
    private Double minimumEntropy;
    private Locale locale;
    private Boolean distanceCalc;
    private Long combinationAlgorithmTimeout;
    private Long crackingHardwareCost;

    /**
     * @return Includes all standard password matchers included with Nbvcxz.
     */
    public static List getDefaultPasswordMatchers()
    {
        List passwordMatchers = new ArrayList<>();
        passwordMatchers.add(new DateMatcher());
        passwordMatchers.add(new YearMatcher());
        passwordMatchers.add(new RepeatMatcher());
        passwordMatchers.add(new SequenceMatcher());
        passwordMatchers.add(new SpacialMatcher());
        passwordMatchers.add(new DictionaryMatcher());
        passwordMatchers.add(new SeparatorMatcher());
        return passwordMatchers;
    }

    /**
     * Returns the Moore's law multiplier we're using for getDefaultGuessTypes().
     *
     * We will only return a multiplier greater than 1 if it has been more than year since we've updated the constants.
     * The date for this function is: 2018-08-01
     *
     * @return the Moore's Law multiplier
     */
    public static BigDecimal getMooresMultiplier()
    {
        double years = (System.currentTimeMillis() - START) / YEAR;

        // Only use the multiplier if we haven't updated the value date in over a year.
        if(years <= 1d)
        {
            years = 0;
        }

        // the multiplier for Moore's law is 2 to the power of (years / 2)
        return BigDecimal.valueOf(Math.pow(2d, years / 2d));
    }

    /**
     * This list was compiled in August 2018 using a baseline of what could be bought for roughly $20k usd for the offline attack values.
     * 

* In the case this library is no longer maintained (or you choose to stay on an old version of it), we will scale the existing values by Moore's law. * * @param crackingHardwareCost the hardware cost (USD) to scale the guesses per second * @return The default list of guess types and associated values of guesses per second. */ public static Map getDefaultGuessTypes(Long crackingHardwareCost) { BigDecimal moores_multiplier = getMooresMultiplier(); BigDecimal cost_multiplier = BigDecimal.valueOf(crackingHardwareCost).divide(BigDecimal.valueOf(20000), 5, RoundingMode.HALF_UP); Map guessTypes = new HashMap<>(); guessTypes.put("OFFLINE_MD5", cost_multiplier.multiply(moores_multiplier.multiply(BigDecimal.valueOf(250375000000L))).longValue()); guessTypes.put("OFFLINE_SHA1", cost_multiplier.multiply(moores_multiplier.multiply(BigDecimal.valueOf(85963750000L))).longValue()); guessTypes.put("OFFLINE_SHA512", cost_multiplier.multiply(moores_multiplier.multiply(BigDecimal.valueOf(10780875000L))).longValue()); guessTypes.put("OFFLINE_BCRYPT_5", cost_multiplier.multiply(moores_multiplier.multiply(BigDecimal.valueOf(130875L))).longValue()); guessTypes.put("OFFLINE_BCRYPT_10", cost_multiplier.multiply(moores_multiplier.multiply(BigDecimal.valueOf(4129L))).longValue()); guessTypes.put("OFFLINE_BCRYPT_12", cost_multiplier.multiply(moores_multiplier.multiply(BigDecimal.valueOf(1033L))).longValue()); guessTypes.put("OFFLINE_BCRYPT_14", cost_multiplier.multiply(moores_multiplier.multiply(BigDecimal.valueOf(259L))).longValue()); guessTypes.put("ONLINE_UNTHROTTLED", 100L); guessTypes.put("ONLINE_THROTTLED", 2L); return guessTypes; } /** * This list was compiled in August 2018 using a baseline of what could be bought for roughly $20k usd for the offline attack values. *

* In the case this library is no longer maintained (or you choose to stay on an old version of it), we will scale the existing values by Moore's law. * * @return The default list of guess types and associated values of guesses per second. */ public static Map getDefaultGuessTypes() { return getDefaultGuessTypes(getDefaultCrackingHardwareCost()); } /** * @return Returns all the dictionaries included with Nbvcxz. * Namely there is a dictionary for common passwords, english male names, english female names, english surnames, and common english words. */ public static List getDefaultDictionaries() { List tmpDictionaries = new ArrayList<>(); tmpDictionaries.add(new Dictionary("passwords", DictionaryUtil.loadRankedDictionary(DictionaryUtil.passwords), false)); tmpDictionaries.add(new Dictionary("male_names", DictionaryUtil.loadRankedDictionary(DictionaryUtil.male_names), false)); tmpDictionaries.add(new Dictionary("female_names", DictionaryUtil.loadRankedDictionary(DictionaryUtil.female_names), false)); tmpDictionaries.add(new Dictionary("surnames", DictionaryUtil.loadRankedDictionary(DictionaryUtil.surnames), false)); tmpDictionaries.add(new Dictionary("english", DictionaryUtil.loadRankedDictionary(DictionaryUtil.english), false)); tmpDictionaries.add(new Dictionary("eff_large", DictionaryUtil.loadUnrankedDictionary(DictionaryUtil.eff_large), false)); return tmpDictionaries; } /** * @return Default keyboard adjacency graphs for standard querty, standard keypad, and mac keypad */ public static List getDefaultAdjacencyGraphs() { List tmpAdjacencyGraphs = new ArrayList<>(); tmpAdjacencyGraphs.add(new AdjacencyGraph("Qwerty", AdjacencyGraphUtil.qwerty)); tmpAdjacencyGraphs.add(new AdjacencyGraph("Standard Keypad", AdjacencyGraphUtil.standardKeypad)); tmpAdjacencyGraphs.add(new AdjacencyGraph("Mac Keypad", AdjacencyGraphUtil.macKeypad)); return tmpAdjacencyGraphs; } /** * @return The default table of common english leet substitutions */ public static Map getDefaultLeetTable() { Map tmpLeetTable = new HashMap<>(); tmpLeetTable.put('4', new Character[]{'a'}); tmpLeetTable.put('@', new Character[]{'a'}); tmpLeetTable.put('8', new Character[]{'b'}); tmpLeetTable.put('(', new Character[]{'c'}); tmpLeetTable.put('{', new Character[]{'c'}); tmpLeetTable.put('[', new Character[]{'c'}); tmpLeetTable.put('<', new Character[]{'c'}); tmpLeetTable.put('3', new Character[]{'e'}); tmpLeetTable.put('9', new Character[]{'g'}); tmpLeetTable.put('6', new Character[]{'g'}); tmpLeetTable.put('&', new Character[]{'g'}); tmpLeetTable.put('#', new Character[]{'h'}); tmpLeetTable.put('!', new Character[]{'i', 'l'}); tmpLeetTable.put('1', new Character[]{'i', 'l'}); tmpLeetTable.put('|', new Character[]{'i', 'l'}); tmpLeetTable.put('0', new Character[]{'o'}); tmpLeetTable.put('$', new Character[]{'s'}); tmpLeetTable.put('5', new Character[]{'s'}); tmpLeetTable.put('+', new Character[]{'t'}); tmpLeetTable.put('7', new Character[]{'t', 'l'}); tmpLeetTable.put('%', new Character[]{'x'}); tmpLeetTable.put('2', new Character[]{'z'}); return tmpLeetTable; } /** * @return The default pattern for years includes years 1900-2029 */ public static Pattern getDefaultYearPattern() { return Pattern.compile("19\\d\\d|200\\d|201\\d|202\\d"); } /** * @return The default value for minimum entropy is 35. */ public static double getDefaultMinimumEntropy() { return 35D; } /** * @return the default is false */ public static Boolean getDefaultDistanceCalc() { return true; } /** * @return The default value for combination algorithm timeout is 500 (ms). */ public static long getDefaultCombinationAlgorithmTimeout() { return 500l; } /** * @return The default value for hardware cost is 20000 usd. */ public static long getDefaultCrackingHardwareCost() { return 20000; } /** * {@link PasswordMatcher} are what look for different patterns within the password and create an associated {@link Match} object. *
* Users of this library can implement their own {@link PasswordMatcher} and {@link Match} classes, here is where you would register them. * * @param passwordMatchers List of matchers * @return Builder */ public ConfigurationBuilder setPasswordMatchers(List passwordMatchers) { this.passwordMatchers = passwordMatchers; return this; } /** * Guess types are used to calculate how long an attack would take using that method using guesses/sec. * * @param guessTypes key is a description of the type of guess, value is how many guesses per second * @return Builder */ public ConfigurationBuilder setGuessTypes(Map guessTypes) { this.guessTypes = guessTypes; return this; } /** * Dictionaries are used by the {@link DictionaryMatcher} to find common words, names, and known passwords within the password. * * @param dictionaries List of dictionaries * @return Builder */ public ConfigurationBuilder setDictionaries(List dictionaries) { this.dictionaries = dictionaries; return this; } /** * {@link AdjacencyGraph}s are used to find spacial patterns within passwords (e.g. asdfghj). * * @param adjacencyGraphs List of adjacencyGraphs * @return Builder */ public ConfigurationBuilder setAdjacencyGraphs(List adjacencyGraphs) { this.adjacencyGraphs = adjacencyGraphs; return this; } /** * The leet table is used to check within a password for common character substitutions (e.g. s to $). * * @param leetTable Map for leetTable * @return Builder */ public ConfigurationBuilder setLeetTable(Map leetTable) { this.leetTable = leetTable; return this; } /** * Year patterns are used to look for years within a password. * * @param yearPattern Pattern for year matching * @return Builder */ public ConfigurationBuilder setYearPattern(Pattern yearPattern) { this.yearPattern = yearPattern; return this; } /** * Used to check if the password is secure enough, and give feedback if not. * * @param minimumEntropy Value for minimumEntropy (should be a positive value) * @return Builder */ public ConfigurationBuilder setMinimumEntropy(Double minimumEntropy) { this.minimumEntropy = minimumEntropy; return this; } /** * Sets the minimum entropy based on time to crack, and a specific guess type. *
* If you are specifying a cracking hardware cost, you should set that prior to calling this. * * @param seconds_to_crack Value in seconds that you want to consider the minimum for a password to be considered good * @param guess_type The guess type to use to figure out what the guesses per second are for this calculation * @return Builder */ public ConfigurationBuilder setMinimumEntropy(BigDecimal seconds_to_crack, String guess_type) { BigDecimal guesses_per_second; if(guessTypes != null) guesses_per_second = BigDecimal.valueOf(guessTypes.get(guess_type)); else guesses_per_second = BigDecimal.valueOf(getDefaultGuessTypes(null != crackingHardwareCost ? crackingHardwareCost : getDefaultCrackingHardwareCost()).get(guess_type)); BigDecimal guesses = guesses_per_second.multiply(seconds_to_crack); minimumEntropy = Nbvcxz.getEntropyFromGuesses(guesses); return this; } /** * Supported locales are en, and fr.
* Default locale is en. * * @param locale Locale for localization * @return Builder */ public ConfigurationBuilder setLocale(Locale locale) { this.locale = locale; return this; } /** * Distance based dictionary calculations which provide support for misspelling * detection, at the expense of performance. This will slow down calculations * by an order of magnitude. * * @param distanceCalc true to enable distance based dictionary calculations * @return Builder */ public ConfigurationBuilder setDistanceCalc(final Boolean distanceCalc) { this.distanceCalc = distanceCalc; return this; } /** * Timeout for the findBestCombination algorithm. If there are too many possible matches at each position of * the password, the algorithm can take too long to get an answer and we must fall back to a simpler algorithm. *

* To disable the findBestMatches calculation and always fall back to the faster, less accurate one, set to 0. * * @param combinationAlgorithmTimeout The time in ms to timeout * @return Builder */ public ConfigurationBuilder setCombinationAlgorithmTimeout(final Long combinationAlgorithmTimeout) { this.combinationAlgorithmTimeout = combinationAlgorithmTimeout; return this; } /** * Sets the cost of cracking hardware to scale the guesses / second for the default guess types. *
* Does not have any affect if you manually specify the guess types. * @param crackingHardwareCost The hardware cost in USD * @return Builder */ public ConfigurationBuilder setCrackingHardwareCost(final Long crackingHardwareCost) { this.crackingHardwareCost = crackingHardwareCost; return this; } /** * Creates the {@link Configuration} object using all values set in this builder, or default values if unset. * * @return Configuration object from builder */ public Configuration createConfiguration() { if (crackingHardwareCost == null) { crackingHardwareCost = getDefaultCrackingHardwareCost(); } if (passwordMatchers == null) { passwordMatchers = getDefaultPasswordMatchers(); } if (guessTypes == null) { guessTypes = getDefaultGuessTypes(crackingHardwareCost); } if (dictionaries == null) { dictionaries = getDefaultDictionaries(); } if (adjacencyGraphs == null) { adjacencyGraphs = getDefaultAdjacencyGraphs(); } if (leetTable == null) { leetTable = getDefaultLeetTable(); } if (yearPattern == null) { yearPattern = getDefaultYearPattern(); } if (minimumEntropy == null) { minimumEntropy = getDefaultMinimumEntropy(); } if (locale == null) { locale = Locale.getDefault(); } if (distanceCalc == null) { distanceCalc = getDefaultDistanceCalc(); } if (combinationAlgorithmTimeout == null) { combinationAlgorithmTimeout = getDefaultCombinationAlgorithmTimeout(); } return new Configuration(passwordMatchers, guessTypes, dictionaries, adjacencyGraphs, leetTable, yearPattern, minimumEntropy, locale, distanceCalc, combinationAlgorithmTimeout); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy