当前位置:首页 > PHP

php实现TOTP

2026-01-30 03:08:34PHP

TOTP 简介

TOTP(Time-Based One-Time Password)是基于时间的一次性密码算法,常用于双因素认证(2FA)。其核心是结合共享密钥和当前时间戳生成动态密码,通常每30秒更新一次。

实现步骤

安装依赖库 确保已安装 PHP 的 hash_hmacbase64_decode 函数支持。推荐使用 Base32 编码库处理密钥(如 spomky-labs/base32):

composer require spomky-labs/base32

生成共享密钥 使用 Base32 编码生成一个随机密钥:

use Base32\Base32;
$secret = Base32::encode(random_bytes(10)); // 16字符的Base32密钥

计算时间窗口 TOTP 以30秒为一个时间窗口(Unix时间戳除以30取整):

$timestamp = time();
$timeWindow = floor($timestamp / 30);

生成HMAC-SHA1哈希 使用 hash_hmac 生成密钥和时间的哈希:

$hash = hash_hmac('sha1', pack('J', $timeWindow), Base32::decode($secret), true);

动态截断(DT) 取哈希最后一个字节的低4位作为偏移量,从该偏移量开始截取4字节:

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

生成6位数字密码 将截取的二进制数据转换为无符号整数,取最后6位:

php实现TOTP

$otp = (unpack('N', $binary)[1] & 0x7FFFFFFF) % 1000000;
$otp = str_pad($otp, 6, '0', STR_PAD_LEFT);

完整代码示例

use Base32\Base32;

function generateTOTP($secret, $timestamp = null) {
    $timestamp = $timestamp ?? time();
    $timeWindow = floor($timestamp / 30);
    $binarySecret = Base32::decode($secret);

    $hash = hash_hmac('sha1', pack('J', $timeWindow), $binarySecret, true);
    $offset = ord(substr($hash, -1)) & 0x0F;
    $binary = substr($hash, $offset, 4);

    $otp = (unpack('N', $binary)[1] & 0x7FFFFFFF) % 1000000;
    return str_pad($otp, 6, '0', STR_PAD_LEFT);
}

// 使用示例
$secret = Base32::encode(random_bytes(10));
$otp = generateTOTP($secret);
echo "TOTP: $otp (Secret: $secret)";

验证注意事项

  • 时间同步:服务器和客户端时间需同步(NTP协议推荐)。
  • 容错窗口:验证时可检查前后1-2个时间窗口的密码以应对时钟偏差。
  • 密钥存储:共享密钥需安全存储(如加密数据库)。

通过上述步骤可实现符合 RFC 6238 标准的 TOTP 生成器。

标签: phpTOTP
分享给朋友:

相关文章

php实现文件下载

php实现文件下载

PHP 实现文件下载的方法 使用 header() 函数强制下载 设置正确的 HTTP 头信息,强制浏览器下载文件而不是直接打开。 $file = 'path/to/file.pdf'; if (f…

php 实现购物车

php 实现购物车

PHP 实现购物车功能 购物车功能是电子商务网站的核心部分,可以通过 PHP 和 Session 或数据库来实现。以下是两种常见的实现方式: 使用 Session 存储购物车数据 Sessi…

php验证码的实现

php验证码的实现

PHP 验证码实现方法 使用 GD 库生成基础验证码 创建画布并生成随机字符串作为验证码内容: session_start(); $width = 120; $height = 40; $image…

php实现文件的下载

php实现文件的下载

PHP 实现文件下载的方法 在 PHP 中实现文件下载功能通常需要设置正确的 HTTP 头信息,并输出文件内容。以下是几种常见的实现方式: 使用 header() 函数强制下载 通过设置 Conte…

php实现下载

php实现下载

PHP实现文件下载 使用PHP实现文件下载可以通过设置HTTP头部信息强制浏览器下载文件而非直接打开。以下是几种常见的方法: 方法一:直接输出文件内容 $file_path = 'path/to/…

php 实现单链表

php 实现单链表

单链表的基本概念 单链表是一种线性数据结构,由节点组成,每个节点包含数据域和指向下一个节点的指针域。链表的头节点是访问整个链表的入口。 单链表的节点类实现 在PHP中,可以通过类来定义链表节点。每个…