Change bcrypt rounds from 8 to 11

This commit is contained in:
Pavel Djundik 2016-10-21 22:00:43 +03:00
parent f3f933ed44
commit c5e0dee3a3
5 changed files with 73 additions and 19 deletions

View File

@ -1,7 +1,6 @@
"use strict"; "use strict";
var ClientManager = new require("../clientManager"); var ClientManager = new require("../clientManager");
var bcrypt = require("bcrypt-nodejs");
var program = require("commander"); var program = require("commander");
var Helper = require("../helper"); var Helper = require("../helper");
@ -26,8 +25,7 @@ program
}); });
function add(manager, name, password) { function add(manager, name, password) {
var salt = bcrypt.genSaltSync(8); var hash = Helper.password.hash(password);
var hash = bcrypt.hashSync(password, salt);
manager.addUser( manager.addUser(
name, name,
hash hash

View File

@ -1,6 +1,5 @@
"use strict"; "use strict";
var bcrypt = require("bcrypt-nodejs");
var ClientManager = new require("../clientManager"); var ClientManager = new require("../clientManager");
var fs = require("fs"); var fs = require("fs");
var program = require("commander"); var program = require("commander");
@ -24,7 +23,7 @@ program
if (err) { if (err) {
return; return;
} }
user.password = bcrypt.hashSync(password, bcrypt.genSaltSync(8)); user.password = Helper.password.hash(password);
user.token = null; // Will be regenerated when the user is loaded user.token = null; // Will be regenerated when the user is loaded
fs.writeFileSync( fs.writeFileSync(
file, file,

View File

@ -5,6 +5,7 @@ var _ = require("lodash");
var path = require("path"); var path = require("path");
var os = require("os"); var os = require("os");
var fs = require("fs"); var fs = require("fs");
var bcrypt = require("bcrypt-nodejs");
var Helper = { var Helper = {
config: null, config: null,
@ -14,6 +15,12 @@ var Helper = {
setHome: setHome, setHome: setHome,
getVersion: getVersion, getVersion: getVersion,
getGitCommit: getGitCommit, getGitCommit: getGitCommit,
password: {
hash: passwordHash,
compare: passwordCompare,
requiresUpdate: passwordRequiresUpdate,
},
}; };
module.exports = Helper; module.exports = Helper;
@ -83,3 +90,15 @@ function expandHome(shortenedPath) {
return path.resolve(shortenedPath.replace(/^~($|\/|\\)/, home + "$1")); return path.resolve(shortenedPath.replace(/^~($|\/|\\)/, home + "$1"));
} }
function passwordRequiresUpdate(password) {
return bcrypt.getRounds(password) !== 11;
}
function passwordHash(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(11));
}
function passwordCompare(password, expected) {
return bcrypt.compareSync(password, expected);
}

View File

@ -2,7 +2,6 @@
var _ = require("lodash"); var _ = require("lodash");
var pkg = require("../package.json"); var pkg = require("../package.json");
var bcrypt = require("bcrypt-nodejs");
var Client = require("./client"); var Client = require("./client");
var ClientManager = require("./clientManager"); var ClientManager = require("./clientManager");
var express = require("express"); var express = require("express");
@ -192,15 +191,14 @@ function init(socket, client) {
}); });
return; return;
} }
if (!bcrypt.compareSync(old || "", client.config.password)) { if (!Helper.password.compare(old || "", client.config.password)) {
socket.emit("change-password", { socket.emit("change-password", {
error: "The current password field does not match your account password" error: "The current password field does not match your account password"
}); });
return; return;
} }
var salt = bcrypt.genSaltSync(8); var hash = Helper.password.hash(p1);
var hash = bcrypt.hashSync(p1, salt);
client.setPassword(hash, function(success) { client.setPassword(hash, function(success) {
var obj = {}; var obj = {};
@ -259,17 +257,30 @@ function reverseDnsLookup(socket, client) {
} }
function localAuth(client, user, password, callback) { function localAuth(client, user, password, callback) {
var result = false; if (!client || !password) {
try { return callback(false);
result = bcrypt.compareSync(password || "", client.config.password);
} catch (error) {
if (error === "Not a valid BCrypt hash.") {
log.error("User (" + user + ") with no local password set tried to sign in. (Probably a LDAP user)");
} }
result = false;
} finally { if (!client.config.password) {
callback(result); log.error("User", user, "with no local password set tried to sign in. (Probably a LDAP user)");
return callback(false);
} }
var result = Helper.password.compare(password, client.config.password);
if (result && Helper.password.requiresUpdate(client.config.password)) {
var hash = Helper.password.hash(password);
client.setPassword(hash, function(success) {
if (!success) {
log.error("Failed to update password of", client.name, "to match new security requirements");
} else {
log.info("User", client.name, "logged in and their hashed password has been updated to match new security requirements");
}
});
}
return callback(result);
} }
function ldapAuth(client, user, password, callback) { function ldapAuth(client, user, password, callback) {

27
test/tests/passwords.js Normal file
View File

@ -0,0 +1,27 @@
"use strict";
const expect = require("chai").expect;
const Helper = require("../../src/helper");
describe("Client passwords", function() {
const inputPassword = "my$Super@Cool Password";
it("hashed password should match", function() {
// Generated with third party tool to test implementation
let comparedPassword = Helper.password.compare(inputPassword, "$2a$11$zrPPcfZ091WNfs6QrRHtQeUitlgrJcecfZhxOFiQs0FWw7TN3Q1oS");
expect(comparedPassword).to.be.true;
});
it("freshly hashed password should match", function() {
let hashedPassword = Helper.password.hash(inputPassword);
let comparedPassword = Helper.password.compare(inputPassword, hashedPassword);
expect(comparedPassword).to.be.true;
});
it("shout passwords should be marked as old", function() {
expect(Helper.password.requiresUpdate("$2a$08$K4l.hteJcCP9D1G5PANzYuBGvdqhUSUDOLQLU.xeRxTbvtp01KINm")).to.be.true;
expect(Helper.password.requiresUpdate("$2a$11$zrPPcfZ091WNfs6QrRHtQeUitlgrJcecfZhxOFiQs0FWw7TN3Q1oS")).to.be.false;
});
});