Last active
July 1, 2023 18:13
-
-
Save VottusCode/6e9817fc650cde030e2037c3f9b4a45f to your computer and use it in GitHub Desktop.
Simple implementation of AuthMe SHA256 as a Laravel Facade.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php declare(strict_types=1); | |
namespace App\Facades; | |
use Illuminate\Contracts\Hashing\Hasher; | |
use Illuminate\Support\Facades\Facade; | |
use Illuminate\Support\Str; | |
/** | |
* Hasher implementation that supports | |
* the AuthMe SHA256 hash. | |
* | |
* @package App\Facades | |
* | |
* @author Mia Vališová <valisova@lilianaa.dev> | |
*/ | |
class Hash extends Facade implements Hasher { | |
const SALT_LENGTH = 16; | |
/** | |
* Gets the name of the Facade. | |
* | |
* @return string | |
*/ | |
protected static function getFacadeAccessor() | |
{ | |
return 'shaHash'; | |
} | |
/** | |
* Returns the information about the hash. | |
* | |
* Array shape: | |
* [ | |
* "rawHash" => // the raw hash, | |
* "salt" => // the salt | |
* ] | |
* | |
* Returns null if the hash is invalid. | |
* | |
* @param string $hashedValue | |
* @return array|null | |
*/ | |
public function info($hashedValue): ?array | |
{ | |
$parts = explode('$', $hashedValue); | |
return count($parts) === 4 ? [ | |
"rawHash" => $parts[2], | |
"salt" => $parts[3] | |
] : null; | |
} | |
/** | |
* Makes a hash with a random salt. | |
* | |
* Additionally, you can pass a salt in the | |
* options array. | |
* | |
* Options shape (optional): | |
* [ | |
* "salt" => // Specify the salt | |
* ] | |
* | |
* @param string $value | |
* @param array $options | |
* @return string | |
*/ | |
public function make($value, array $options = []): string | |
{ | |
$salt = !empty($options['salt']) && is_string($options['salt']) ? $options($options['salt']) : ? Str::random(self::SALT_LENGTH); | |
return '$SHA$' . $salt . '$' . hash('sha256', hash('sha256', $value) . $salt); | |
} | |
/** | |
* Checks whether the password matches the hash. | |
* | |
* This is done by hashing the password again with the | |
* same salt that the hash has. If both hashes match, | |
* the password is correct. | |
* | |
* Returns false if the hash is invalid. | |
* | |
* @param string $value | |
* @param string $hashedValue | |
* @param array $options | |
* @return bool | |
*/ | |
public function check($value, $hashedValue, array $options = []): bool | |
{ | |
$split = explode('$', $hashedValue); | |
if (count($split) !== 4) return false; // Invalid hash | |
$hashAndSalt = $split[3]; | |
$salt = array_key_exists("salt", $options) && is_string($options["salt"]) | |
? $options["salt"] | |
: $split[2]; | |
return $hashAndSalt === $this->make($value, [ "salt" => $salt ]); | |
} | |
/** | |
* This function always returns false as the hash | |
* never needs rehash. | |
* | |
* @param string $hashedValue | |
* @param array $options | |
* @return bool | |
*/ | |
public function needsRehash($hashedValue, array $options = []): bool | |
{ | |
return false; | |
} | |
} |
@Cregennan updated to !empty($options['salt']) && is_string($options['salt']) ? $options($options['salt']) : ? Str::random(self::SALT_LENGTH)
, this also ensures that an empty string is not passed in
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There's a small issue in a class - you don't use salt provided by
options
param inmake
.Changing
$salt = Str::random(self::SALT_LENGTH);
to$salt = array_key_exists('salt', $options) ? $options['salt'] : Str::random(self::SALT_LENGTH);
will solve this issue.