在Node.js中密码哈希

这是我目前的密码散列和保存到数据库的代码:

var config = { hashBytes: 64, saltBytes: 64, iterations: 8000 }; crypto.randomBytes(config.saltBytes, function(err, salt) { crypto.pbkdf2(password, salt, config.iterations, config.hashBytes, function(err, hash) { var combined = new Buffer(hash.length + salt.length + 8); combined.writeUInt32BE(salt.length, 0, true); combined.writeUInt32BE(config.iterations, 4, true); salt.copy(combined, 8); hash.copy(combined, salt.length + 8); callback(combined); }); }); 

代码的目标是将salt与散列一起保存到数据库中的一个字段。 这是可以接受的方式来存储密码/盐在数据库中相同的字段? 我已经很久以前发现了这个algorithm,所以我不确定我是否理解这个。

据我所知,首先我们创build一个缓冲区,有足够的空间存储散列,盐,迭代次数和盐长度(不知道为什么我们在这里加8):

 var combined = new Buffer(hash.length + salt.length + 8); 

然后我们将盐长度字节保存到位置0:

 combined.writeUInt32BE(salt.length, 0, true); 

我们保存迭代位置4(为什么是4?):

 combined.writeUInt32BE(config.iterations, 4, true); 

我们把盐保存到位置8:

 salt.copy(combined, 8); 

我们将散列保存到位置,这是盐的长度加上我们保存的迭代和盐长的大小:

 hash.copy(combined, salt.length + 8); 

这段代码似乎是在做一个现在很危险的假设:“一个整数是4个字节长,因此两个整数是8个字节”。

在今天的64位世界里,这个假设不再是事实。 而且,无论如何,我们不需要这样的复杂度和字节混杂程度!

一个更好的(更简单的)策略… (源代码示例没有显示) …是简单地将所有三个值存储为string,由已知字符分隔。 例如, 12:34:5678被用来存储盐长12,迭代34,散列值5678.存储该值的代码简单地连接三个string并将它们存储在具有足够大小的VARCHAR字段中。 而且,以类似的方式,首先检索和检查值的代码将string“拆分”为其三个组成部分(例如使用正则expression式…),将前两个string转换为整数,然后继续进行求值。

这样做有很多原因,其中最重要的原因是人类对数据库的查询能够清楚地看到这三个部分。 (所以,如果代码中存在错误,他/她可以一眼就看到错误的后果。)