问题
I want to use Bcrypt for the password encryption in my systems. But all the examples are something like this:
$password = $_POST['password'];
$salt = substr(str_replace('+', '.', base64_encode(sha1(microtime(true), true))), 0, 22);
$hash = crypt($password, '$2a$12$'.$salt);
This looks pretty safe to me, but I was wondering, in each example, nobody hashes the password before using Bcrypt.
Due to the unique salt, Rainbow tables shouldn't be able to crack all the passwords at once. But in case the hacker takes one record and creates a rainbow table with the salt of that particular record, he should be able to crack a weak password.
So if someone takes a weak password (let's say 'foo'), it would be safer to hash it first with SHA-512 before using Bcrypt. Am I right? Or is this just looking safer?
回答1:
Actually the answer has to be no, it doesn't make the hash significant stronger in a cryptographically sense. As you probably know, bcrypt (although the function to use is named crypt
) is a hash function itself, not an encryption function.
In bcrypt you pass a cost factor, which defines, how many iterations will be done (normally hundreds of them). That slows down calculation of the hash, what makes brute force attacks impracticable. Using SHA-512 before, will only add one iteration more.
What you said about the salt is correct, but of course if you have to build a rainbow table for each password, you will simply brute force until you have found a match, no need to build the whole rainbow table.
If the attacker has control over database and code, an additional SHA-512 will help nothing at all (only a single iteration more). If he has only the database without code (SQL-Injection), then he will recognize the bcrypt hash. He can now brute force with bcrypt, but because of the SHA-512 there aren't any weak passwords. It's like the SHA-512 hash would be the password to crack, so a dictionary is of no use. This is security by obscurity, but will be effective as long as the code is not known. You can get the same effect easier, by adding a fix hard coded salt (key), before using bcrypt with the unique salt.
回答2:
crypt()
is a one-way string hash, not an encryption mechanism. To use an SHA-512 hash, you have to use the hash()
function. Bcrypt requires a PHP extension. For storing passwords, why do you want to make them reversible, rather than just hashing them? That's less secure -- if someone gets your key and DB, they have all the passwords, but a table of SHA512 hashes is pretty useless.
回答3:
Hashing first won't help. A bad password is one that is deemed more probable by an attacker and placed earlier in his list of passwords to try.
Bcrypt incorporates salt to eliminate pre-computed lookup tables (a Rainbow Table is one example). Why would an attacker build a rainbow table for a single record? No, when attacking a salted password, an attacker simply works through his ordered list of most likely passwords, repeating the hash algorithm to see if it matches.
How far he can work through that list depends on how long the hash algorithm takes to execute. Bcrypt controls that with the "cost" factor—12 in your example (which is okay, but probably the minimum I'd use). An extra SHA-512 round doesn't add anything to that. You are already performing 4096 expensive bcrypt iterations. Adding 1 cheap SHA-512 iteration is negligible.
If you choose the first password on the list, it will be broken in a fraction of a second. If you pick the billionth password, the attacker won't break it for a few decades.
回答4:
bcrypt already uses salt, and what it's doing internally is quite a bit stronger than SHA512. Adding an iteration of SHA512 (and/or an extra layer of salt) on top of bcrypt will not give you a significantly stronger result. If the two functions interact in the wrong way, combining them in this way may in fact give you a hash function that is weaker.
来源:https://stackoverflow.com/questions/11276026/using-512-hash-before-bcrypt