<commit_before>(function(upb) {

    upb.makeHashHumanReadable = function(array) {
        var availableChars = [
            '!','$','+','-','=','_','.',':',';',',','?','#','%','&','(',')','[',']',
            '0','1','2','3','4','5','6','7','8','9',
            'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
            'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
        ];

        var password = '';
        for(var i = 0; i < array.length; i+=2) {
            var v = array[i] + array[i+1];
            password += availableChars[v % availableChars.length];
        }
        return password;
    };

    upb.getSaltOnLocation = function(input) {
        if (!input) {
            return '';
        }
        if (input.indexOf('//') === -1) {
            return input;
        }

        var parts = input.split('/'); // Extract protocol and host from input value
        return (parts[0]|| '') + '//' + ( parts[2]  || '') ;
    };

    upb.generate = function(algorithm, locationSalt, difficulty, masterPassword, userSalt, callback, nolog, params) {
        if (!masterPassword) {
            throw new Error('master password should not be empty');
        }

        var t = +new Date();
        if(algorithm === 'scrypt') {
            var userSalt = userSalt && userSalt != 0 ? "-keyidx:" + userSalt : ""; // keyidx is here for legacy reason, to avoid changing password
            var salt = locationSalt + userSalt;
            var difficulty = difficulty || 8192;
            if (!upb.isPowerOfTwo(difficulty)) {
                throw new Error('difficulty should be a power of two, got ' + difficulty);
            }
            var logN = Math.log2(difficulty);

            scrypt(masterPassword, salt, logN, 8, 32, function(hashedPassword) {
                var outputPassword = upb.makeHashHumanReadable(hashedPassword);

                if (!nolog && console && console.log) {
                    var timeMessage = ' in ' + ((+new Date()) - t) / 1000 + ' seconds';
                    var difficultyMessage = (difficulty > 1) ? ' (in ' + difficulty + ' difficulty)' : '';
                    console.log('UniquePasswordBuilder - Generated password (scrypt): ' + outputPassword + ' for salt (domain + key index): ' + salt + timeMessage + difficultyMessage);
                }
                callback(outputPassword);
            });
        } else {
            var difficulty = difficulty || 10;
            //Good long salt generated with http://passwordsgenerator.net/
            var salt = locationSalt + '|' + (userSalt || '0') + '|' + '5yB8xbz*BsiMxI8yaz&_9!1u3=ZS$fEH16URassf2OzcZEuvIgt4So0sB2aMAp!SDc#HoHuPZ1_??|X-yw2&J+d+c?AKo-k!ifhH6Qp%25alTVdzE*UAFo9#WduBLCXXZhEjg9V&j#DJQba^e#^NNP';
            // https://github.com/antelle/argon2-browser
            // Info: In Argon2, all the algorithm parameters are used as salt to increase entropy
            // so on change will generate different results...
            var slatLimit = 328;
            if(salt.length > slatLimit) {
                callback("Salt is too long :( Should be " + (salt.length - slatLimit) + " chars shorter...");
                return;
            }
            var applyArgon2 = function(password, type, argonCallback) {
                return argon2.hash({
                    pass: password,
                    salt: salt, //fail when salt length is >328
                    // optional
                    time: difficulty, // the number of iterations
                    // mem: 1024, // used memory, in KiB
                    hashLen: 32, // desired hash length
                    // parallelism: 1, // desired parallelism (will be computed in parallel only for PNaCl)
                    type: type, // argon2.ArgonType.Argon2i or argon2.ArgonType.Argon2d
                    distPath: params === undefined ? '.' : params.argon2AsmPath // argon2-asm.min.js script location, without trailing slash
                }).then(argonCallback);
            };

            applyArgon2(masterPassword, argon2.ArgonType.Argon2i, function (hashArgon2i) {
                //  console.log("======>hash", Argon2i.hashHex, Argon2i.encoded);
                applyArgon2(hashArgon2i.hashHex, argon2.ArgonType.Argon2d, function (hashArgon2d) {
                    var outputPassword = upb.makeHashHumanReadable(hashArgon2d.hash);

                    if (!nolog && console && console.log) {
                        var timeMessage = ' in ' + ((+new Date()) - t) / 1000 + ' seconds';
                        var difficultyMessage = (difficulty > 1) ? ' (in ' + difficulty + ' iterations Argon2i then ' + difficulty + ' iterations Argon2d)' : '';
                        console.log('Argon2 results', hashArgon2d.hash, hashArgon2d.hashHex, hashArgon2d.encoded, outputPassword)
                        console.log('UniquePasswordBuilder - Generated password (argon2): ' + outputPassword + ' for salt (domain + user salt): ' + salt + timeMessage + difficultyMessage);
                    }
                    callback(outputPassword);
            });
        })
        .catch(function (err) { console.error(err.message, err.code)});
        }
    };

    upb.isPowerOfTwo = function(x) {
        return ((x != 0) && !(x & (x - 1)));
    };


})(window.UniquePasswordBuilder = window.UniquePasswordBuilder || {});
<commit_msg>refactor: get hash length required from password length wished<commit_after>(function(upb) {

    var passwordLength = 16;
    upb.makeHashHumanReadable = function(array) {
        var availableChars = [
            '!','$','+','-','=','_','.',':',';',',','?','#','%','&','(',')','[',']',
            '0','1','2','3','4','5','6','7','8','9',
            'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
            'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
        ];

        var password = '';
        for(var i = 0; i < array.length; i+=2) {
            var v = array[i] + array[i+1];
            password += availableChars[v % availableChars.length];
        }
        return password;
    };

    upb.getSaltOnLocation = function(input) {
        if (!input) {
            return '';
        }
        if (input.indexOf('//') === -1) {
            return input;
        }

        var parts = input.split('/'); // Extract protocol and host from input value
        return (parts[0]|| '') + '//' + ( parts[2]  || '') ;
    };

    upb.generate = function(algorithm, locationSalt, difficulty, masterPassword, userSalt, callback, nolog, params) {
        if (!masterPassword) {
            throw new Error('master password should not be empty');
        }
        var hashLength = 2 * passwordLength;
        var t = +new Date();
        if(algorithm === 'scrypt') {
            var userSalt = userSalt && userSalt != 0 ? "-keyidx:" + userSalt : ""; // keyidx is here for legacy reason, to avoid changing password
            var salt = locationSalt + userSalt;
            var difficulty = difficulty || 8192;
            if (!upb.isPowerOfTwo(difficulty)) {
                throw new Error('difficulty should be a power of two, got ' + difficulty);
            }
            var logN = Math.log2(difficulty);

            scrypt(masterPassword, salt, logN, 8, hashLength, function(hashedPassword) {
                var outputPassword = upb.makeHashHumanReadable(hashedPassword);

                if (!nolog && console && console.log) {
                    var timeMessage = ' in ' + ((+new Date()) - t) / 1000 + ' seconds';
                    var difficultyMessage = (difficulty > 1) ? ' (in ' + difficulty + ' difficulty)' : '';
                    console.log('UniquePasswordBuilder - Generated password (scrypt): ' + outputPassword + ' for salt (domain + key index): ' + salt + timeMessage + difficultyMessage);
                }
                callback(outputPassword);
            });
        } else {
            var difficulty = difficulty || 10;
            //Good long salt generated with http://passwordsgenerator.net/
            var salt = locationSalt + '|' + (userSalt || '0') + '|' + '5yB8xbz*BsiMxI8yaz&_9!1u3=ZS$fEH16URassf2OzcZEuvIgt4So0sB2aMAp!SDc#HoHuPZ1_??|X-yw2&J+d+c?AKo-k!ifhH6Qp%25alTVdzE*UAFo9#WduBLCXXZhEjg9V&j#DJQba^e#^NNP';
            // https://github.com/antelle/argon2-browser
            // Info: In Argon2, all the algorithm parameters are used as salt to increase entropy
            // so on change will generate different results...
            var slatLimit = 328;
            if(salt.length > slatLimit) {
                callback("Salt is too long :( Should be " + (salt.length - slatLimit) + " chars shorter...");
                return;
            }
            var applyArgon2 = function(password, type, argonCallback) {
                return argon2.hash({
                    pass: password,
                    salt: salt, //fail when salt length is >328
                    // optional
                    time: difficulty, // the number of iterations
                    // mem: 1024, // used memory, in KiB
                    hashLen: hashLength, // desired hash length
                    // parallelism: 1, // desired parallelism (will be computed in parallel only for PNaCl)
                    type: type, // argon2.ArgonType.Argon2i or argon2.ArgonType.Argon2d
                    distPath: params === undefined ? '.' : params.argon2AsmPath // argon2-asm.min.js script location, without trailing slash
                }).then(argonCallback);
            };

            applyArgon2(masterPassword, argon2.ArgonType.Argon2i, function (hashArgon2i) {
                //  console.log("======>hash", Argon2i.hashHex, Argon2i.encoded);
                applyArgon2(hashArgon2i.hashHex, argon2.ArgonType.Argon2d, function (hashArgon2d) {
                    var outputPassword = upb.makeHashHumanReadable(hashArgon2d.hash);

                    if (!nolog && console && console.log) {
                        var timeMessage = ' in ' + ((+new Date()) - t) / 1000 + ' seconds';
                        var difficultyMessage = (difficulty > 1) ? ' (in ' + difficulty + ' iterations Argon2i then ' + difficulty + ' iterations Argon2d)' : '';
                        console.log('Argon2 results', hashArgon2d.hash, hashArgon2d.hashHex, hashArgon2d.encoded, outputPassword)
                        console.log('UniquePasswordBuilder - Generated password (argon2): ' + outputPassword + ' for salt (domain + user salt): ' + salt + timeMessage + difficultyMessage);
                    }
                    callback(outputPassword);
            });
        })
        .catch(function (err) { console.error(err.message, err.code)});
        }
    };

    upb.isPowerOfTwo = function(x) {
        return ((x != 0) && !(x & (x - 1)));
    };


})(window.UniquePasswordBuilder = window.UniquePasswordBuilder || {});

{'fraction_non_alphanumeric': 0.16261343012704174, 'fraction_numerical': 0.01823956442831216, 'mean_word_length': 1.9997278170930866, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1043387', 'n_tokens_mistral': 3408, 'n_tokens_neox': 3167, 'n_words': 707}