Password Hashing

To manage the security of our users, we never store their passwords in plaintext format, we store the password´s hash instead. Hashing is not a reversible operation, the password cannot be recovered. The password can be cracked though and to make cracking as hard as possible we have to use a secure algorithm. Class Nette\Security\Passwords will help us with that.

Installation:

composer require nette/utils

Following examples expect this alias:

use Nette\Security\Passwords;

hash(string $passwords, array $options=null)string

Generates password´s hash using a modern bcrypt algorithm. We can set the cost parameter of range 4–31, which sets the number of iterations the algorithm takes to run and changes the hashing speed. If we omit this parameter, a default value of 10 will be used.

In year 2020, with cost 10, the hashing of one password takes roughly 80ms, cost 11 takes 160ms, cost 12 then 320ms, the scale is logarithmic. The slower the better, cost 10–12 is considered slow enough for most use cases.

$hash = Passwords::hash($password); // Hashes the password
$hash = Passwords::hash($password, ['cost' => 12]); // Hashes the password using 2^12 iterations of bcrypt algorithm

The result $hash contains the algorithm identifier and its settings, cryptographical salt and the hash itself. The full hash is backwards compatible, when you change the hashing parameters, you'd still be able to verify passwords hashed using previous settings. Store the full result to database, so there is no need to store salt or settings separately.

verify(string $password, string $hash)bool

Finds out, whether the given password matches the given hash. Get the $hash from database by username or email address.

if (Passwords::verify($password, $hash)) {
	// Correct password
}

needsRehash(string $password, array $options=null)bool

Finds out if the hash matches given options. We can set the cost parameter of range 4–31, which sets the number of iterations the algorithm takes to run. If we omit this parameter, a default value of 10 will be used.

Use this method when you're for example changing hashing parameters. Password verification will use parameters stored with the hash and if needsRehash() returns true, you have to calculate the hash again, this time with the updated parameters, and again store it in database. This ensures that passwords hashes will be automatically “upgraded” when users are signing in.

if (Passwords::needsRehash($hash, $options)) {
	$hash = Passwords::hash($password, $options);
	// store $hash to database
}
Improve this page