<commit_before>var crypto = require('crypto');

// Bytesize
var len = 128;

// Current prefered algorithm
var currentAlgorithm = 'pbkdf2';

// Rounds of encryption
var currentIterations = 12000;

// root of hashing algorithm type hierarchy
var hashAlgorithm = {
    name : '',
    adaptive : false,
    doHash : function(hashArgs) {
        throw "Algorithm not defined!";
    }
};

// non-iterative hash functions supported by crypto
var simpleHashAlgorithm = Object.create(hashAlgorithm, {
    doHash : {
        value : function(hashArgs, fn) {
            var hash;
            hash = crypto.createHash(this.name).update(
                    hashArgs.plaintext + hashArgs.salt).digest('base64');
            fn(null, this.name + "$" + hash + '$' + hashArgs.salt);
        }
    }
});

// This is an example of how to secure an obsolete hash with a wrapper adaptive
// algorithm. If both wrapper and wrapped algorithms are adaptive of course you
// will need to have a composite iteration field as well
var wrappedAlgorithm = Object.create(hashAlgorithm, {
    // assume wrapped algorithm is simple hash, outer is adaptive; if not you'd
    // have to split the iterations field as well
    wrappedAlgorithm : {
        value : ''
    },
    wrapperAlgorithm : {
        value : ''
    },
    adaptive : {
        value : true
    },
    doHash : {
        value : function(hashArgs, fn) {
            // 1st salt is for wrapped algorithm, 2nd for wrapper
            var salts = hashArgs.salt.split('|');
            var wrapperAlgorithm = this.wrapperAlgorithm;
            var name = this.name;
            // create wrapped hash with plaintext password
            this.wrappedAlgorithm.doHash({
                plaintext : hashArgs.plaintext,
                salt : salts[0]
            }, function(err, wrappedHash) {
                // now treat the wrapped hash as plaintext to create the output
                // hash
                wrapperAlgorithm.doHash({
                    plaintext : wrappedHash,
                    salt : salts[1],
                    byteLen : hashArgs.byteLen,
                    iterations : hashArgs.iterations
                }, function(err, wrapperHash) {
                    if (err)
                        return fn(err);
                    var fields = exports.splitCredentialFields(wrapperHash);
                    // callback with final output
                    fn(null, name + '$' + hashArgs.iterations + '$'
                            + fields.hash + '$' + hashArgs.salt);
                });
            });
        }
    }
});

// lookup table for the algorithms we support
var algorithms = {
    sha1 : Object.create(simpleHashAlgorithm, {
        name : {
            value : 'sha1'
        }
    }),
    sha256 : Object.create(simpleHashAlgorithm, {
        name : {
            value : 'sha256'
        }
    }),
    pbkdf2 : Object.create(hashAlgorithm, {
        name : {
            value : 'pbkdf2'
        },
        adaptive : {
            value : false
        },
        doHash : {
            // use crypto.pbkdf2 to generate hash
            value : function(hashArgs, fn) {
                crypto.pbkdf2(hashArgs.plaintext, hashArgs.salt,
                        hashArgs.iterations, hashArgs.byteLen, function(err, hash) {
                            if (err)
                                return fn(err);
                            fn(null, 'pbkdf2$' + hashArgs.iterations + '$'
                                    + hash.toString('base64') + '$'
                                    + hashArgs.salt);
                        });
            }
        }
    })
};

// helper function to make secured credentials more readable
exports.splitCredentialFields = function(hash) {
    // 3 fields for simple hash, 4 for adaptive
    var fields = hash.split('$');
    if (fields.length < 3 || fields.length > 4)
        throw new Error('Hash should have 3 or 4 fields');
    if (fields.length === 3) {
        return {
            algorithm : fields[0],
            hash : fields[1],<commit_msg>some cleanup<commit_after>var crypto = require('crypto');

// Bytesize
var len = 128;

// Current prefered algorithm
var currentAlgorithm = 'pbkdf2';

// Rounds of encryption
var currentIterations = 12000;

// root of hashing algorithm type hierarchy
var hashAlgorithm = {
    name : '',
    adaptive : false,
    doHash : function(hashArgs) {
        throw "Algorithm not defined!";
    }
};

// non-iterative hash functions supported by crypto
var simpleHashAlgorithm = Object.create(hashAlgorithm, {
    doHash : {
        value : function(hashArgs, fn) {
            var hash;
            hash = crypto.createHash(this.name).update(
                    hashArgs.plaintext + hashArgs.salt).digest('base64');
            fn(null, this.name + "$" + hash + '$' + hashArgs.salt);
        }
    }
});

// This is an example of how to secure an obsolete hash with a wrapper adaptive
// algorithm. If both wrapper and wrapped algorithms are adaptive of course you
// will need to have a composite iteration field as well
var wrappedAlgorithm = Object.create(hashAlgorithm, {
    // assume wrapped algorithm is simple hash, outer is adaptive; if not you'd
    // have to split the iterations field as well
    wrappedAlgorithm : {
        value : ''
    },
    wrapperAlgorithm : {
        value : ''
    },
    adaptive : {
        value : true
    },
    doHash : {
        value : function(hashArgs, fn) {
            // 1st salt is for wrapped algorithm, 2nd for wrapper
            var salts = hashArgs.salt.split('|');
            var wrapperAlgorithm = this.wrapperAlgorithm;
            var name = this.name;
            
            var wrapHash = function(err, hash) {
                if (err)
                    return fn(err);
                fn(null, 'pbkdf2$' + hashArgs.iterations + '$'
                        + hash.toString('base64') + '$'
                        + hashArgs.salt);
            }

            
            // create wrapped hash with plaintext password
            this.wrappedAlgorithm.doHash({
                plaintext : hashArgs.plaintext,
                salt : salts[0]
            }, wrapHash);
        }
    }
});

// lookup table for the algorithms we support
var algorithms = {
    sha1 : Object.create(simpleHashAlgorithm, {
        name : {
            value : 'sha1'
        }
    }),
    sha256 : Object.create(simpleHashAlgorithm, {
        name : {
            value : 'sha256'
        }
    }),
    pbkdf2 : Object.create(hashAlgorithm, {
        name : {
            value : 'pbkdf2'
        },
        adaptive : {
            value : false
        },
        doHash : {
            // use crypto.pbkdf2 to generate hash
            value : function(hashArgs, fn) {
                
                var onHash = function(err, hash) {
                    if (err)
                        return fn(err);
                    fn(null, 'pbkdf2$' + hashArgs.iterations + '$'
                            + hash.toString('base64') + '$'
                            + hashArgs.salt);
                };

                crypto.pbkdf2(hashArgs.plaintext, hashArgs.salt,
                        hashArgs.iterations, hashArgs.byteLen, onHash);
            }
        }
        
    })
};

// helper function to make secured credentials more readable
exports.splitCredentialFields = function(hash) {
    // 3 fields for simple hash, 4 for adaptive
    var fields = hash.split('$');
    if (fields.length < 3 || fields.length > 4)
        throw new Error('Hash should have 3 or 4 fields');
    if (fields.length === 3) {
        return {
            algorithm : fields[0],
            hash : fields[1],
{'fraction_non_alphanumeric': 0.10197197716658017, 'fraction_numerical': 0.010378827192527244, 'mean_word_length': 1.5619807244931871, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4587360', 'n_tokens_mistral': 2084, 'n_tokens_neox': 1965, 'n_words': 564}