Skip to content

Instantly share code, notes, and snippets.

@stmkza
Created August 3, 2018 04:15
Show Gist options
  • Save stmkza/ff9391aa60db6de4c8b202b243c7be8c to your computer and use it in GitHub Desktop.
Save stmkza/ff9391aa60db6de4c8b202b243c7be8c to your computer and use it in GitHub Desktop.
TOTPを実装してみた
<?php
/**
* Created by PhpStorm.
* User: stmkza
* Date: 2018/08/03
* Time: 10:49
*/
function base32_decode(string $data, bool $strict = false): ?string
{
$table = [
'A' => 0,
'B' => 1,
'C' => 2,
'D' => 3,
'E' => 4,
'F' => 5,
'G' => 6,
'H' => 7,
'I' => 8,
'J' => 9,
'K' => 10,
'L' => 11,
'M' => 12,
'N' => 13,
'O' => 14,
'P' => 15,
'Q' => 16,
'R' => 17,
'S' => 18,
'T' => 19,
'U' => 20,
'V' => 21,
'W' => 22,
'X' => 23,
'Y' => 24,
'Z' => 25,
'2' => 26,
'3' => 27,
'4' => 28,
'5' => 29,
'6' => 30,
'7' => 31,
];
$data = strtoupper($data);
$chars = str_split($data, 1);
$state = 0;
$latestChunkSize = 0;
$chunks = [];
foreach ($chars as $ch) {
if (!isset($table[$ch])) {
if ($strict) {
return null;
} else {
continue;
}
}
$state = $state << 5;
$state = $state + $table[$ch];
$latestChunkSize = $latestChunkSize + 5;
if ($latestChunkSize >= 8) {
$latestChunkSize = $latestChunkSize - 8;
$chunks[] = chr(($state & (0xFF << $latestChunkSize)) >> $latestChunkSize);
}
}
return implode($chunks);
}
// key: 入力された6桁の数字
// secret: QRコードを作るときに使ったシークレット
function verifyTotpKey(string $key, string $secret): string
{
$currentTerm = pack('N*', 0) . pack('N*', floor(microtime(true) / 30));
if (mb_strlen($key, 'UTF-8') !== 6 || strlen($key) !== 6) {
return false;
}
$hash = hash_hmac('sha1', $currentTerm, base32_decode($secret, true), true);
$correctKey = sprintf('%06d', (
((ord($hash[(ord($hash[19]) & 0xf) + 3]) & 0xff) << 0) |
((ord($hash[(ord($hash[19]) & 0xf) + 2]) & 0xff) << 8) |
((ord($hash[(ord($hash[19]) & 0xf) + 1]) & 0xff) << 16) |
((ord($hash[(ord($hash[19]) & 0xf) + 0]) & 0x7f) << 24)
) % 1000000);
$result = true;
for ($i = 0; $i < 6; $i++) {
if ((ord($key[$i]) - ord($correctKey[$i])) !== 0) {
$result = false;
}
}
return $result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment