Skip to content

Commit

Permalink
Merge pull request thelounge#711 from thelounge/xpaw/bcrypt
Browse files Browse the repository at this point in the history
Change bcrypt rounds from 8 to 11
  • Loading branch information
astorije authored Oct 23, 2016
2 parents 3c3436e + c5e0dee commit 5ff1496
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 19 deletions.
4 changes: 1 addition & 3 deletions src/command-line/add.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use strict";

var ClientManager = new require("../clientManager");
var bcrypt = require("bcrypt-nodejs");
var program = require("commander");
var Helper = require("../helper");

Expand All @@ -26,8 +25,7 @@ program
});

function add(manager, name, password) {
var salt = bcrypt.genSaltSync(8);
var hash = bcrypt.hashSync(password, salt);
var hash = Helper.password.hash(password);
manager.addUser(
name,
hash
Expand Down
3 changes: 1 addition & 2 deletions src/command-line/reset.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"use strict";

var bcrypt = require("bcrypt-nodejs");
var ClientManager = new require("../clientManager");
var fs = require("fs");
var program = require("commander");
Expand All @@ -24,7 +23,7 @@ program
if (err) {
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
fs.writeFileSync(
file,
Expand Down
19 changes: 19 additions & 0 deletions src/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var _ = require("lodash");
var path = require("path");
var os = require("os");
var fs = require("fs");
var bcrypt = require("bcrypt-nodejs");

var Helper = {
config: null,
Expand All @@ -14,6 +15,12 @@ var Helper = {
setHome: setHome,
getVersion: getVersion,
getGitCommit: getGitCommit,

password: {
hash: passwordHash,
compare: passwordCompare,
requiresUpdate: passwordRequiresUpdate,
},
};

module.exports = Helper;
Expand Down Expand Up @@ -83,3 +90,15 @@ function expandHome(shortenedPath) {

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);
}
39 changes: 25 additions & 14 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

var _ = require("lodash");
var pkg = require("../package.json");
var bcrypt = require("bcrypt-nodejs");
var Client = require("./client");
var ClientManager = require("./clientManager");
var express = require("express");
Expand Down Expand Up @@ -192,15 +191,14 @@ function init(socket, client) {
});
return;
}
if (!bcrypt.compareSync(old || "", client.config.password)) {
if (!Helper.password.compare(old || "", client.config.password)) {
socket.emit("change-password", {
error: "The current password field does not match your account password"
});
return;
}

var salt = bcrypt.genSaltSync(8);
var hash = bcrypt.hashSync(p1, salt);
var hash = Helper.password.hash(p1);

client.setPassword(hash, function(success) {
var obj = {};
Expand Down Expand Up @@ -259,17 +257,30 @@ function reverseDnsLookup(socket, client) {
}

function localAuth(client, user, password, callback) {
var result = false;
try {
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 {
callback(result);
if (!client || !password) {
return callback(false);
}

if (!client.config.password) {
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) {
Expand Down
27 changes: 27 additions & 0 deletions test/tests/passwords.js
Original file line number Diff line number Diff line change
@@ -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;
});
});

0 comments on commit 5ff1496

Please sign in to comment.