Initial commit

This commit is contained in:
2018-03-02 03:00:51 -05:00
commit 834c66b216
21 changed files with 3365 additions and 0 deletions

92
modules/authentication.js Normal file
View File

@@ -0,0 +1,92 @@
var crypto = require('crypto');
// larger numbers mean better security, less
var config = {
digest: 'sha512',
// size of the generated hash
hashBytes: 32,
// larger salt means hashed passwords are more resistant to rainbow table, but
// you get diminishing returns pretty fast
saltBytes: 24,
// more iterations means an attacker has to take longer to brute force an
// individual password, so larger is better. however, larger also means longer
// to hash the password. tune so that hashing the password takes about a
// second
iterations: 233335
};
/**
* Hash a password using Node's asynchronous pbkdf2 (key derivation) function.
*
* Returns a self-contained buffer which can be arbitrarily encoded for storage
* that contains all the data needed to verify a password.
*
* @param {!String} password
* @param {!function(?Error, ?Buffer=)} callback
*/
function hashPassword (password, callback) {
// generate a salt for pbkdf2
crypto.randomBytes(config.saltBytes, function (err, salt) {
if (err) {
return callback(err);
}
crypto.pbkdf2(password, salt, config.iterations, config.hashBytes, config.digest,
function (err, hash) {
if (err) {
return callback(err);
}
var combined = Buffer.alloc((hash.length + salt.length + 8));
// include the size of the salt so that we can, during verification,
// figure out how much of the hash is salt
combined.writeUInt32BE(salt.length, 0, true);
// similarly, include the iteration count
combined.writeUInt32BE(config.iterations, 4, true);
salt.copy(combined, 8);
hash.copy(combined, salt.length + 8);
callback(null, combined);
}
);
});
}
/**
* Verify a password using Node's asynchronous pbkdf2 (key derivation) function.
*
* Accepts a hash and salt generated by hashPassword, and returns whether the
* hash matched the password (as a boolean).
*
* @param {!String} password
* @param {!Buffer} combined Buffer containing hash and salt as generated by
* hashPassword.
* @param {!function(?Error, !boolean)}
*/
function verifyPassword (password, combined, callback) {
// extract the salt and hash from the combined buffer
var saltBytes = combined.readUInt32BE(0);
var hashBytes = combined.length - saltBytes - 8;
var iterations = combined.readUInt32BE(4);
var salt = combined.slice(8, saltBytes + 8);
var hash = combined.toString('binary', saltBytes + 8);
// verify the salt and hash against the password
crypto.pbkdf2(password, salt, iterations, hashBytes, config.digest, function(err, verify) {
if (err && typeof callback === 'function') {
return callback(err, false);
} else if (err) {
return false;
}
if (typeof callback === 'function') {
callback(null, verify.toString('binary') === hash);
} else {
return true;
}
});
}
exports.hashPassword = hashPassword;
exports.verifyPassword = verifyPassword;