91 lines
2.7 KiB
PHP
91 lines
2.7 KiB
PHP
<?php
|
|
|
|
use Carbon\CarbonImmutable;
|
|
use Illuminate\Support\Facades\Hash;
|
|
|
|
if (! function_exists('utc_now')) {
|
|
function utc_now(): string
|
|
{
|
|
return CarbonImmutable::now('UTC')->toDateTimeString();
|
|
}
|
|
}
|
|
|
|
if (! function_exists('local_date')) {
|
|
function local_date(string $utcDateTime, string $format = 'Y-m-d H:i:s'): string
|
|
{
|
|
try {
|
|
$carbon = CarbonImmutable::parse($utcDateTime)->setTimezone(config('app.timezone'));
|
|
|
|
return $carbon->format($format);
|
|
} catch (Throwable $e) {
|
|
return CarbonImmutable::parse($utcDateTime)->format($format);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! function_exists('user_timezone')) {
|
|
function user_timezone(): string
|
|
{
|
|
return (string) (config('School')->attendance['timezone'] ?? config('app.timezone', 'America/New_York'));
|
|
}
|
|
}
|
|
|
|
if (! function_exists('pbkdf2_hash')) {
|
|
function pbkdf2_hash(string $password, string $algo = 'sha256', int $iterations = 100000, int $length = 64): string
|
|
{
|
|
$salt = random_bytes(16);
|
|
$saltHex = bin2hex($salt);
|
|
$derived = hash_pbkdf2($algo, $password, $salt, $iterations, $length, true);
|
|
$derivedHex = bin2hex($derived);
|
|
|
|
return implode('$', [$algo, $iterations, $saltHex, $derivedHex]);
|
|
}
|
|
}
|
|
|
|
if (! function_exists('pbkdf2_verify')) {
|
|
function pbkdf2_verify(string $password, string $storedHash): bool
|
|
{
|
|
$delim = strpos($storedHash, '$') !== false ? '$' : ':';
|
|
$parts = explode($delim, $storedHash);
|
|
if (count($parts) !== 4) {
|
|
return false;
|
|
}
|
|
|
|
[$algo, $iterations, $saltHex, $derivedHex] = $parts;
|
|
if ($saltHex === '' || $derivedHex === '') {
|
|
return false;
|
|
}
|
|
|
|
$salt = ctype_xdigit($saltHex) ? hex2bin($saltHex) : false;
|
|
$derived = ctype_xdigit($derivedHex) ? hex2bin($derivedHex) : false;
|
|
if ($salt === false || $derived === false) {
|
|
return false;
|
|
}
|
|
|
|
$calc = hash_pbkdf2($algo, $password, $salt, (int) $iterations, strlen($derived), true);
|
|
|
|
return hash_equals($derived, $calc);
|
|
}
|
|
}
|
|
|
|
if (! function_exists('verify_stored_password')) {
|
|
function verify_stored_password(string $password, ?string $storedHash): bool
|
|
{
|
|
if (! $storedHash) {
|
|
return false;
|
|
}
|
|
|
|
$hashInfo = password_get_info($storedHash);
|
|
if (($hashInfo['algo'] ?? null) !== null) {
|
|
return Hash::check($password, $storedHash);
|
|
}
|
|
|
|
$parts = preg_split('/[:$]/', $storedHash);
|
|
if (is_array($parts) && count($parts) === 4) {
|
|
return pbkdf2_verify($password, $storedHash);
|
|
}
|
|
|
|
return Hash::check($password, $storedHash);
|
|
}
|
|
}
|