简体   繁体   English

openssl_digest vs hash vs hash_hmac? SALT和HMAC之间的区别?

[英]openssl_digest vs hash vs hash_hmac? Difference between SALT & HMAC?

I want to use SHA512 to store passwords. 我想使用SHA512来存储密码。 To do that, which of openssl_digest , hash and hash_hmac should I use and why? 要做到这openssl_digest ,我应该使用openssl_digesthashhash_hmac哪一个?为什么?


What is the difference between SALT & HMAC ? SALTHMAC什么区别?


I just read that HMAC is built on top of hash function. 我刚刚读到HMAC是建立在哈希函数之上的。

So is SHA512+SALT+HMAC really necessary or SHA512+SALT or SHA512+HMAC ? SHA512+SALT+HMAC真的有必要还是SHA512+SALTSHA512+HMAC

So, first off, let's clear one thing up. 所以,首先,让我们清楚一件事。 openssl_digest() === hash() . openssl_digest() === hash() It's just another function by a different name that does the exact same thing. 它只是另一个不同名称的功能,完全相同。 It computes a cryptographic hash of the input. 它计算输入的加密哈希值。

So, now we have the question: When storing passwords, which is better: hash or hash_hmac ? 所以,现在我们有了一个问题: 存储密码时哪个更好: hashhash_hmac

Short Answer: 简答:

Neither 也不

Long Answer: 答案很长:

As it turns out, The Rainbow Table Is Dead . 事实证明, 彩虹表已经死了 Just using hash($password . $salt) or even hash_hmac($password, $salt) is not good enough for password storage. 只使用hash($password . $salt)甚至hash_hmac($password, $salt)对于密码存储来说还不够好。 Period. 期。 If you're doing so, stop right now. 如果您这样做,请立即停止。

The reason is simple: computation time on a computer (or GPU) is incredibly cheap. 原因很简单:计算机(或GPU)上的计算时间非常便宜。 It's so cheap, that to brute force a list of passwords is cheap enough that you need to worry about it. 这是如此便宜,以至于蛮力的密码列表足够便宜,你需要担心它。 Remember, hash functions are designed to be fast . 请记住,哈希函数设计得很快 Not expensive... 不贵啊...

But, as it also turns out, there is a way to make those fast hash functions more expensive. 但是,事实证明,有一种方法可以使这些快速哈希函数更加昂贵。 In fact, it's pretty simple: iterate. 事实上,它非常简单:迭代。

Now, I know what you're thinking. 现在,我知道你在想什么。 You're going to just loop over the hash: 你将只是循环哈希:

function hash_password($password, $salt) {
    $hash = hash("sha512", $password . $salt);
    for ($i = 0; $i < 1000; $i++) {
        $hash = hash("sha512", $hash);
    }
}

Surely that's good enough, right? 当然这很好,对吧? Nope. 不。 As explained in Fundamental Difference Between Hashing and Encryption , that's not a good idea. 正如Hashing和Encryption之间的基本差异所解释的那样,这不是一个好主意。 So why not just feed back the password and salt in again? 那么为什么不再重新输入密码和盐呢?

function hash_password($password, $salt) {
    $hash = hash("md5", $salt . $password);
    for ($i = 0; $i < 1000; $i++) {
        $hash = hash("md5", $hash . $password);
    }
}

In fact, this is exactly what PHPASS uses (slightly tweaked, but this is the base algorithm)... 事实上,这正是PHPASS使用的(略微调整,但这是基本算法)...

So now 1 call to hash_password executes 1000 hash cycles. 所以现在1调用hash_password执行1000个哈希循环。

But can we improve on that? 但我们可以改进吗?

Well, as it turns out, we can. 好吧,事实证明,我们可以。 The next logical thing to do would be to see if we can get more hash cycles for the same amount of time. 下一个合乎逻辑的做法是看看我们是否可以在相同的时间内获得更多的哈希循环。 And this is where hash_hmac() comes in. As it turns out, HMAC uses 2 hash cycles each time it's called. 这就是hash_hmac()用武之地。事实证明, HMAC每次调用时都会使用2个哈希周期。 And because it's all C, it only takes about 1.5 times the amount of time that hash() takes to do a single round. 而且因为它都是C,所以它只需要hash()执行一轮的时间量的1.5倍。

So that means if we replace hash with hash_hmac , we can instantly see a 33% increase in the amount of work being done in a specified time. 这意味着如果我们用hash_hmac替换hash ,我们可以立即看到在指定时间内完成的工作量增加了33%。 So now we're here: 所以现在我们在这里:

function hash_password($password, $salt) {
    $hash = hash_hmac("md5", $salt, $password);
    for ($i = 0; $i < 1000; $i++) {
        $hash = hash_hmac("md5", $hash, $password);
    }
}

And this is actually the basic inner-loop of PBKDF2 . 这实际上是PBKDF2的基本内循环。

But can we get better? 但我们可以变得更好吗?

Yes, again, we can get better. 是的,再次,我们可以变得更好。 If we look closely, we can see that -in addition to password and salt- all of the above algorithms use a very small amount of memory. 如果我们仔细观察,我们可以看到 - 除了密码和盐 - 所有上述算法都使用非常少量的内存。 In the case of sha512, they'll use on the order of 128 to 256 bytes (buffers and state) to hash the password. 在sha512的情况下,它们将使用128到256字节(缓冲区和状态)的顺序来散列密码。 Since the memory use is so small, it's trivial to run a lot of them at once side-by-side in a GPU. 由于内存使用量非常小,因此在GPU中并排运行大量内存非常简单。 If we could only increase the memory usage... 如果我们只能增加内存使用量......

Well, as it turns out, we can simply use bcrypt , which is an adaptive hashing algorithm. 好吧,事实证明,我们可以简单地使用bcrypt ,这是一种自适应散列算法。 It has an advantage that it uses more memory than the above algorithms (on the order of 4 to 5kb). 它的优点是它使用比上述算法更多的内存(大约4到5kb)。 So it's more resistent to parallelizing. 因此,对并行化更具抵抗力。 And it's resistent to brute forcing since it's computationally expensive. 并且由于它的计算成本很高,因此它对强制执行是不利的。

Luckily, it's available for PHP: 幸运的是,它适用于PHP:

crypt($password, '$2y$07$usesomesillystringforsalt$')

Note that crypt() uses many algorithms, but the $2y$ and $2a$ algorithms are bcrypt . 请注意, crypt()使用许多算法,但$2y$$2a$算法是bcrypt

But can we improve on this? 但我们能改进吗?

Kind-of. 的种类。 There is a relatively new algorithm called scrypt . 有一种叫做scrypt的相对较新的算法。 It's better than bcrypt, because it's just as computationally expensive, but uses a LOT more memory (on the order of 20mb to 40mb to hash a single password). 它比bcrypt更好,因为它的计算成本非常高,但是使用了更多的内存(大约20mb到40mb来散列单个密码)。 Therefore, it's even more resistent to parallelization... 因此,对并行化更具抵抗力......

Unfortunately, scrypt is not available in PHP yet (I'm working on changing that). 不幸的是,PHP中还没有 scrypt (我正在努力改变它)。 Until then, use bcrypt ... 在那之前,使用bcrypt ......

Sidenote 边注

After the recent lessons from LinkedIn , LastFM , Hotmail , Gawker , etc, the proof is apparent that a lot of people are doing it wrong. LinkedInLastFMHotmailGawker等最近的经验教训之后,很明显很多人都做错了。 Don't do it wrong, use a library with a vetted algorithm. 不要做错,使用带有审查算法的库。 Use CRYPT_BLOWFISH (bcrypt), use PHPASS, use PasswordLib . 使用CRYPT_BLOWFISH (bcrypt),使用PHPASS,使用PasswordLib But don't invent your own just because you don't want to pull a dependency... That's just negligence. 但是不要仅仅因为你不想依赖而发明自己的......这只是疏忽。

More reading: 更多阅读:

HMAC is a specific way to use a hash algorithm (like SHA512). HMAC使用哈希算法(如SHA512)的特定方法。 It's used to sign a message and you can then verify that the message is from a specific signer and has not been altered. 它用于签署消息,然后您可以验证消息是否来自特定签名者并且未被更改。 So this isn't what you want. 所以这不是你想要的。

A salt is used to add a bit of "randomness" to a text that should be encrypted or hashed. salt用于向应加密或散列的文本添加一些“随机性”。 The point is that even if you encrypt the same text several times you'd get different results. 关键是,即使您多次加密相同的文本,您也会得到不同的结果。 This makes it harder to do some attacks. 这使得进行一些攻击变得更加困难。 This is what you want: SHA512(salt+password) . 就是你想要的: SHA512(salt+password)

For storing passwords, the most secure way I could imagine would be: 对于存储密码,我能想象的最安全的方式是:

(disclaimer: I'm not very experienced with cryptography and there might be a better solution) (免责声明:我对加密技术不是很熟悉,可能有更好的解决方案)

  • Client (JavaScript code?) would generate a salt value. 客户端(JavaScript代码?)会生成一个salt值。
  • The client then combines salt and password, and run the result through your hashing algorithm. 然后,客户端将salt和密码组合在一起,并通过散列算法运行结果。
  • The client then transmits both salt and hash value to the server which stores it (preferably in different locations). 然后,客户端将salt和hash值都发送到存储它的服务器(最好是在不同的位置)。

To verify a password, you'd then do: 要验证密码,您需要执行以下操作:

  • Pass the salt to the client. 将盐传递给客户。
  • Client combines salt and entered password, runs it through your hashing algorithm. 客户端将salt和输入的密码组合在一起,通过哈希算法运行它。
  • Client sends the hash value to the server. 客户端将哈希值发送到服务器。
  • Server compares the hash value with the stored hash value. 服务器将哈希值与存储的哈希值进行比较。 If they match, it was the same password. 如果匹配,则密码相同。

Of course you could transmit the password in plaintext and do the whole salting and hashing on the server, but this would weaken your solution dramatically. 当然,你可以用明文传输密码并在服务器上进行整个salting和散列,但这会大大削弱你的解决方案。 You should never transmit the password in plaintext. 绝不应以明文形式传输密码。

But the "pass the salt to the client" part might be a problem. 但是“将盐传递给客户”部分可能是个问题。 One way that I could imagine to solve this would be to somehow derive the salt from the username (easiest way: simply do lowercase(username) + password ), but the problem with that would be that the salt would be predictable and thus weakening your solution a little bit. 我可以想象解决这个问题的一种方法是以某种方式从用户名中获取salt(最简单的方法:只做lowercase(username) + password ),但问题是盐可以预测,从而削弱你的解决方案一点点。 Yet, it's still way better than transmitting the "raw" hash and you wouldn't even need to store the salt as you could derive it from the username every time. 然而,它仍然方式比发射“原始”哈希更好,你甚至不会需要存储的盐,你可以从用户名,每次得到它。 Should your password DB get stolen it would still resist a rainbow table attack with this "salting with username" approach. 如果您的密码数据库被盗,它仍然可以通过这种“用户名腌制”方法抵御彩虹表攻击。

The problem is that a man-in-the-middle attack is still possible. 问题是仍然可能发生中间人攻击。 If an attacker would intercept username and hash it has all the relevant infos and it wouldn't be any different than transmitting the plaintext password. 如果攻击者拦截用户名和哈希,则它具有所有相关的信息,并且与发送明文密码没有任何不同。 So you might want to secure the connection with SSL (HTTPS). 因此,您可能希望使用SSL(HTTPS)保护连接。

According to IT Security experts: 根据IT安全专家的说法:

Use Bcrypt Source: https://security.stackexchange.com/a/10905/7599 . 使用Bcrypt来源: https//security.stackexchange.com/a/10905/7599

I would give answer according to SO point of view. 我会根据SO的观点给出答案。

openssl_digest vs hash vs hash_hmac
  1. openssl_digest - Computes a digest. openssl_digest - 计算摘要。
  2. hash Generate a hash value (message digest) hash生成哈希值(消息摘要)
  3. hash_hmac — Generate a keyed hash value using the HMAC method hash_hmac - 使用HMAC方法生成键控哈希值

And In cryptography, a hash-based message authentication code (HMAC) is a specific construction for calculating a message authentication code (MAC) involving a cryptographic hash function in combination with a secret key. 并且在密码学中, 基于散列的消息认证码(HMAC)是用于计算涉及密码散列函数结合密钥的消息认证码(MAC)的特定结构。

As said by ircmaxell, hash or hash_hmac are not better for storing passwords with SHA-512. 正如ircmaxell所说, hashhash_hmac对于使用SHA-512存储密码并不是更好。 I would rather say, you can use openssl_digest for storing passwords. 我宁愿说,您可以使用openssl_digest存储密码。

See SHA-512 library for PHP 请参阅用于PHP的SHA-512库

SALT vs HMAC
  1. A hash, in this context, is a one-way function - ie a function that makes it very easy to find the result from the argument (the password) but difficult (or impossible) to find any argument that generates a given result. 在这种情况下,哈希是一个单向函数 - 即一个函数,它可以很容易地从参数(密码)中找到结果,但很难(或不可能)找到生成给定结果的任何参数。
  2. A salt is some auxiliary data that augments the argument to a hash function. salt是一些辅助数据,用于扩充哈希函数的参数。 This is useful as it prevents accidental discovery of passwords through observation that two hashed passwords have identical values. 这很有用,因为它可以通过观察两个散列密码具有相同的值来防止意外发现密码。 With a salt, the stored/transmitted value will only be identical if both the salt and the password match. 对于salt,如果salt和password都匹配,则存储/传输的值将相同。
  3. An HMAC refers to the application of a hash (and optional salt) to a "message authentication code" - which, depending upon context might be a password... or, at least, there's nothing stopping you passing a password into the HMAC as if it were the message authentication code. HMAC是指将哈希(和可选盐)应用于“消息身份验证代码” - 根据上下文可能是密码...或者,至少,没有什么能阻止您将密码传递给HMAC如果是消息验证码。

HMAC is meant to be used in cases where you have a random and secret key. HMAC旨在用于您拥有随机密钥的情况。 For these cases, HMAC is usually better than other ways of incorporating the key into the hash function. 对于这些情况,HMAC通常比将密钥合并到散列函数中的其他方式更好。 (For example, using HMAC takes care of things like extension attacks, etc.) (例如,使用HMAC处理扩展攻击等事情)

Salt is usually a random value that is not secret. 盐通常是一个非秘密的随机值。 That is to say, when you use the term salt you usually refer to situations where there is a random value that may very well be known to the attacker. 也就是说,当你使用术语salt时,通常指的是攻击者可能已经知道随机值的情况。 The security of the system should therefore not depend on the salt being kept secret. 因此,系统的安全性不应取决于保密的盐。 In these situations HMAC is often not a very good choice. 在这些情况下,HMAC通常不是一个很好的选择。

HMAC and Salt comparison is not logical. HMAC和Salt比较不合逻辑。 Personally I'd use a salt and a hash function... and I wouldn't be paranoid about the strength of the hash function as its unlikely to be the weak link in any practical system.... 就个人而言,我会使用一个salt和一个哈希函数......我不会对哈希函数的强弱感到偏执,因为它不太可能成为任何实际系统中的薄弱环节....

See http://www.derkeiler.com/Newsgroups/sci.crypt/2006-01/msg00321.html 请参阅http://www.derkeiler.com/Newsgroups/sci.crypt/2006-01/msg00321.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM