mirror of
https://github.com/RobThree/TwoFactorAuth.git
synced 2026-08-21 16:11:48 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f546c73537 | |||
| c94fcd83d8 | |||
| 856167c950 |
@@ -81,7 +81,7 @@ When outputting a QR-code you can choose a `$label` for the user (which, when en
|
|||||||
|
|
||||||
### Step 2: Verify secret shared key
|
### Step 2: Verify secret shared key
|
||||||
|
|
||||||
When the code is added to the app, the app will be ready to start generating codes which 'expire' each '`$period`' number of seconds. To make sure the secret was entered, or scanned, correctly you need to verify this by having the user enter a generated code. To check if the generated code is valid you call the `verifyCode()` method:
|
When the shared secret is added to the app, the app will be ready to start generating codes which 'expire' each '`$period`' number of seconds. To make sure the secret was entered, or scanned, correctly you need to verify this by having the user enter a generated code. To check if the generated code is valid you call the `verifyCode()` method:
|
||||||
|
|
||||||
````php
|
````php
|
||||||
// Verify code
|
// Verify code
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
<Compile Include="lib\Providers\Qr\QRException.php" />
|
<Compile Include="lib\Providers\Qr\QRException.php" />
|
||||||
<Compile Include="lib\Providers\Qr\QRicketProvider.php" />
|
<Compile Include="lib\Providers\Qr\QRicketProvider.php" />
|
||||||
<Compile Include="lib\Providers\Qr\QRServerProvider.php" />
|
<Compile Include="lib\Providers\Qr\QRServerProvider.php" />
|
||||||
|
<Compile Include="lib\Providers\Rng\CSRNGProvider.php" />
|
||||||
<Compile Include="lib\Providers\Rng\IRNGProvider.php" />
|
<Compile Include="lib\Providers\Rng\IRNGProvider.php" />
|
||||||
<Compile Include="lib\Providers\Rng\MCryptRNGProvider.php" />
|
<Compile Include="lib\Providers\Rng\MCryptRNGProvider.php" />
|
||||||
<Compile Include="lib\Providers\Rng\OpenSSLRNGProvider.php" />
|
<Compile Include="lib\Providers\Rng\OpenSSLRNGProvider.php" />
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "robthree/twofactorauth",
|
"name": "robthree/twofactorauth",
|
||||||
"description": "Two Factor Authentication",
|
"description": "Two Factor Authentication",
|
||||||
"version": "1.3",
|
"version": "1.4",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"keywords": [ "Authentication", "Two Factor Authentication", "Multi Factor Authentication", "TFA", "MFA", "PHP", "Authenticator", "Authy" ],
|
"keywords": [ "Authentication", "Two Factor Authentication", "Multi Factor Authentication", "TFA", "MFA", "PHP", "Authenticator", "Authy" ],
|
||||||
"homepage": "https://github.com/RobThree/TwoFactorAuth",
|
"homepage": "https://github.com/RobThree/TwoFactorAuth",
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ class QRServerProvider extends BaseHTTPQRCodeProvider
|
|||||||
case 'eps':
|
case 'eps':
|
||||||
return 'application/postscript';
|
return 'application/postscript';
|
||||||
}
|
}
|
||||||
|
throw new QRException(sprintf('Unknown MIME-type: %s', $this->format));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getQRCodeImage($qrtext, $size)
|
public function getQRCodeImage($qrtext, $size)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class QRicketProvider extends BaseHTTPQRCodeProvider
|
|||||||
case 'j':
|
case 'j':
|
||||||
return 'image/jpeg';
|
return 'image/jpeg';
|
||||||
}
|
}
|
||||||
|
throw new QRException(sprintf('Unknown MIME-type: %s', $this->format));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getQRCodeImage($qrtext, $size)
|
public function getQRCodeImage($qrtext, $size)
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RobThree\Auth\Providers\Rng;
|
||||||
|
|
||||||
|
class CSRNGProvider implements IRNGProvider
|
||||||
|
{
|
||||||
|
public function getRandomBytes($bytecount) {
|
||||||
|
return random_bytes($bytecount); // PHP7+
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isCryptographicallySecure() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,7 +45,9 @@ class TwoFactorAuth
|
|||||||
|
|
||||||
// Try to find best available RNG provider if none was specified
|
// Try to find best available RNG provider if none was specified
|
||||||
if ($rngprovider==null) {
|
if ($rngprovider==null) {
|
||||||
if (function_exists('mcrypt_create_iv')) {
|
if (function_exists('random_bytes')) {
|
||||||
|
$rngprovider = new Providers\Rng\CSRNGProvider();
|
||||||
|
} elseif (function_exists('mcrypt_create_iv')) {
|
||||||
$rngprovider = new Providers\Rng\MCryptRNGProvider();
|
$rngprovider = new Providers\Rng\MCryptRNGProvider();
|
||||||
} elseif (function_exists('openssl_random_pseudo_bytes')) {
|
} elseif (function_exists('openssl_random_pseudo_bytes')) {
|
||||||
$rngprovider = new Providers\Rng\OpenSSLRNGProvider();
|
$rngprovider = new Providers\Rng\OpenSSLRNGProvider();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ require_once 'lib/Providers/Qr/GoogleQRCodeProvider.php';
|
|||||||
|
|
||||||
require_once 'lib/Providers/Rng/IRNGProvider.php';
|
require_once 'lib/Providers/Rng/IRNGProvider.php';
|
||||||
require_once 'lib/Providers/Rng/RNGException.php';
|
require_once 'lib/Providers/Rng/RNGException.php';
|
||||||
|
require_once 'lib/Providers/Rng/CSRNGProvider.php';
|
||||||
require_once 'lib/Providers/Rng/MCryptRNGProvider.php';
|
require_once 'lib/Providers/Rng/MCryptRNGProvider.php';
|
||||||
require_once 'lib/Providers/Rng/OpenSSLRNGProvider.php';
|
require_once 'lib/Providers/Rng/OpenSSLRNGProvider.php';
|
||||||
require_once 'lib/Providers/Rng/HashRNGProvider.php';
|
require_once 'lib/Providers/Rng/HashRNGProvider.php';
|
||||||
@@ -24,7 +25,7 @@ class TwoFactorAuthTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testConstructorThrowsOnInvalidDigits() {
|
public function testConstructorThrowsOnInvalidDigits() {
|
||||||
|
|
||||||
$tfa = new TwoFactorAuth('Test', 0);
|
new TwoFactorAuth('Test', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,7 +33,7 @@ class TwoFactorAuthTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testConstructorThrowsOnInvalidPeriod() {
|
public function testConstructorThrowsOnInvalidPeriod() {
|
||||||
|
|
||||||
$tfa = new TwoFactorAuth('Test', 6, 0);
|
new TwoFactorAuth('Test', 6, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,7 +41,7 @@ class TwoFactorAuthTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testConstructorThrowsOnInvalidAlgorithm() {
|
public function testConstructorThrowsOnInvalidAlgorithm() {
|
||||||
|
|
||||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'xxx');
|
new TwoFactorAuth('Test', 6, 30, 'xxx');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +49,7 @@ class TwoFactorAuthTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testConstructorThrowsOnQrProviderNotImplementingInterface() {
|
public function testConstructorThrowsOnQrProviderNotImplementingInterface() {
|
||||||
|
|
||||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', new stdClass());
|
new TwoFactorAuth('Test', 6, 30, 'sha1', new stdClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,7 +57,7 @@ class TwoFactorAuthTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testConstructorThrowsOnRngProviderNotImplementingInterface() {
|
public function testConstructorThrowsOnRngProviderNotImplementingInterface() {
|
||||||
|
|
||||||
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, new stdClass());
|
new TwoFactorAuth('Test', 6, 30, 'sha1', null, new stdClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetCodeReturnsCorrectResults() {
|
public function testGetCodeReturnsCorrectResults() {
|
||||||
@@ -147,7 +148,7 @@ class TwoFactorAuthTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetCodeThrowsOnInvalidBase32String1() {
|
public function testGetCodeThrowsOnInvalidBase32String1() {
|
||||||
$tfa = new TwoFactorAuth('Test');
|
$tfa = new TwoFactorAuth('Test');
|
||||||
$result = $tfa->getCode('FOO1BAR8BAZ9'); //1, 8 & 9 are invalid chars
|
$tfa->getCode('FOO1BAR8BAZ9'); //1, 8 & 9 are invalid chars
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -155,7 +156,7 @@ class TwoFactorAuthTest extends PHPUnit_Framework_TestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetCodeThrowsOnInvalidBase32String2() {
|
public function testGetCodeThrowsOnInvalidBase32String2() {
|
||||||
$tfa = new TwoFactorAuth('Test');
|
$tfa = new TwoFactorAuth('Test');
|
||||||
$result = $tfa->getCode('mzxw6==='); //Lowercase
|
$tfa->getCode('mzxw6==='); //Lowercase
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testKnownBase32DecodeTestVectors() {
|
public function testKnownBase32DecodeTestVectors() {
|
||||||
@@ -242,7 +243,62 @@ class TwoFactorAuthTest extends PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals('47863826', $tfa->getCode($secret, 20000000000));
|
$this->assertEquals('47863826', $tfa->getCode($secret, 20000000000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires function random_bytes
|
||||||
|
*/
|
||||||
|
public function testCSRNGProvidersReturnExpectedNumberOfBytes() {
|
||||||
|
$rng = new \RobThree\Auth\Providers\Rng\CSRNGProvider();
|
||||||
|
foreach ($this->getRngTestLengths() as $l)
|
||||||
|
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||||
|
$this->assertEquals(true, $rng->isCryptographicallySecure());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires function hash_algos
|
||||||
|
* @requires function hash
|
||||||
|
*/
|
||||||
|
public function testHashRNGProvidersReturnExpectedNumberOfBytes() {
|
||||||
|
$rng = new \RobThree\Auth\Providers\Rng\HashRNGProvider();
|
||||||
|
foreach ($this->getRngTestLengths() as $l)
|
||||||
|
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||||
|
$this->assertEquals(false, $rng->isCryptographicallySecure());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires function mcrypt_create_iv
|
||||||
|
*/
|
||||||
|
public function testMCryptRNGProvidersReturnExpectedNumberOfBytes() {
|
||||||
|
$rng = new \RobThree\Auth\Providers\Rng\MCryptRNGProvider();
|
||||||
|
foreach ($this->getRngTestLengths() as $l)
|
||||||
|
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||||
|
$this->assertEquals(true, $rng->isCryptographicallySecure());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires function openssl_random_pseudo_bytes
|
||||||
|
*/
|
||||||
|
public function testStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes() {
|
||||||
|
$rng = new \RobThree\Auth\Providers\Rng\OpenSSLRNGProvider(true);
|
||||||
|
foreach ($this->getRngTestLengths() as $l)
|
||||||
|
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||||
|
$this->assertEquals(true, $rng->isCryptographicallySecure());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires function openssl_random_pseudo_bytes
|
||||||
|
*/
|
||||||
|
public function testNonStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes() {
|
||||||
|
$rng = new \RobThree\Auth\Providers\Rng\OpenSSLRNGProvider(false);
|
||||||
|
foreach ($this->getRngTestLengths() as $l)
|
||||||
|
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
|
||||||
|
$this->assertEquals(false, $rng->isCryptographicallySecure());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function getRngTestLengths() {
|
||||||
|
return array(1, 16, 32, 256);
|
||||||
|
}
|
||||||
|
|
||||||
private function DecodeDataUri($datauri) {
|
private function DecodeDataUri($datauri) {
|
||||||
if (preg_match('/data:(?P<mimetype>[\w\.\-\/]+);(?P<encoding>\w+),(?P<data>.*)/', $datauri, $m) === 1) {
|
if (preg_match('/data:(?P<mimetype>[\w\.\-\/]+);(?P<encoding>\w+),(?P<data>.*)/', $datauri, $m) === 1) {
|
||||||
return array(
|
return array(
|
||||||
|
|||||||
Reference in New Issue
Block a user