Why is password hashing, e.g. php's password_hash so slow? Why is password hashing, e.g. php's password_hash so slow? php php

Why is password hashing, e.g. php's password_hash so slow?


After running on 3v4l that seems perfectly normal.

Password hashing is not something you want optimize. In the words of Leigh on the hash documentation:

If you are hashing passwords etc for security, speed is not your friend. You should use the slowest method.

Slow to hash means slow to crack and will hopefully make generating things like rainbow tables more trouble than it's worth.


The default algorithm for password_hash, bcrypt, is designed to be slow.

http://en.wikipedia.org/wiki/Key_stretching

In cryptography, key stretching refers to techniques used to make a possibly weak key, typically a password or passphrase, more secure against a brute force attack by increasing the time it takes to test each possible key. Passwords or passphrases created by humans are often short or predictable enough to allow password cracking. Key stretching makes such attacks more difficult.

http://en.wikipedia.org/wiki/Rainbow_table#Defense_against_rainbow_tables

Another technique that helps prevent precomputation attacks is key stretching. When stretching is used, the salt, password, and a number of intermediate hash values are run through the underlying hash function multiple times to increase the computation time required to hash each password. For instance, MD5-Crypt uses a 1000 iteration loop that repeatedly feeds the salt, password, and current intermediate hash value back into the underlying MD5 hash function. The user's password hash is the concatenation of the salt value (which is not secret) and the final hash. The extra time is not noticeable to users because they have to wait only a fraction of a second each time they log in. On the other hand, stretching reduces the effectiveness of a brute-force attacks in proportion to the number of iterations because it reduces the number of computations an attacker can perform in a given time frame. This principle is applied in MD5-Crypt and in bcrypt. It also greatly increases the time needed to build a precomputed table, but in the absence of salt, this needs only be done once.

A full second is probably a little long - you could experiment with dropping $cost by one or two to bring it more to something like a tenth of a second, which will retain the effective protection while making the delay unnoticeable to your users.


Yes, it's normal. That's what the cost parameter is for: it allows you to tweak the iteration count, making the hash slower or faster as needed.

You should always make the hash as slow as possible and as fast as necessary. The reason being that the only feasible attack on a password hash is brute force. You want to make the cost so large that it takes prohibitively long to simple brute force all possible values. That's your only real defence against attackers with password hashing to begin with.

One whole second seems prohibitively for your own use. You should lower that cost a bit to stay within a few hundred milliseconds at most. Adjust to your target systems as needed.