Skip to content

Commit 8df4718

Browse files
committed
new password hashing scheme: PBKDF2
1 parent 0fbd50e commit 8df4718

File tree

1 file changed

+54
-15
lines changed

1 file changed

+54
-15
lines changed

app/server/modules/account-manager.js

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const crypto = require('crypto');
33
const moment = require('moment');
44
const MongoClient = require('mongodb').MongoClient;
55

6+
const PASS_VER = 1;
67
var db, accounts;
78
MongoClient.connect(process.env.DB_URL, { useNewUrlParser: true }, function(e, client) {
89
if (e){
@@ -39,13 +40,23 @@ exports.manualLogin = function(user, pass, callback)
3940
if (o == null){
4041
callback('user-not-found');
4142
} else{
42-
validatePassword(pass, o.pass, function(err, res) {
43-
if (res){
44-
callback(null, o);
45-
} else{
46-
callback('invalid-password');
47-
}
48-
});
43+
if (o.pass_ver === undefined || o.pass_ver === 0) {
44+
validatePasswordV0(pass, o.pass, function(err, res) {
45+
if (res){
46+
callback(null, o);
47+
} else{
48+
callback('invalid-password');
49+
}
50+
});
51+
} else if (o.pass_ver === 1) {
52+
validatePasswordV1(pass, o.pass, function(err, res) {
53+
if (res){
54+
callback(null, o);
55+
} else{
56+
callback('invalid-password');
57+
}
58+
});
59+
}
4960
}
5061
});
5162
}
@@ -104,6 +115,7 @@ exports.addNewAccount = function(newData, callback)
104115
} else{
105116
saltAndHash(newData.pass, function(hash){
106117
newData.pass = hash;
118+
newData.pass_ver = PASS_VER;
107119
// append date stamp when record was created //
108120
newData.date = moment().format('MMMM Do YYYY, h:mm:ss a');
109121
accounts.insertOne(newData, callback);
@@ -122,8 +134,11 @@ exports.updateAccount = function(newData, callback)
122134
email : data.email,
123135
country : data.country
124136
}
125-
if (data.pass) o.pass = data.pass;
126-
accounts.findOneAndUpdate({_id:getObjectId(data.id)}, {$set:o}, {returnOriginal : false}, callback);
137+
if (data.pass) {
138+
o.pass = data.pass;
139+
o.pass_ver = PASS_VER;
140+
}
141+
accounts.findOneAndUpdate({_id:getObjectId(data.id)}, {$set:o}, {upsert:true, returnOriginal:false}, callback);
127142
}
128143
if (newData.pass == ''){
129144
findOneAndUpdate(newData);
@@ -137,9 +152,8 @@ exports.updateAccount = function(newData, callback)
137152

138153
exports.updatePassword = function(passKey, newPass, callback)
139154
{
140-
saltAndHash(newPass, function(hash){
141-
newPass = hash;
142-
accounts.findOneAndUpdate({passKey:passKey}, {$set:{pass:newPass}, $unset:{passKey:''}}, {returnOriginal : false}, callback);
155+
saltAndHash(newPass, function(hash) {
156+
accounts.findOneAndUpdate({passKey:passKey}, {$set:{pass:hash, pass_ver:PASS_VER}, $unset:{passKey:''}}, {upsert:true, returnOriginal:false}, callback);
143157
});
144158
}
145159

@@ -187,17 +201,42 @@ var md5 = function(str) {
187201

188202
var saltAndHash = function(pass, callback)
189203
{
190-
var salt = generateSalt();
191-
callback(salt + md5(pass + salt));
204+
const hasher = 'sha256';
205+
const iterations = 10000;
206+
const hashLength = 32;
207+
const saltBytes = 16;
208+
let salt, hash;
209+
crypto.randomBytes(saltBytes, function(err, buf) {
210+
if (err) throw err;
211+
salt = buf.toString('hex');
212+
crypto.pbkdf2(pass, salt, iterations, hashLength, hasher, function(err, derivedKey) {
213+
if (err) throw err;
214+
hash = derivedKey.toString('hex');
215+
callback([salt, hash].join('$'));
216+
});
217+
});
192218
}
193219

194-
var validatePassword = function(plainPass, hashedPass, callback)
220+
var validatePasswordV0 = function(plainPass, hashedPass, callback)
195221
{
196222
var salt = hashedPass.substr(0, 10);
197223
var validHash = salt + md5(plainPass + salt);
198224
callback(null, hashedPass === validHash);
199225
}
200226

227+
var validatePasswordV1 = function(plainPass, hashedPass, callback)
228+
{
229+
const hasher = 'sha256';
230+
const iterations = 10000;
231+
const hashLength = 32;
232+
const salt = hashedPass.split('$')[0];
233+
crypto.pbkdf2(plainPass, salt, iterations, hashLength, hasher, function(err, derivedKey) {
234+
if (err) throw err;
235+
let validHash = [salt, derivedKey.toString('hex')].join('$');
236+
callback(null, hashedPass === validHash);
237+
});
238+
}
239+
201240
var getObjectId = function(id)
202241
{
203242
return new require('mongodb').ObjectID(id);

0 commit comments

Comments
 (0)