Upload via GUI (258 Dateien)
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* Minimale TOTP-Implementierung (RFC 6238) ohne externe Abhängigkeiten.
|
||||
* Kompatibel mit Google Authenticator, Authy, etc.
|
||||
*/
|
||||
|
||||
function totp_generate_secret(int $length = 16): string
|
||||
{
|
||||
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
|
||||
$secret = '';
|
||||
$bytes = random_bytes($length);
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$secret .= $chars[ord($bytes[$i]) & 31];
|
||||
}
|
||||
return $secret;
|
||||
}
|
||||
|
||||
function totp_get_code(string $secret, int $timeSlot = 0): string
|
||||
{
|
||||
$time = floor(time() / 30) + $timeSlot;
|
||||
$key = base32_decode($secret);
|
||||
$msg = pack('N*', 0) . pack('N*', $time);
|
||||
$hash = hash_hmac('sha1', $msg, $key, true);
|
||||
$offset = ord($hash[19]) & 0xF;
|
||||
$code = (
|
||||
((ord($hash[$offset]) & 0x7F) << 24) |
|
||||
((ord($hash[$offset + 1]) & 0xFF) << 16) |
|
||||
((ord($hash[$offset + 2]) & 0xFF) << 8) |
|
||||
((ord($hash[$offset + 3]) & 0xFF))
|
||||
) % 1000000;
|
||||
return str_pad((string) $code, 6, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
function totp_verify(string $secret, string $code, int $window = 1): bool
|
||||
{
|
||||
$code = preg_replace('/\s+/', '', $code);
|
||||
if (!preg_match('/^\d{6}$/', $code)) return false;
|
||||
for ($i = -$window; $i <= $window; $i++) {
|
||||
if (hash_equals(totp_get_code($secret, $i), $code)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function totp_qr_url(string $secret, string $email, string $issuer = 'DeskHub'): string
|
||||
{
|
||||
$label = rawurlencode($issuer . ':' . $email);
|
||||
$params = http_build_query([
|
||||
'secret' => $secret,
|
||||
'issuer' => $issuer,
|
||||
'algorithm' => 'SHA1',
|
||||
'digits' => 6,
|
||||
'period' => 30,
|
||||
]);
|
||||
$otpauth = 'otpauth://totp/' . $label . '?' . $params;
|
||||
return 'https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=' . rawurlencode($otpauth);
|
||||
}
|
||||
|
||||
function base32_decode(string $input): string
|
||||
{
|
||||
$map = array_flip(str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'));
|
||||
$input = strtoupper(rtrim($input, '='));
|
||||
$binary = '';
|
||||
$buffer = 0;
|
||||
$bits = 0;
|
||||
foreach (str_split($input) as $char) {
|
||||
if (!isset($map[$char])) continue;
|
||||
$buffer = ($buffer << 5) | $map[$char];
|
||||
$bits += 5;
|
||||
if ($bits >= 8) {
|
||||
$binary .= chr(($buffer >> ($bits - 8)) & 0xFF);
|
||||
$bits -= 8;
|
||||
}
|
||||
}
|
||||
return $binary;
|
||||
}
|
||||
Reference in New Issue
Block a user