在相同的输入下,为什么节点scrypt哈希值相同? [英] Why Are node scrypt Hashes the Same Given the Same Inputs?

查看:121
本文介绍了在相同的输入下,为什么节点scrypt哈希值相同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图为节点的内置加密模块(尤其是scrypt)找到比较或验证功能,因为我使用的大多数密码哈希模块都具有这种功能。然后,我发现了为什么这是不可能完成的任务:用这些算法使用相同的参数生成的所有散列都生成相同的字符串(技术上是缓冲区)。许多 crypto 的散列函数就是这种情况,包括其 pbkdf2 实现。

I was trying to find a compare or verify function for node's built-in crypto module, specifically for scrypt, as most password-hashing modules I have used have such a function. Then, I discovered why this was an impossible task: All hashes generated with these algorithms using the same parameters generate the same string (technically buffer). This is the case for many of crypto's hashing functions, including its pbkdf2 implementation.

为什么这样安全?难道不是密码/消息哈希函数的整个(现代)要点,即您无法使用相同的输入再次生成相同的密码/消息吗?这就是各种bcrypt模块以及原始版本scrypt的工作方式,其中衍生出了我要问的内置版本。

Why is this safe? Isn't the whole (modern) point of a password/message hashing function that you can't generate the same password/message again using the same input? This is how the various bcrypt modules work, as well as the original version of scrypt, from which the built-in version, the one I'm asking about, got derived.

例如:

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设计。话虽这么说,任何可接受的答案都应包括为什么此方法是安全的,或足以安全切换的方法(授予足够安全永远不会足够安全)。我将安全作为我的专业,但是现在我是一名Web开发人员,并且安全一直在变化,尽管核心概念保持不变。

I originally asked this question on Cryptography, as I'm more concerned about the safety than anything else, as I want to move from bcrypt to scrypt. However, as multiple people pointed out, and as I feared, the question is more about API design. That being said, any accepted answer should include why this method is safe, or safe enough to switch over (granting that "safe enough" is never safe enough). I took security as my major, but I'm now a web dev, and security changes all the time, though the core concepts stay mostly the same.

推荐答案

您似乎对密码哈希有一些基本的误解。首先,就像任何哈希函数一样,密码哈希函数在数学意义上也是 function 。即

You seem to have some fundamental misunderstanding about password hashing. First and foremost, just as any hash function a password hashing function is also a function in the mathematical sense. I.e. it is simply a mapping that assigns a fixed value from its range to every element of its input domain.

将密码哈希值与常规哈希值区分开的是两件事:第一,在评估时,它们被设计为速度慢和/或使用大量内存。 (这与我们在这里的讨论无关。)其次,他们输入第二个输入,即盐。

What sets password hashes apart from regular hashes is two things: First, they are designed to be slow and/or use large amounts of memory when evaluated. (This is irrelevant for our discussion here.) And second they take a second input, the salt.

对于密码哈希函数H,您希望对任何固定密码m以及任意两个盐s≠s',它不仅保持H(m,s)≠H(m,s'),而且在给出哈希值和盐的情况下,您也无法检测到它们是相同。

For a password hashing function H you want that for any fixed password m and any two salts s≠ s' it not only holds that H(m,s)≠ H(m,s'), but also given both hash values and salts you should not be able to detect that they are hash values of the same m.

您似乎困惑的是API设计的不同选择。特别是谁来选择盐。每次对新密码m进行哈希处理(例如输入到数据库中)时,都应选择新鲜的均匀随机盐s,然后计算哈希值h:= H(m,s)并同时存储h和s在数据库中。每当声称自己是同一用户的某人提交密码m'进行身份验证时,会发生这种情况,即检索(h,s)并检查其是否为h = H(m',s)。

What you seem confused about are different choices of API design. Specifically who gets to choose the salt. Every time a new password m is hashed (e.g. to be entered into a database), a fresh uniformly random salt s should be chosen and then the hash value h:=H(m,s) is computed and both h and s are stored in the database. Whenever someone claiming to be that same user submits a password m' to authenticate themselves, what happens is that (h,s) is retrieved and its checked whether h=H(m',s).

现在的问题是谁选择盐。您似乎熟悉的API不信任用户这样做。因此,当您调用哈希密码m时,库将选择一个salt s,计算h并输出h’=(h,s)作为哈希值。要检查密码m'是否正确,请提交h',m',然后库将提取出盐,重新计算哈希值并进行比较。

Now the question is who chooses the salt. It appears that APIs you are familiar with do not trust the user to do so. So when you make a call to hash password m, the library will choose a salt s, compute h and output h'=(h,s) as a "hash value". To check whether a password m' is correct, you then submit h',m' and the library will extract the salt, recompute the hash and compare.

您所使用的库现在正在期待用户选择盐。即,每次在密码数据库中创建新条目时,您都必须选择一个新的盐,计算h = H(m,s)并同时存储两个(h,s)。由于本例中的库不会尝试隐藏您的任何内容,因此您需要进行比较。

The library you are now looking at expects the user to choose the salt. I.e., each time you create a new entry in a password database you have to choose a new salt, compute h=H(m,s) and store both (h,s). Since the library in this case does not attempt to "hide" anything from you, you need to take care of the comparison.

这篇关于在相同的输入下,为什么节点scrypt哈希值相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆