問題描述
我想使用 SHA512 來存儲密碼.為此,我應該使用 openssl_digest
、hash
和 hash_hmac
中的哪一個,為什么?
I want to use SHA512 to store passwords. To do that, which of openssl_digest
, hash
and hash_hmac
should I use and why?
SALT
和有什么區別?HMAC
?
我剛剛讀到 HMAC 是建立在哈希函數之上的.
I just read that HMAC is built on top of hash function.
那么SHA512+SALT+HMAC
真的有必要還是SHA512+SALT
或SHA512+HMAC
?
So is SHA512+SALT+HMAC
really necessary or SHA512+SALT
or SHA512+HMAC
?
推薦答案
所以,首先,讓我們弄清楚一件事.openssl_digest()
=== hash()
.它只是另一個名稱不同的函數,它執行完全相同的操作.它計算輸入的加密哈希.
So, first off, let's clear one thing up. 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.
那么,現在我們有一個問題:存儲密碼時,哪個更好:hash
還是 hash_hmac
?
So, now we have the question: When storing passwords, which is better: hash
or hash_hmac
?
都沒有
事實證明,彩虹桌已死一>.僅使用 hash($password . $salt)
甚至 hash_hmac($password, $salt)
都不足以存儲密碼.時期.如果您正在這樣做,請立即停止.
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. Period. If you're doing so, stop right now.
原因很簡單:計算機(或 GPU)上的計算時間非常便宜.它太便宜了,以致于對密碼列表進行暴力破解已經足夠便宜,您需要擔心它.請記住,哈希函數旨在快速.不貴...
The reason is simple: computation time on a computer (or GPU) is incredibly cheap. 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. 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);
}
}
事實上,這正是 PHPASS 使用的(略有調整,但這是基本算法)...
In fact, this is exactly what PHPASS uses (slightly tweaked, but this is the base algorithm)...
所以現在對 hash_password
的 1 次調用會執行 1000 個哈希周期.
So now 1 call to hash_password
executes 1000 hash cycles.
但是我們可以改進嗎?
好吧,事實證明,我們可以.下一個合乎邏輯的事情是看看我們是否可以在相同的時間內獲得更多的哈希周期.這就是 hash_hmac()
的用武之地.事實證明,HMAC
每次被調用時使用 2 個哈希周期.而且因為它都是 C 語言,所以它只需要 hash()
完成一輪所需的時間的 1.5 倍左右.
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. 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.
這意味著如果我們將 hash
替換為 hash_hmac
,我們可以立即看到在指定時間內完成的工作量增加了 33%.所以現在我們在這里:
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. 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);
}
}
這實際上是PBKDF2的基本內循環.
And this is actually the basic inner-loop of PBKDF2.
但我們能變得更好嗎?
是的,我們可以變得更好.如果我們仔細觀察,我們會發現——除了密碼和鹽之外——上述所有算法都使用了非常少的內存.在 sha512 的情況下,他們將使用大約 128 到 256 個字節(緩沖區和狀態)來散列密碼.由于內存使用量非常小,因此在 GPU 中同時并排運行很多內存是微不足道的.如果我們只能增加內存使用...
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. Since the memory use is so small, it's trivial to run a lot of them at once side-by-side in a GPU. If we could only increase the memory usage...
好吧,事實證明,我們可以簡單地使用 bcrypt
,這是一種自適應散列算法.它的優勢在于它比上述算法使用更多的內存(大約 4 到 5kb).所以它更難并行化.由于計算成本高昂,因此它可以抵抗暴力破解.
Well, as it turns out, we can simply use bcrypt
, which is an adaptive hashing algorithm. It has an advantage that it uses more memory than the above algorithms (on the order of 4 to 5kb). So it's more resistent to parallelizing. And it's resistent to brute forcing since it's computationally expensive.
幸運的是,它可用于 PHP:
Luckily, it's available for PHP:
crypt($password, '$2y$07$usesomesillystringforsalt$')
注意 crypt()
使用了很多算法,但是 $2y$
和 $2a$
算法是 bcrypt代碼>.
Note that crypt()
uses many algorithms, but the $2y$
and $2a$
algorithms are bcrypt
.
但是我們可以改進嗎?
有點.有一種相對較新的算法,稱為 scrypt.它比 bcrypt 更好,因為它在計算上同樣昂貴,但使用了更多的內存(大約 20mb 到 40mb 來散列單個密碼).因此,它更難并行化...
Kind-of. There is a relatively new algorithm called 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). Therefore, it's even more resistent to parallelization...
不幸的是,scrypt
在 PHP 中 不可用(我正在努力改變它).在那之前,使用 bcrypt
...
Unfortunately, scrypt
is not available in PHP yet (I'm working on changing that). Until then, use bcrypt
...
最近從 LinkedIn 吸取教訓后,LastFM、Hotmail,Gawker 等,證明很多的人都做錯了.不要做錯,使用帶有經過審查的算法的庫.使用CRYPT_BLOWFISH
(bcrypt),使用PHPASS,使用PasswordLib.但是不要僅僅因為你不想拉依賴關系就發明你自己的......那只是疏忽.
After the recent lessons from LinkedIn, LastFM, Hotmail, Gawker, etc, the proof is apparent that a lot of people are doing it wrong. Don't do it wrong, use a library with a vetted algorithm. Use CRYPT_BLOWFISH
(bcrypt), use PHPASS, use PasswordLib. But don't invent your own just because you don't want to pull a dependency... That's just negligence.
更多閱讀:
- 正確加鹽密碼 - 反對 Pepper 的案例一個>
- GPU 加速 PBKDF2
- 多次哈希迭代,每次都追加鹽?一個>
- MD5 解碼,他們是怎么做的
這篇關于openssl_digest vs hash vs hash_hmac?SALT 和 SALT 的區別HMAC?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!