TOTP: PHP Token Generator

TOTP: PHP Token Generator

Da ich für ein Projekt einen TOTP Generator mittels PHP einbinden wollte und keine weitere Bibliothek installieren wollte, habe ich in Zusammenarbeit mit ChatGPT ein TOTP Token Generator gebastelt.

Fangen wir vorne an. Als erstes braucht man die Variablen für den späteren Token.

$label = "Simon Zipperling";
$issuer = "simon.zipperling.net";
$secret = "55IY2MYYPWKWLEQR2LKLRTXSGYZCBIUWECIHXX36B4YHQGCELD7EB3RU6RZXRI4CBQY2PEDVVAGTGGCAE6M63FOCI6QQY6OWLR7L2DQ";
$expiry = 90;
$length = 6;
$algorithm = "sha512";

Bei $expire kann die zuvor verhandelte Zeit eingestellt werden; Bei $lenght die Länge des Tokens und bei $alogorith der zu verwendende Algorithmus. $secret gibt den geheimen Schlüssel weiter.

Für die spätere TOTP Funktion brauchen wir aber noch eine Zusatzfunktion.

  function base32_decode($base32) {
    $base32chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
    $base32charsFlipped = array_flip(str_split($base32chars));

    $output = '';
    $v = 0;
    $vbits = 0;

    for ($i = 0, $j = strlen($base32); $i < $j; $i++) {
        $v <<= 5;
        if ($base32[$i] == ' ') continue;
        $v += $base32charsFlipped[$base32[$i]];
        $vbits += 5;

        if ($vbits >= 8) {
            $vbits -= 8;
            $output .= chr(($v & (0xFF << $vbits)) >> $vbits);
        }
    }

    return $output;
}

Diese Funktion dekodiert die Base32 aus dem Secret.

function generateToken($secret, $length = 6, $expiry = 30, $algorithm = "sha1") {
    $time = floor(time() / $expiry);
    $data = pack('J', $time);

    $secret = base32_decode($secret);
    $hash = hash_hmac($algorithm, $data, $secret, true);

    $offset = ord(substr($hash, -1)) & 0x0F;
    $truncatedHash = substr($hash, $offset, 4);

    $code = unpack('N', $truncatedHash)[1];
    $code = $code & 0x7FFFFFFF;

    $code = str_pad($code % pow(10, $length), $length, '0', STR_PAD_LEFT);

    return $code;
}

Diese Funktion erstellt nun den eigentlichen TOTP Token. Dieser kann mit diesem Aufruf benutzt werden:

$token = generateToken("55IY2MYYPWKWLEQR2LKLRTXSGYZCBIUWECIHXX36B4YHQGCELD7EB3RU6RZXRI4CBQY2PEDVVAGTGGCAE6M63FOCI6QQY6OWLR7L2DQ", 6, 30, "sha1");

echo $token;