使用JavascriptNodejs进行密码哈希
我的密码保护经验几乎不存在。我在大学里没有上任何密码学课程,我的数学课程也只是简单地介绍了实际的加密算法。不过现在,我想将用户密码存储在数据库中,以创建一种安全的方法登录到我的应用程序。在阅读之后,我收集了一些东西:使用JavascriptNodejs进行密码哈希,javascript,node.js,password-protection,Javascript,Node.js,Password Protection,我的密码保护经验几乎不存在。我在大学里没有上任何密码学课程,我的数学课程也只是简单地介绍了实际的加密算法。不过现在,我想将用户密码存储在数据库中,以创建一种安全的方法登录到我的应用程序。在阅读之后,我收集了一些东西: 密码哈希应该花费大量时间,以防止重复登录尝试并提高安全性 两个或多个密码可能会对同一字符串进行哈希运算 考虑到这一点,我尝试在我的节点服务器上使用。从自述文件中复制示例: var jsSHA = require('jssha'); var sha = new jsSHA("SH
- 密码哈希应该花费大量时间,以防止重复登录尝试并提高安全性
- 两个或多个密码可能会对同一字符串进行哈希运算
var jsSHA = require('jssha');
var sha = new jsSHA("SHA-512", "TEXT");
sha.update("password");
var hash = sha.getHash("HEX");
console.log(hash);
我可以为密码字符串创建哈希,但是这个模块似乎违反了上面的两个要点。在一行中运行脚本5次,每次都会创建相同的字符串,甚至使用构造函数中的可选hashmap添加迭代:
var sha = new jsSHA("SHA-512", "TEXT", '{"numRounds" : 4000000}');
散列在微秒内完成,与我提供给构造函数的轮数无关
我在Javascript/Node中找不到任何专门用于哈希的文档。我是否错误地使用了该模块,还是应该使用其他模块?节点具有用于基于哈希的密钥拉伸的内置模块:
crypto.pbkdf2
我使用以下函数创建哈希:
function createHash(password, salt, iterations, hashLength, callback) {
if(hashLength % 2 !== 0){
throw new Error("hashLength must be even, because it returns a string of two-character hexadecimal digits.");
}
var keyLength = hashLength / 2;
iterations = iterations || 10000;
crypto.pbkdf2(password, salt, iterations, keyLength, function(err, bytes){
var hash = Buffer(bytes, 'binary').toString('hex');
callback(err, hash);
});
}
…其中,password
是要转换为散列的文本,salt
是与密码一起存储的随机字符串,iterations
是重复密钥拉伸算法的次数,keydlength
是十六进制散列字符串的长度,和callback
将哈希返回给调用代码
我使用hash和salt将迭代次数和密钥长度存储在同一数据库行中,而不是存储在配置中,因此我可以选择在用户更新其密码时强化加密
加密模块还包括一个salt创建方法crypto.randomBytes
,我这样使用它:
function createSalt(saltLength, callback){
if(saltLength % 2 !== 0){
throw new Error("saltLength must be even, because it returns a string of two-character hexadecimal digits.");
}
var byteLength = saltLength / 2;
crypto.randomBytes(byteLength, function(err, bytes){
var salt = Buffer(bytes, 'binary').toString('hex');
callback(err, salt);
});
}
免责声明:我也不是密码学家。:) 节点有一个用于基于散列的密钥拉伸的内置模块:
crypto.pbkdf2
我使用以下函数创建哈希:
function createHash(password, salt, iterations, hashLength, callback) {
if(hashLength % 2 !== 0){
throw new Error("hashLength must be even, because it returns a string of two-character hexadecimal digits.");
}
var keyLength = hashLength / 2;
iterations = iterations || 10000;
crypto.pbkdf2(password, salt, iterations, keyLength, function(err, bytes){
var hash = Buffer(bytes, 'binary').toString('hex');
callback(err, hash);
});
}
…其中,password
是要转换为散列的文本,salt
是与密码一起存储的随机字符串,iterations
是重复密钥拉伸算法的次数,keydlength
是十六进制散列字符串的长度,和callback
将哈希返回给调用代码
我使用hash和salt将迭代次数和密钥长度存储在同一数据库行中,而不是存储在配置中,因此我可以选择在用户更新其密码时强化加密
加密模块还包括一个salt创建方法crypto.randomBytes
,我这样使用它:
function createSalt(saltLength, callback){
if(saltLength % 2 !== 0){
throw new Error("saltLength must be even, because it returns a string of two-character hexadecimal digits.");
}
var byteLength = saltLength / 2;
crypto.randomBytes(byteLength, function(err, bytes){
var salt = Buffer(bytes, 'binary').toString('hex');
callback(err, salt);
});
}
免责声明:我也不是密码学家。:) 第三个参数应该是一个对象文本,而不是一个字符串。但是,我强烈建议不要使用SHA-512,因为它作为一个安全散列基本上是不可靠的。虽然HMAC-SHA1也被认为是一个可接受的选择,但最先进的是scrypt。哦,真的。。。我会调查这件事的。你看过这件事吗?jsSHA似乎没有任何盐的助手。bcrypt是scrypt的另一个很好的替代品。第三个参数应该是对象文本,而不是字符串。您将在中获得更好的答案。但是,我强烈建议不要使用SHA-512,因为它作为一个安全散列基本上是不可靠的。虽然HMAC-SHA1也被认为是一个可接受的选择,但最先进的是scrypt。哦,真的。。。我会调查这件事的。你看过这件事吗?jsSHA似乎没有盐的助手。bcrypt是scrypt的另一个很好的替代品。为什么像其他人建议的那样选择PBKDF2而不是scrypt、bcrypt和HMAC-SHA1?因为它是节点的默认实现。吸引我的不是它的优点,而是我假设,作为Node的内置库,它将得到良好的维护和广泛的测试。这是最强大的可用算法吗?可能不会,但其他方案似乎也有其他缺点(比如可以说更安全的scrypt的内存使用率高),而且就我的目的而言,它似乎足够安全。FWIW,在你作为“标准算法”发布的Crackstation文章中,它与bcrypt一起提到。为什么像其他人建议的那样选择PBKDF2而不是Scrypt、bcrypt和HMAC-SHA1?因为它是节点的默认实现。吸引我的不是它的优点,而是我假设,作为Node的内置库,它将得到良好的维护和广泛的测试。这是最强大的可用算法吗?可能不会,但其他方案似乎也有其他缺点(比如可以说更安全的scrypt的内存使用率高),而且就我的目的而言,它似乎足够安全。FWIW,在你作为“标准算法”发布的Crackstation文章中,它与bcrypt一起被提到