November 30, 2016 —John Koster
The Illuminate\Hashing\Bcrypt
hasher is registered with the service container in the Illuminate\Hashing\HashServiceProvider
service provider, and is bound to the name hash
(the hash
key in the service container is itself an alias for the Illuminate\Contracts\Hashing\Hasher
interface). The following code sample would return an instance of the Bcrypt
hasher by default:
1<?php2 3// Get a new Bcrypt instance.4$hasher = app('hash');
The Bcrypt
hasher is also used by the bcrypt
application helper function. It actually uses the above method to resolve the Bcrypt
hasher from the service container. This means that any other service provider that modifies the hash
service container entry will also affect the bcrypt
helper function. The bcrypt
helper function is also used internally in the Illuminate\Foundation\Auth\ResetPasswords
trait; specifically, it is used in the implementation of the resetPassword($user, $password)
method.
The following sections will explain the Bcrypt
hasher's various methods.
setRounds($rounds)
The setRounds
method is simple way to control how many rounds, or iterations the make
method will use when calculating the final hash. An argument passed to $rounds
must be a positive integer between 4
and 31
(including both 4
and 31
). If an integer outside the stated range is supplied an instance of ErrorException
will be thrown. The internal default value for $rounds
is 10
.
make($value, array $options = [])
The make
method is used to hash a given $value
with the provided $options
. At the time of writing, the rounds
value is the only option that is checked for in the $options
array. See the information on the setRounds
method for more information on the rounds
option. The internal default value for rounds
is 10
.
If a user supplies a value for rounds
using the $options
array, that value will be used when calculating the hash. In all other scenarios, the internal value for rounds
will be used (this value can be modified using the setRounds($rounds)
method).
The make
method internally makes a call to PHP's password_hash
function with PASSWORD_BCRYPT
as the argument for the $algo
parameter.
The following code example will get an implementation of Illuminate\Contracts\Hashing\Hasher
from the service container and generate a few hashes. The output will appear below the code example. The output will be different each time the code is ran:
1<?php 2 3/** 4 * Get a new instance of Hahser from the service container. 5 * 6 * @var \Illuminate\Contracts\Hashing\Hasher $hasher 7 */ 8$hasher = app('Illuminate\Contracts\Hashing\Hasher'); 9 10// Generate hashes for integers 0 - 911// using the default work factor.12for ($i = 0; $i < 10; $i++) {13 echo $hasher->make($i),PHP_EOL;14}
The above would produce results similar to the following output:
1$2y$10$jVlNmKI5Gg0j.3nER7tevuUaesWYIuwoxzghpIKfb2LvNMoTGaac6 2$2y$10$DZzbYPf88wWo6nFW4LOAje4oJsWxZK.vg.k6vqxouXmb/6lsx045y 3$2y$10$7CKZ0rmSOVxjvc2XG3diLOpalxjMkjcdw1.zKeqZPiSa7dD8K7GdS 4$2y$10$qpiLO4hCLgYWmK4WJp0tTuv7klAM6RO5QrAnEqn1ULN92S.V5U4B6 5$2y$10$no8cpUgVPiLw9rYOBknKWeiO2fC45.dzzhxE.rW8qn9ZojixXvoq. 6$2y$10$31BmbMpivMGz1bsf5PAwTeEFhnS0GMS4GOkjNp.TWh9PZsZ0jLVWC 7$2y$10$76T.L071J.8ewnnI3oocoukJtC8QljZiIesebdgewyMKygsl20QU2 8$2y$10$nCE.5KTwPR8g6mrm4M9jlecoBpITCavThwRT0IZVQuMRg8qHQXaea 9$2y$10$8uQ/0uc6wB1OQ7220wA2Ze54WqMzKTxWPQyi./bODTiBL/I7QgwgW10$2y$10$2ywQnQZKXAHMRqmj4iCr5O9Lr67Gv9u1BjXEiVspSRO.gWV1ROF7a
check($value, $hashedValue, array $options = [])
The check
method will validate a given $value
against a previously generated $hashedValue
. The $options
parameter is not utilized in Laravel's Bcrypt
implementation. The $value
must be the plain text value to check, and the $hashedValue
should be the previously generated hash. The check
method internally makes a call to PHP's password_verify
function.
The following code example will generate a hash for the string Ave Maria
and perform some check if arbitrary strings are valid against the hashed value.
1<?php 2 3/** 4 * Get a new instance of Hahser from the service container. 5 * 6 * @var \Illuminate\Contracts\Hashing\Hasher $hasher 7 */ 8$hasher = app('Illuminate\Contracts\Hashing\Hasher'); 9 10// Generate a hash for "Ave Maria"11$hash = $hasher->make('Ave Maria');12 13// true14$isValid = $hasher->check('Ave Maria', $hash);15 16// false17$isValid = $hasher->check('Ave maria', $hash);18 19// false20$isValid = $hasher->check('password', $hash);
The following example will generate twenty hashes for the string Ave Maria
and check the original string against all hashes. This demonstrates that even though the hashes are different each time a string is hashed, enough information is stored with the hash that a password can be checked successfully;
1<?php 2 3/** 4 * Get a new instance of Hahser from the service container. 5 * 6 * @var \Illuminate\Contracts\Hashing\Hasher $hasher 7 */ 8$hasher = app('Illuminate\Contracts\Hashing\Hasher'); 9 10// Generate 20 hashes for "Ave Maria"11for ($i = 0; $i < 20; $i++) {12 $validHashes[] = $hasher->make('Ave Maria');13}14 15// Check "Ave Maria" against all 20 differnet hashes.16// They should all be valid.17foreach ($validHashes as $hash) {18 $isValid = $hasher->check('Ave Maria', $hash);19 20 // Improve the readability of the output.21 $isValid = ($isValid) ? 'true' : 'false';22 23 echo $hash, ' valid: ', $isValid, PHP_EOL;24}
The above code would generate something similar to the following output (the exact hashes will change each time it is ran):
1$2y$10$0wgNNEz6N6avHmomWEPQI.GVZS32c8Kk.E1jAdUp0n4SuILQNohQC valid: true 2$2y$10$g81.C5MDdFfYXLMM6iRPJOW8frm6N6jAHYBzQT9TddbYFX2pDgt2W valid: true 3$2y$10$lWIUivhbnr8W3ILhquCqVuVl2E2esGNFSd4pueuVp/I7BbCNPI48. valid: true 4$2y$10$WIHxrlsgCpIqUZKIzi5AEe4cMWBCvFliwBas7YGMuJS4yDxI4f/Je valid: true 5$2y$10$XBq/FNfv87T0SXGBUd0UvO/azpuECPDYM7cLSKhszWBwu3I2m5aO2 valid: true 6$2y$10$El8v3pu2Ko4IQ82g4Xacd.NpJw3Pj4VLLoIJMIVmPDQqur9tSzG/i valid: true 7$2y$10$pW85CptXh9cC6XQ6HqKwTeBOrBWBMsogFRpNTHxvHc4U8bBUS/Wte valid: true 8$2y$10$5j6hK9uYpc3Vbp4ATsJh5O8MxTIzB8JMmgxLlULA6HjOd4mFnW13u valid: true 9$2y$10$W3rNwIfEfBMaiub1kxhW5u2b3lrwpLNzPajOc2CYy224s4WUEdpGW valid: true10$2y$10$h6gEqC8IfQRmBflGD93BD.hNwNBYxQaMPqkKLqAySAfQziL2deYvS valid: true11$2y$10$8QQ7RpXOfCIl0dZi0XcL1uuAFui6xCqbWLyIZxRWmwwYizK4ckOO2 valid: true12$2y$10$RHhyoygqBS3Cb.kwXEihW.jLh.wOkIO6wjSZIqcK3HeStR.Jy/IFC valid: true13$2y$10$jHd4HrR.2f.Vf7XIsVdPVuoIxUNMWpErwRZtiyffenG7adJd7AOJS valid: true14$2y$10$CwK0aN9BtVYfb2yIIfbpduPJ1CFtvA028jK1EDZmH1PdpGwLO.b06 valid: true15$2y$10$lsfaDaZqrt.n.UByvC90e.JXCKUa48uiUekue5zKDIJEFKEblkNQK valid: true16$2y$10$.QoDYocdqXltvr4Q4E67V.tFpsXtuq3IshwCpMlanFES/sLYIUx4q valid: true17$2y$10$MlfY7z9aKSudnkd00r6h5O0ZSt6B7qBel8jXEYGEaL7.zugM.lfbq valid: true18$2y$10$4jvJYkkpTjlj1nwW8epIb.QLYK0nrDEnKmj/BfcGyTlIjaQO/2Dh6 valid: true19$2y$10$XFEfJeDM.rTc3Kj4cMEYtegiRejRynLbn7aubaPzd0G3iHbf5VgVS valid: true20$2y$10$.NDd6lPPSaJ0uRttNhB8K.kmk/i.1ntNI4/Apj.RtXkyDHncwAdNm valid: true
needsRehash($hashedValue, array $options = [])
The needsRehash
method is used to determine if the provided $hashedValue
has been hashed with the supplied $options
. This is useful for when the work factor of a hashing function has been updated and all passwords need to be updated to use the new hashing options. The following code example will demonstrate the usage of the needsRehash
method. It also shows that two hashes generated with different $options
will still be valid, but only one of them does not need to be rehashed.
1<?php 2 3/** 4* Get a new instance of Hahser from the service container. 5* 6* @var \Illuminate\Contracts\Hashing\Hasher $hasher 7*/ 8$hasher = app('Illuminate\Contracts\Hashing\Hasher'); 9 10// Generate a hash with fewer rounds than the default.11$lessRounds = $hasher->make('Ave Maria', ['rounds' => 4]);12 13// Generate a hash with the default number of rounds.14$defaultRounds = $hasher->make('Ave Maria');15 16// Generate a hash with more rounds than the default.17$moreRounds = $hasher->make('Ave Maria', ['rounds' => 11]);18 19// All of these are valid.20$isValid = $hasher->check('Ave Maria', $lessRounds);21$isValid = $hasher->check('Ave Maria', $defaultRounds);22$isValid = $hasher->check('Ave Maria', $moreRounds);23 24// This hash needs to be rehashed because it was generated with25// fewer rounds than the current number of rounds (default).26$needsRehash = $hasher->needsRehash($lessRounds);27 28// This hash does not need to be rehashed because it was generate29// with the same number of rounds as the current number of rounds.30$needsRehash = $hasher->needsRehash($defaultRounds);31 32// The $moreRounds hash also needs to be rehashed because it has more rounds33// than the current number of rounds (the default number), even though it34// has a higher work factor.35$needsRehash = $hasher->needsRehash($moreRounds);
Laravel provides many facades to make it easier to quickly build application and test ideas. One such facade is the Illuminate\Support\Facades\Hash
facade, which provides access to whatever implementation is bound to the Illuminate\Contracts\Hashing\Hasher
interface within the service container. Since the Hash
facade resolves an implementation of Hasher
, all Hasher
methods can be used on the facade:
1<?php 2 3use Illuminate\Support\Facades\Hash; 4 5// All of the following calls are functionally 6// equivalent. The output will differ only 7// because bcrypt hashes will differ. 8$hash = Hash::make('test'); 9$hash = app('hash')->make('test');10$hash = app('Illuminate\Contracts\Hashing\Hasher')->make('test');
∎
The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.