php实现动态口令
PHP 实现动态口令(OTP)的方法
动态口令(One-Time Password, OTP)是一种一次性使用的密码,常用于双因素认证(2FA)。以下是几种常见的实现方法:
基于时间的一次性密码(TOTP)
TOTP(Time-based One-Time Password)是基于时间和共享密钥生成的一次性密码。以下是实现步骤:
-
安装依赖库
使用spomky-labs/otphp库(推荐):composer require spomky-labs/otphp -
生成 TOTP 密钥
use OTPHP\TOTP; $totp = TOTP::create(); $secret = $totp->getSecret(); // 保存此密钥用于验证 -
生成动态口令
$otpCode = $totp->now(); // 获取当前动态口令 -
验证动态口令
$isValid = $totp->verify($userInputCode);
基于 HMAC 的一次性密码(HOTP)
HOTP(HMAC-based One-Time Password)是基于计数器的一次性密码。实现方法如下:
-
安装依赖库
同样使用spomky-labs/otphp:composer require spomky-labs/otphp -
生成 HOTP 密钥
use OTPHP\HOTP; $hotp = HOTP::create(); $secret = $hotp->getSecret(); // 保存此密钥 -
生成动态口令
$counter = 1; // 计数器需递增并保存 $otpCode = $hotp->at($counter); -
验证动态口令
$isValid = $hotp->verify($userInputCode, $counter);
使用 Google Authenticator 兼容方案
-
生成二维码供用户扫描
$totp = TOTP::create(); $qrCodeUri = $totp->getProvisioningUri('user@example.com', 'MyApp'); // 输出为二维码图片,用户可用 Google Authenticator 扫描 -
验证用户输入
$totp = TOTP::createFromSecret($savedSecret); $isValid = $totp->verify($userInputCode);
自定义实现(不推荐)
如需手动实现 TOTP 逻辑(仅用于学习):
-
生成密钥
$secret = bin2hex(random_bytes(10)); // 20字符十六进制密钥 -
计算动态口令
$timeStep = 30; // 时间步长(秒) $timestamp = floor(time() / $timeStep); $hash = hash_hmac('sha1', pack('J', $timestamp), hex2bin($secret)); $offset = hexdec(substr($hash, -1)) & 0x0F; $otp = (hexdec(substr($hash, $offset * 2, 8)) & 0x7FFFFFFF) % 1000000; $otpCode = str_pad($otp, 6, '0', STR_PAD_LEFT);
注意事项
- 密钥需安全存储,建议加密后存入数据库。
- 时间同步至关重要,服务器时间需与客户端(如手机)保持一致。
- 可设置容差窗口(如 ±1 个时间步长)以缓解时间偏差问题。
以上方法均符合 RFC 4226 (HOTP) 和 RFC 6238 (TOTP) 标准,兼容主流认证应用(如 Google Authenticator、Microsoft Authenticator)。







