node.js - 为什么在给定相同输入的情况下节点 scrypt 哈希值相同?
问题描述
我试图为节点的内置加密模块(特别是 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 设计。话虽如此,任何公认的答案都应该包括为什么这种方法是安全的,或者足够安全以进行切换(承认“足够安全”永远不够安全)。我的专业是安全,但我现在是一名网络开发人员,安全一直在变化,尽管核心概念基本保持不变。
解决方案
您似乎对密码哈希有一些基本的误解。首先,就像任何散列函数一样,密码散列函数也是数学意义上的函数。即,它只是一个映射,将其范围内的固定值分配给其输入域的每个元素。
密码散列与常规散列的区别在于两点:首先,它们被设计为速度慢和/或在评估时使用大量内存。(这与我们在这里的讨论无关。)其次,他们需要第二个输入,盐。
对于密码散列函数 H,您希望对于任何固定密码 m 和任何两个盐 s≠ s' 它不仅保持 H(m,s)≠ H(m,s'),而且还给定散列值和盐您应该无法检测到它们是相同 m 的哈希值。
您似乎对 API 设计的不同选择感到困惑。具体来说,谁可以选择盐。每次对新密码 m 进行散列(例如输入数据库)时,应选择一个新的均匀随机盐 s,然后计算散列值 h:=H(m,s) 并存储 h 和 s在数据库中。每当有人声称是同一用户提交密码 m' 以验证他们自己时,就会检索 (h,s) 并检查是否 h=H(m',s)。
现在的问题是谁选择盐。您熟悉的 API 似乎不信任用户这样做。因此,当您调用哈希密码 m 时,库将选择一个盐 s,计算 h 并输出 h'=(h,s) 作为“哈希值”。要检查密码 m' 是否正确,然后提交 h',m' 并且库将提取盐,重新计算哈希并进行比较。
您现在正在查看的库希望用户选择盐。即,每次您在密码数据库中创建一个新条目时,您必须选择一个新的盐,计算 h=H(m,s) 并存储两者 (h,s)。由于在这种情况下库不会尝试向您“隐藏”任何内容,因此您需要注意比较。
推荐阅读
- flutter - 导航不适用于 Firebase 动态链接 - 使用颤振
- testng - Qmetry:测试用例执行的顺序没有按照 testNG 文件中的给定顺序发生
- python - 具有来自 Pandas 中 2 个不同列的颜色的散点矩阵(没有 seaborn)
- macos - Openflow 项目在 OMNET++ 5.6.2 中的 Mac OS 上构建失败
- microsoft-graph-api - Office 365:如何查找项目 ID 的最大长度
- javascript - 我想将大写单词转换为小写,将小写转换为大写,但我遇到了问题
- laravel - 没有获取数据透视表的 laravel id
- oracle - 用于学习的简单存储过程
- javascript - react-hook-form 在自定义选择框输入中不起作用
- java - Android Java:使用颜色动画突出显示新的 ListView-Items