我试图为节点的内置加密模块(特别是 scrypt)找到比较或验证功能,因为我使用的大多数密码散列模块都有这样的功能。然后,我发现了为什么这是一项不可能完成的任务:使用这些算法生成的所有哈希使用相同的参数生成相同的字符串(技术上是缓冲区)。crypto
许多的散列函数就是这种情况,包括它的pbkdf2
实现。
为什么这样安全?密码/消息散列函数的全部(现代)点不是您不能使用相同的输入再次生成相同的密码/消息吗?这就是各种 bcrypt 模块的工作方式,以及 scrypt 的原始版本,内置版本,即我要询问的版本,就是从中派生出来的。
例如:
let scryptHash1;
let scryptHash2;
let scryptHash3;
let pbkdfHash1;
let pbkdfHash2;
let pbkdfHash3;
const key1 = 'my secret key';
const key2 = 'my other secret key';
const salt = 'my salt';
crypto.scrypt(key1, salt, 16, hash => scryptHash1 = hash);
crypto.scrypt(key1, salt, 16, hash => scryptHash2 = hash);
crypto.scrypt(key2, salt, 16, hash => scryptHash3 = hash);
scryptHash1.toString() === scryptHash2.toString(); // true
scryptHash1.toString() === scryptHash3.toString(); // false
crypto.pbkdf2(key1, salt, 16, 16, 'sha256', hash => pbkdfHash1 = hash);
crypto.pbkdf2(key1, salt, 16, 16, 'sha256', hash => pbkdfHash2 = hash);
crypto.pbkdf2(key2, salt, 16, 16, 'sha256', hash => pbkdfHash3 = hash);
pbkdfHash1.toString() === pbkdfHash2.toString(); // true
pbkdfHash1.toString() === pbkdfHash3.toString(); // false
我最初是在 上问这个问题的Cryptography
,因为我更关心安全性而不是其他任何事情,因为我想从 移动bcrypt
到scrypt
。然而,正如多人指出的那样,正如我所担心的那样,问题更多的是关于 API 设计。话虽如此,任何公认的答案都应该包括为什么这种方法是安全的,或者足够安全以进行切换(承认“足够安全”永远不够安全)。我的专业是安全,但我现在是一名网络开发人员,安全一直在变化,尽管核心概念基本保持不变。