简单且安全的通用OTP,OCRA (RFC6287),TOTP (RFC6238) & HOTP (RFC4226)解决方案!
Requires
- php: >=8.2
- bacon/bacon-qr-code: ^3.0
- paragonie/constant_time_encoding: ^3.0
- symfony/cache: ^7.0
Requires (Dev)
- captainhook/captainhook: ^5.23
- laravel/pint: ^1.15
- pestphp/pest: ^2.34
- rector/rector: ^1.0
- symfony/var-dumper: ^7.0
README
简单但安全的AIO OTP解决方案。支持:
- 通用OTP(无存储OTP解决方案)
- TOTP (RFC6238)
- HOTP (RFC4226)
- OCRA (RFC6287)
目录
先决条件
语言:PHP 8.2+
安装
composer require infocyph/otp
为什么选择这个库?
TOTP & HOTP
- 使用离线二维码生成器(不再暴露您的秘密在线)
- 时间安全的Base32编码(30秒有效期意味着30秒)
通用OTP
- 无需为用户信息分配额外的存储/数据库(只需构建一个唯一的签名)
OCRA
- PHP中为数不多的实现之一,易于使用
用法
HOTP (RFC4226)
- 生成密钥
$secret = \Infocyph\OTP\HOTP::generateSecret();
- 为密钥 $secret 生成二维码图像(SVG格式)
// supports digit count in 2nd parameter, recommended to be either 6 or 8 (default 6) (new \Infocyph\OTP\HOTP($secret)) // only required if the counter is being imported from another system or if it is old, & for QR only ->setCounter(3) // default is sha1; Caution: many app (in fact, most of them) have algorithm limitation ->setAlgorithm('sha256') // or `getProvisioningUri` just to get the URI ->getProvisioningUriQR('TestName', 'abc@def.ghi');
getProvisioningUriQR
&getProvisioningUri
接受第三个参数,其中它接受参数数组['algorithm', 'digits', 'period', 'counter']
。您可能会遇到的问题,与URI/图像有关,大多数OTP生成器可能不支持所有这些选项。在这种情况下,传递一个空数组将删除所有可选键,或者您可以选择性地传递所需的参数。此外,您还可以在第四个参数中传递其他参数以反映在URI字符串或QR图像中。但请注意,客户端应用程序可能不支持这些参数。
- 为给定的计数器获取当前的OTP
$counter = 346; $otp = (new \Infocyph\OTP\HOTP($secret))->getOTP($counter);
- 验证
(new \Infocyph\OTP\HOTP($secret))->verify($otp,$counter);
TOTP (RFC6238)
- 生成密钥
$secret = \Infocyph\OTP\TOTP::generateSecret();
- 为密钥 $secret 生成二维码图像(SVG格式)
// supports digit count in 2nd parameter, recommended to be either 6 or 8 (default 6) (new \Infocyph\OTP\TOTP($secret)) // default is sha1; Caution: many app (in fact, most of them) have algorithm limitation ->setAlgorithm('sha256') // or `getProvisioningUri` just to get the URI ->getProvisioningUriQR('TestName', 'abc@def.ghi');
getProvisioningUriQR
&getProvisioningUri
接受第三个参数,其中它接受参数数组['algorithm', 'digits', 'period', 'counter']
。您可能会遇到的问题,与URI/图像有关,大多数OTP生成器可能不支持所有这些选项。在这种情况下,传递一个空数组将删除所有可选键,或者您可以选择性地传递所需的参数。此外,您还可以在第四个参数中传递其他参数以反映在URI字符串或QR图像中。但请注意,客户端应用程序可能不支持这些参数。
- 为给定的计数器获取当前的OTP
$counter = 346; $otp = (new \Infocyph\OTP\TOTP($secret))->getOTP($counter); // or get OTP for another specified epoch time $otp = (new \Infocyph\OTP\TOTP($secret))->getOTP(1604820275);
- 验证
(new \Infocyph\OTP\TOTP($secret))->verify($otp); // or verify for a specified time (new \Infocyph\OTP\TOTP($secret))->verify($otp, 1604820275);
在第三个参数
(bool)
上,它支持启用宽容度。如果启用,它还将检查最后一段生成的OTP。
通用OTP
- 启动
/** * Param 1 is OTP length (default 6) * Param 2 is validity in seconds (default 30) * Param 3 is retry count on failure (default 3) */ $otpInstance = new \Infocyph\OTP\OTP(4, 60, 2);
- 生成并获取OTP
$otp = $otpInstance->generate('an unique signature for a cause');
- 验证OTP
$otpInstance->verify('an unique signature for a cause', $otp);
在第三个参数设置为false的情况下
将保留记录直到OTP被验证或过期
。默认情况下,将保留记录直到密钥名匹配或OTP被验证或过期
- 删除记录
$otpInstance->delete('an unique signature for a cause');
- 刷新所有现有的OTP(如果有的话)
$otpInstance->flush()
通用OTP使用 临时位置 进行存储,请确保您有适当的访问权限
OCRA (RFC6287)
// Example usage: $sharedKey = 'mySecretKey'; // Replace with your actual shared key (binary format) $challenge = '123456'; // Replace with your challenge value $counter = 0; // Replace with the appropriate counter value // Create an OCRA instance $suite = new \Infocyph\OTP\OCRA('OCRA-1:HOTP-SHA1-6:C-QN08', $sharedKey); // If the OCRA suite supports session, set the session $suite->setSession('...'); // If the OCRA suite supports time format, set the time $suite->setTime(new \DateTime()); // If the OCRA suite supports pin, set the pin $suite->setPin('...'); // Generate the OCRA value $suite->generate($challenge, $counter);
构建OCRA套件
根据当前的RFC6287,示例字符串应采用以下格式
OCRA-1:HOTP-SHA1-6:C-QN08-PSHA1
OCRA-1:HOTP-
固定为当前文档。
- SHA1是加密哈希函数。(支持的:SHA1,SHA256,SHA512)
- 6是生成OTP的位数。(支持的:0,4-10)
- C表示计数器支持(可选)
- QN08表示模式(可以是QNxx,QAxx,QHxx之一)
- 下一部分是可选的,有些复杂
- PSHA1表示用于PIN支持的哈希函数(可以是PSHA1,PSHA256,PSHA512之一)
- S(不在示例中)表示会话长度(3位数)
- T(不在示例中)表示时间格式,如下表所示
支持
遇到麻烦?创建一个问题!
参考资料
- HOTP (RFC4226): https://tools.ietf.org/html/rfc4226
- TOTP (RFC6238): https://tools.ietf.org/html/rfc6238
- OCRA (RFC6287): https://tools.ietf.org/html/rfc6287