CodeCodeStudy
2024-01-12 14:42:55 +08:00
php 的代码,不依赖第三方库
```php
<?php
class TOTP {
private static $base32Map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
private static function base32Decode($in) {
$l = strlen($in);
$n = $bs = 0;
for ($i = 0; $i < $l; $i++) {
$n <<= 5;
$n += stripos(self::$base32Map, $in[$i]);
$bs = ($bs + 5) % 8;
@$out .= $bs < 5 ? chr(($n & (255 << $bs)) >> $bs) : null;
}
return $out;
}
public static function getOTP($secret, $digits = 6, $period = 30, $offset = 0) {
if (strlen($secret) < 16 || strlen($secret) % 8 != 0)
return ['err' => 'length of secret must be a multiple of 8, and at least 16 characters'];
if (preg_match('/[^a-z2-7]/i', $secret) === 1)
return ['err' => 'secret contains non-base32 characters'];
$digits = intval($digits);
if ($digits < 6 || $digits > 8)
return ['err' => 'digits must be 6, 7 or 8'];
$seed = self::base32Decode($secret);
$time = str_pad(pack('N', intval($offset + time() / $period)), 8, "\x00", STR_PAD_LEFT);
$hash = hash_hmac('sha1', $time, $seed, false);
$otp = (hexdec(substr($hash, hexdec($hash[39]) * 2, 8)) & 0x7fffffff) % pow(10, $digits);
return ['otp' => sprintf("%'0{$digits}u", $otp)];
}
}
echo TOTP::getOTP('xxx')['otp'];
```