如何将散列值与 JavaScript 库 node-password-hash 进行比较?
How to compare hashed values with the JavaScript library node-password-hash?
短版:
我想知道是否使用随机盐对相同的值进行哈希处理,我如何验证我现在得到的值是否 "equal" 与我数据库中已存储为用户的值密码。还有这里的equal是什么意思?
长版:
直到现在,当必须对密码进行哈希处理时,我认为哈希函数是这样工作的:
- 选择一种算法,假设它是 SHA1
- 使用该算法将输入更改得如此之多,以至于您无法猜测输入是什么或它看起来如何
- 将散列值与用户一起放入数据库,当需要登录时再次使用散列函数输入并将其与数据库中已有的值相匹配
- 建议使用随机盐,将它们与用户一起存储,在登录阶段,您取出该盐对给定密码进行哈希处理,并将其与数据库中已有的哈希值相匹配。
因此,我在 Node.js
中有以下代码
var passwordHash = require('password-hash');
var foo = passwordHash.generate('password123');
var bar = passwordHash.generate('password123');
console.log(foo); //sha1$d1d19f32$d5cb099afdd9bb130c969e0394c9bf5e57d6a2aa
console.log(bar); //sha1$df372235dfd5485e8a223e21738621bf4a7cdfca949721
console.log(passwordHash.verify('password123', foo)); //true
console.log(passwordHash.verify('password123', bar)); //true
我知道 passwordHash.generate()
使用随机盐,它是 $...$
之间的部分。我在文档中找不到盐存储在某个地方,如果是,为什么两个散列值不相同?
我认为 passwordHash.verify()
散列 "password123"
并检查它是否与 foo
和 bar
相同。然而这不可能发生,因为我总是正确的,但是 foo
和 bar
是不同的。
那么 passwordHash.verify()
是如何工作的?
盐包含在 generate 返回的字符串中,由 $ 字符分隔:
sha1$d1d19f32$1$d5cb099afdd9bb130c969e0394c9bf5e57d6a2aa
alg $ salt $ hash
查看密码哈希的源代码,您所要做的就是对包含 $ 和盐的结果字符串调用验证方法。
这是他们的验证函数:
module.exports.verify = function(password, hashedPassword) {
if (!password || !hashedPassword) return false;
hashedPassword = makeBackwardCompatible(hashedPassword);
var parts = hashedPassword.split('$');
if (parts.length != 4) return false;
try {
return generateHash(parts[0], parts[1], password, parts[2]) == hashedPassword;
} catch (e) {}
return false;
};
如您所见,它在 $ 上拆分输入字符串,然后生成带有盐的哈希值并与密码进行比较。这意味着您应该使用原始生成方法返回的整个字符串调用验证方法,就像您在问题中所做的那样。
短版:
我想知道是否使用随机盐对相同的值进行哈希处理,我如何验证我现在得到的值是否 "equal" 与我数据库中已存储为用户的值密码。还有这里的equal是什么意思?
长版:
直到现在,当必须对密码进行哈希处理时,我认为哈希函数是这样工作的:
- 选择一种算法,假设它是 SHA1
- 使用该算法将输入更改得如此之多,以至于您无法猜测输入是什么或它看起来如何
- 将散列值与用户一起放入数据库,当需要登录时再次使用散列函数输入并将其与数据库中已有的值相匹配
- 建议使用随机盐,将它们与用户一起存储,在登录阶段,您取出该盐对给定密码进行哈希处理,并将其与数据库中已有的哈希值相匹配。
因此,我在 Node.js
中有以下代码var passwordHash = require('password-hash');
var foo = passwordHash.generate('password123');
var bar = passwordHash.generate('password123');
console.log(foo); //sha1$d1d19f32$d5cb099afdd9bb130c969e0394c9bf5e57d6a2aa
console.log(bar); //sha1$df372235dfd5485e8a223e21738621bf4a7cdfca949721
console.log(passwordHash.verify('password123', foo)); //true
console.log(passwordHash.verify('password123', bar)); //true
我知道 passwordHash.generate()
使用随机盐,它是 $...$
之间的部分。我在文档中找不到盐存储在某个地方,如果是,为什么两个散列值不相同?
我认为 passwordHash.verify()
散列 "password123"
并检查它是否与 foo
和 bar
相同。然而这不可能发生,因为我总是正确的,但是 foo
和 bar
是不同的。
那么 passwordHash.verify()
是如何工作的?
盐包含在 generate 返回的字符串中,由 $ 字符分隔:
sha1$d1d19f32$1$d5cb099afdd9bb130c969e0394c9bf5e57d6a2aa
alg $ salt $ hash
查看密码哈希的源代码,您所要做的就是对包含 $ 和盐的结果字符串调用验证方法。
这是他们的验证函数:
module.exports.verify = function(password, hashedPassword) {
if (!password || !hashedPassword) return false;
hashedPassword = makeBackwardCompatible(hashedPassword);
var parts = hashedPassword.split('$');
if (parts.length != 4) return false;
try {
return generateHash(parts[0], parts[1], password, parts[2]) == hashedPassword;
} catch (e) {}
return false;
};
如您所见,它在 $ 上拆分输入字符串,然后生成带有盐的哈希值并与密码进行比较。这意味着您应该使用原始生成方法返回的整个字符串调用验证方法,就像您在问题中所做的那样。