Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

andylcc349's avatar

Understanding Passwords

I have watched the laracast on passwords - and read several article online about how laravel creates and verifies passwords.

I understand how Hash::make will return a different hash each time it is run.

I do not understand how laravel is able to Auth::check the password if i do not supply the salt to Auth:check.

Does laravel access the database and look up the username and extract the $2y$10$[22-char-salt] from the password column for that user. ? In that case they might as well have a salt column and pass that to PHPs password-verify

0 likes
10 replies
chrisgeary92's avatar

The salt is part of the hashed password string. You'll notice the first part of the strings are all the same (or similar), this is because it's essentially "meta data" for the hashed password. The first section is the algorithm used, the 2nd is the "cost" (amount of processing power it uses), and the last part is the salt/password.

Here is a better explanation: http://stackoverflow.com/questions/16736119/bcrypt-and-randomly-generated-salts

1 like
andylcc349's avatar

This is what I thought. The password hash has 4 pieces of information concated together.
CryptType, Cost, Salt, Hash Result.

These parts could technically be held in separate columns in the database but it is more convenient to keep them in one field.

What I am trying to also understand is that if the Encryption Type, Cost and Salt are known to an attacker - can't they just produce a rainbow table with all inputs suffixed with the salt etc.

To strengthen my system I could use 2 salts, one as currently exists - the 2nd only stored in an ENV Var on the application server - not necessarily the database server. This way - if someone got hold of a password list they would not even know the salt.

i960's avatar

Bcrypt uses per password salts. Producing a rainbow table would not work as it would have to be done for every password.

jekinney's avatar

Depending on the app, isn't that a bit of overkill? You could run hashing 10 times and salt 20 (exaggeration here) but what are you trying to keep safe? Maybe I am not thinking about it right, but your generally trying to keep someone from figuring out someones password so they can't hi-jack an account, or worse the main admin account.

Just limiting the number of tries to say 3 then locked out for a determined amount of time would be fine? If someone "stole" your database the user passwords IMO wouldn't matter as much as the rest of the data presumably.

bashy's avatar

@jekinney Sure most apps don't need that but it's still good practice. Also it's not so much brute force but if the database or password(s) got displayed/dumped, it would be very long time until someone cracked them. Every password is decryptable if you have enough time.

I actually have a limiter on my sites which only allow 3 failed logins per 10 mins. Ban if over 30 failed.

1 like
andylcc349's avatar

@i960 - yes a rainbow table for each password - but with a few i7 processors i could produce a hash match quite quickly for people who use weak passwords. Enforcing min 7 chars, 1 Uppercase, 1 Digit etc does not make the rainbow table so big !, and there are limits to what i can expect of general users to use as a password. The people who us a strong password might be protected - but many use eg. "Florida89"

@jekinney - im not particularly concerned if they hack my system - ok they will screw us a bit. I'm more concerned that many users use their user pass combination in 1000 other places making them max vulnerable. If they steal our list - given that they have the salt etc - they have all the time they need to produce password combination that might match password+salt. SomeWeakishUserPasswords+KnownSalt - from a database table of 20,000,000 users, is bound to get a few hits in a cracking op.

So my idea - that passwords should be protected with a salt as laravel does using php password_hash function, + an env_var which is only on the app server away from the database might be a good option. Or second to that that the password stored in the database be hashed twice. once with the salt in the database and then again with the ENV VAR salt. Even if the database is stored on the same server as teh app - its much harder to get to READ the env vars than the apache or mysql tables.

1 like
ATOM-Group's avatar

So if we go by the last point in ircmaxell's answer, you could technically pass the full hashed string into Laravel's Crypt class, and store that.

http://laravel.com/docs/4.2/security#encryption

$encryptedHash = Crypt::encrypt(Hash::make($password));

Of course, that means all encrypted hashes will be encrypted using the same encryption key. If the key is discovered, then all of the encrypted hashes can be decrypted at once.

But my question is if the database is breached, does having 50,000+ strings all encrypted with the same key, make it easier to determine what the key is? Generally you'd only encrypt transient messages with the same key, or use unique keys per message. I'd be concerned if someone had a big data set that they know (or assume) is encrypted using the same key.

EDIT: Just did a little research, and apparently re-using the same key on N number of messages does not make the key more vulnerable to discovery, even if the messages are all identical (which hashed passwords won't be).

So it should be safe to apply Laravel's Crypt::encrypt() to the output of Hash::make() before storage.

i960's avatar

@andylcc349 - A rainbow table would still be useless. The entire point of a rainbow table is to compute all of the hashes ahead of time for every possible password, and then compare those results with the hashes stored in the database. With per password salts, you would have to compute every password one by one, AKA brute force. Any rainbow table you produced for one password/salt combo would be useless for any other password/salt combo. And since bcrypt is intentionally slow, it would take a lot more than a few i7 processors to brute force passwords in a reasonable amount of time. Yes, any passwords that are weak will be cracked faster than good passwords, but not nearly as quick if bcrypt with per password hashes were not used. You are right though that enforcing good passwords is a good idea. But weak passwords + bcrypt is still better than strong passwords + something like sha1 with a single salt for all passwords.

Please or to participate in this conversation.