TOTP and HOTP objects have the following common methods:
public function at($input)
: generates an OTP at the specified counterpublic function verify($otp, $input, $window)
: verifies if the OTP is valid for the specified input (timestamp, counter...)public function getSecret()
: returns the secretpublic function setSecret($secret)
: sets the secretpublic function getLabel()
: returns the labelpublic function setLabel($label)
: sets the labelpublic function getIssuer()
: returns the issuerpublic function setIssuer($issuer)
: sets the issuerpublic function isIssuerIncludedAsParameter()
: if true, the issuer is also included into the query parameterspublic function setIssuerIncludedAsParameter($issuer_included_as_parameter)
: defines if the issuer is added into the query parameterspublic function getDigits()
: returns the number of digits of OTPspublic function setDigits($digits)
: sets the number of digits of OTPspublic function getDigest()
: returns the digest used to calculate the OTPpublic function setDigest($digest)
: sets the digest used to calculate the OTPpublic function getImage()
: return the URI of in image associated with the OTPpublic function setImage($image)
: sets the URI of in image associated with the OTPpublic function getParameter($parameter)
: returns a custom parameterpublic function getParameters()
: returns all parameterspublic function setParameter($parameter, $value)
: sets a custom parameterpublic function getProvisioningUri()
: returns a provisioning URI to ease integration in applications
This OTP object has a specific method:
public function getCounter()
: returns the current counterpublic function setCounter($counter)
: rset the current counter
This OTP object has a specific method:
public function now()
: return an OTP at the current timestamppublic function getInterval()
: returns the interval (in seconds)public function setInterval($interval)
: sets the interval (in seconds)
Hereafter an example using TOTP:
<?php
use OTPHP\TOTP;
$totp = new TOTP;
$totp->setLabel("alice@google.com")
->setDigits(6)
->setDigest('sha1')
->setInterval(30)
->setSecret("JBSWY3DPEHPK3PXP");
$totp->now(); //e.g. will return '123456'
$totp->verify('123456'); //Will return true.
// 30 seconds later:
$totp->verify('123456'); //Will return false.
And using HOTP:
<?php
use OTPHP\HOTP;
$hotp = new HOTP;
$hotp->setLabel("alice@google.com")
->setDigits(6)
->setDigest('sha1')
->setCounter(1000)
->setSecret("JBSWY3DPEHPK3PXP");
$hotp->at(1000); //e.g. will return '123456'
$hotp->verify('123456', 1000); //Will return true.
$hotp->verify('123456', 1000); //Will return false as the current counter is now 1001.
The method verify
has a windows
parameter. By default, it value is null
. It means that the OTP will be tested at the exact counter/timestamp.
If the value is an integer, the method will try all OTP from counter
to counter+window
.
For example, if the counter
is 1000
and the window 10
, the OTP tested are within 1000
and 1010
.
$hotp->verify('123456', 999); //Will return false
$hotp->verify('123456', 999, 10); //Will return true (1000 is tested)
The window of timestamps goes from - $window * interval + timestamp
to + $window * interval + timestamp
.
For example, if the window
is 5
, the interval 30
and the timestamp 600
, the OTP tested are within 450
and 750
.
$totp->at(1000); //e.g. will return '123456'
$totp->verify('123456'); //Will return true.
// 30 seconds later
$totp->verify('123456'); //Will return false
$totp->verify('123456', null, 1); //Will return true during the next interval
The library works with the Google Authenticator iPhone and Android app, and also includes the ability to generate provisioning URI's for use with the QR Code scanner built into the app.
Google only supports SHA-1 digest algorithm, 30 second interval and 6 digits OTP. Other values for these parameters are ignored by the Google Authenticator application.
<?php
use OTPHP\TOTP;
$totp = new TOTP;
$totp->setLabel("alice@google.com")
->setDigits(6)
->setDigest('sha1')
->setInterval(30)
->setSecret("JBSWY3DPEHPK3PXP");
$totp->getProvisioningUri(); // => 'otpauth://totp/alice%40google.com?secret=JBSWY3DPEHPK3PXP'
You can now create a QRCode using the provisioning URI as input data.
Scan the following barcode with your phone, using Google Authenticator
Now run the following and compare the output
<?php
use OTPHP\TOTP;
$totp = new TOTP;
$totp->setLabel("alice@google.com")
->setDigits(6)
->setDigest('sha1')
->setInterval(30);
->setSecret("JBSWY3DPEHPK3PXP");
echo "Current OTP: ". $totp->now();
The following barcode will not work with Google Authenticator because digest algoritm is not SHA-1, there are 8 digits and counter is not 30 seconds.
Now run the following and compare the output
<?php
use OTPHP\TOTP;
$totp = new TOTP;
$totp->setLabel("alice@google.com")
->setDigits(8)
->setDigest('sha512')
->setInterval(10)
->setSecret("JBSWY3DPEHPK3PXP");
echo "Current OTP: ". $totp->now();
Since version 6.0.0
, OTP object will provide the following additional features
Now you can use any hash algorithm listed by hash_algos()
.
Note that most of applications only support md5
, sha1
, sha256
and sha512
. You must verify that the algorithm you want to use can supported by application your client might use.
<?php
use OTPHP\TOTP;
$totp = new TOTP;
$totp->setLabel("alice@google.com")
->setDigits(6)
->setDigest('ripemd160')
->setInterval(30)
->setSecret("JBSWY3DPEHPK3PXP");
$totp->getProvisioningUri(); // => 'otpauth://totp/alice%40google.com?digest=ripemd160&secret=JBSWY3DPEHPK3PXP'
For example, the application FreeOTP can load images from an URI (image
parameter).
Please note that at the moment, we cannot list applications that support this parameter.
<?php
use OTPHP\TOTP;
$totp = new TOTP;
$totp->setLabel("alice@google.com")
->setDigits(6)
->setDigest('md5')
->setInterval(30)
->setSecret("JBSWY3DPEHPK3PXP")
->setImage('https://foo.bar/otp.png');
$totp->getProvisioningUri(); // => 'otpauth://totp/alice%40google.com?secret=JBSWY3DPEHPK3PXP&image=https%3A%2F%2Ffoo.bar%2Fotp.png'
When you load a QRCode using this input data, the application will try to load the image at https://foo.bar/otp.png
.
OTP objects are able to support custom parameters.
These parameters are available in the provisioning URI or from the method getParameter
.
<?php
use OTPHP\TOTP;
$totp = new TOTP;
$totp->setLabel("alice@google.com")
->setDigits(6)
->setDigest('md5')
->setInterval(30)
->setSecret("JBSWY3DPEHPK3PXP")
->setParameter('foo', 'bar');
$totp->getProvisioningUri(); // => 'otpauth://totp/alice%40google.com?secret=JBSWY3DPEHPK3PXP&foo=bar'
In some cases, you want to load a provisioning URI and get on OTP object. That is why we created a factory.
use OTPHP\Factory;
$otp = Factory::loadFromProvisioningUri('otpauth://totp/alice%40google.com?secret=JBSWY3DPEHPK3PXP&foo=bar');
// The variable $otp is now a valid TOTP object with all parameters set (including custom parameters)