abmmhasan / otp
Simple but Secure OTP solution!
4.0
2024-04-26 08:30 UTC
Requires
- php: >=8.2
- bacon/bacon-qr-code: ^3.0
- paragonie/constant_time_encoding: ^2.6
- symfony/cache: ^7.0
Requires (Dev)
- symfony/var-dumper: ^7.0
Replaces
README
Simple but Secure Generic OTP, TOTP (RFC6238), HOTP (RFC4226) solution!
Prerequisites
Language: PHP 8.2/+
Library Version | PHP Version |
---|---|
3.x.x/+ | 8.2.x or Higher |
2.x.x | 8.x.x |
1.x.x | 7.x.x |
Installation
composer require infocyph/otp
Why this library?
TOTP & HOTP
- Uses offline QR code generator (no more exposing your secret online)
- Time-safe Base32 encoding (30 seconds validity means 30 seconds)
Generic OTP
- No need to dedicate extra storage/db for User information (just build a unique signature)
Usage
HOTP (RFC4226)
/** * Generate Secret * It will generate secure random secret string */ $secret = \Infocyph\OTP\HOTP::generateSecret(); /** * Get QR Code Image for secret $secret */ // 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'); /** * Get current OTP for a given counter */ $counter = 346; $otp = (new \Infocyph\OTP\HOTP($secret))->getOTP($counter); /** * Verify */ (new \Infocyph\OTP\HOTP($secret))->verify($otp,$counter);
TOTP (RFC6238)
/** * Generate Secret * It will generate secure random secret string */ $secret = \Infocyph\OTP\TOTP::generateSecret(); /** * Get QR Code Image for secret $secret */ // 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'); /** * Get current OTP */ $otp = (new \Infocyph\OTP\TOTP($secret))->getOTP(); // or get OTP for another specified epoch time $otp = (new \Infocyph\OTP\TOTP($secret))->getOTP(1604820275); /** * Verify * * on 3rd parameter it supports, enabling leeway. * if enabled, it will also check with last segment's generated otp */ (new \Infocyph\OTP\TOTP($secret))->verify($otp); // or verify for a specified time (new \Infocyph\OTP\TOTP($secret))->verify($otp, 1604820275);
Generic OTP
/** * Initiate * 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); /** * Generate & get the OTP */ $otp = $otpInstance->generate('an unique signature for a cause'); /** * Verify the OTP * * on 3rd parameter setting false will keep the record till the otp is verified or expired * by default it will keep the record till the key name match or the otp is verified or expired */ $otpInstance->verify('an unique signature for a cause', $otp); /** * Delete the record */ $otpInstance->delete('an unique signature for a cause'); /** * Flush all the existing OTPs (if any) */ $otpInstance->flush()
Note: Generic OTP uses temporary location for storage, make sure you have proper access permission
Support
Having trouble? Create an issue!