In this article we will create an implementation of Illuminate\Contracts\Hashing\Hasher using PHP
s crypt function and the CRYPT_STD_DES hashing function. Before we write the code for the CRYPT_STD_DES implementation, we will examine each method that the Hasher interface requires, as well as think about the options our hasher might utilize:
#make($value, array $options = [])
The make method is responsible for doing the actual hashing. It also accepts an $options array. We will allow a salt to be supplied using the options array. If no salt is supplied, we will generate one.
For the actual hashing, we will make a call to PHP's crypt function.
#public function check($value, $hashedValue, array $options = [])
The check method is used to check that a known $value is the same as a $hashedValue. We will not need any options for this method.
Internally, we will use the make method and PHP's hash_equals function.
#public function needsRehash($hashedValue, array $options = [])
The needsRehash method is used to determine if a given hash needs to be updated, or rehashed. We will accept a salt as an option. If the salt from the $options array does not match the salt from the $hashedValue the $hashedValue needs to be rehashed.
The following is the complete implementation of the StandardDesHasher class:
| StandardDesHasher Option | Description | 
|---|---|
| salt | Users can supply their own two character salt to the makeandneedsRehashmethods. If no salt is supplied to themakemethod, one will be generated. | 
 1<?php
 2
 3namespace Laravel\Artisan\Hashing;
 4
 5use RuntimeException;
 6use Illuminate\Contracts\Hashing\Hasher as HasherContract;
 7use Illuminate\Support\Str;
 8
 9class StandardDesHasher implements HasherContract
10{
11
12    const FAILED_HASH = '*0';
13
14    /**
15     * Hash the given value.
16     *
17     * @param  string  $value
18     * @param  array   $options
19     * @return string
20     *
21     * @throws \RuntimeException
22     */
23    public function make($value, array $options = [])
24    {
25        // If the user supplied a salt, use that. If not we
26        // can generate it using the Str helper methods.
27        $salt = isset($options['salt']) ? $options['salt'] : Str::random(2);
28
29        $hash = crypt($value, $salt);
30
31        if ($hash == self::FAILED_HASH) {
32            // Throw an exception because the hashing failed.
33            throw new RuntimeException('DES hashing failed.');
34        }
35
36        return $hash;
37    }
38
39    /**
40     * Check the given plain value against a hash.
41     *
42     * @param  string  $value
43     * @param  string  $hashedValue
44     * @param  array   $options
45     * @return bool
46     */
47    public function check($value, $hashedValue, array $options = [])
48    {
49        $userValue = $this->make($value, ['salt' => $hashedValue]);
50
51        return hash_equals($hashedValue, $userValue);
52    }
53
54    /**
55     * Check if the given hash has been hashed using the given options.
56     *
57     * @param  string  $hashedValue
58     * @param  array   $options
59     * @return bool
60     */
61    public function needsRehash($hashedValue, array $options = [])
62    {
63        if (!isset($options['salt'])) {
64            return false;
65        }
66
67        return (mb_substr($hashedValue, 0, 2)
68            !== mb_substr($options['salt'], 0, 2));
69    }
70
71}
The following sample demonstrates the usage of the custom StandardDesHasher hasher implementation:
 1<?php
 2
 3use Laravel\Artisan\StandardDesHasher;
 4
 5// Create a new instance of StandardDesHasher
 6$hasher = new StandardDesHasher;
 7
 8// Calculate a hash, randomly generated salt. Output
 9// of this method call should change each time.
10$randomSalt = $hasher->make('test');
11
12// Calculate a hash, with a known salt. Should always
13// return 'teH0wLIpW0gyQ'
14$suppliedSalt = $hasher->make('test', ['salt' => 'te']);
15
16// Check if 'test' matches the hash.
17//
18// true
19$isValid = $hasher->check('test', $randomSalt);
20
21// Check if 'test' matches the hash.
22//
23// true
24$isValid = $hasher->check('test', $suppliedSalt);
25
26// Check if $randomSalt need to be rehashed. This will most likely
27// always return true, but it is possible it will return false.
28$needsRehash = $hasher->needsRehash(
29    $randomSalt,
30    ['salt' => 'te']
31);
32
33// Check if the $suppliedSalt needs to be rehashed. This will always
34// return false, unless the salt option is changed.
35$needsRehash = $hasher->needsRehash(
36    $suppliedSalt,
37    ['salt' => 'te']
38);
∎