mirror of
https://github.com/RobThree/TwoFactorAuth.git
synced 2026-08-17 08:00:57 +00:00
Merge branch 'master' into nico-sensitive-attr
* master: add CI4-auth link in README. fix #107 (#123) remove insecure rng providers and remove polyfill for hash_equals (#122) delete files specific to code editors (#120) Exclude useless files from dist archive #103
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
/.github/ export-ignore
|
||||
/demo/ export-ignore
|
||||
/docs/ export-ignore
|
||||
/tests/ export-ignore
|
||||
/testsDependency/ export-ignore
|
||||
/.gitattributes export-ignore
|
||||
/.gitignore export-ignore
|
||||
/.php-cs-fixer.dist.php export-ignore
|
||||
/logo.png export-ignore
|
||||
/multifactorauthforeveryone.png export-ignore
|
||||
/phpstan.neon export-ignore
|
||||
/phpunit.xml export-ignore
|
||||
@@ -19,7 +19,6 @@ You can make use of the included [Endroid](https://robthree.github.io/TwoFactorA
|
||||
|
||||
* Requires PHP version >=8.2
|
||||
* [cURL](http://php.net/manual/en/book.curl.php) when using the provided `QRServerProvider` (default), `ImageChartsQRCodeProvider` or `QRicketProvider` but you can also provide your own QR-code provider.
|
||||
* [random_bytes()](http://php.net/manual/en/function.random-bytes.php), [OpenSSL](http://php.net/manual/en/book.openssl.php) or [Hash](http://php.net/manual/en/book.hash.php) depending on which built-in RNG you use (TwoFactorAuth will try to 'autodetect' and use the best available); however: feel free to provide your own (CS)RNG.
|
||||
|
||||
Optionally, you may need:
|
||||
|
||||
@@ -42,6 +41,7 @@ If you need more in-depth information about the configuration available then you
|
||||
## Integrations
|
||||
|
||||
- [CakePHP 3](https://github.com/andrej-griniuk/cakephp-two-factor-auth)
|
||||
- [CI4-Auth: a user, group, role and permission management library for Codeigniter 4](https://github.com/glewe/ci4-auth)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Name>TwoFactorAuth</Name>
|
||||
<ProjectGuid>{e569f53a-a604-4579-91ce-4e35b27da47b}</ProjectGuid>
|
||||
<RootNamespace>TwoFactorAuth</RootNamespace>
|
||||
<OutputType>Library</OutputType>
|
||||
<ProjectTypeGuids>{A0786B88-2ADB-4C21-ABE8-AA2D79766269}</ProjectTypeGuids>
|
||||
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
||||
<Server>PHPDev</Server>
|
||||
<PublishEvent>None</PublishEvent>
|
||||
<PHPDevAutoPort>True</PHPDevAutoPort>
|
||||
<PHPDevPort>41315</PHPDevPort>
|
||||
<PHPDevHostName>localhost</PHPDevHostName>
|
||||
<IISProjectUrl>http://localhost:41315/</IISProjectUrl>
|
||||
<Runtime>PHP</Runtime>
|
||||
<RuntimeVersion>8.2</RuntimeVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<IncludeDebugInformation>true</IncludeDebugInformation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<IncludeDebugInformation>false</IncludeDebugInformation>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="demo\demo.php" />
|
||||
<Compile Include="demo\loader.php" />
|
||||
<Compile Include="lib\Providers\Qr\BaseHTTPQRCodeProvider.php" />
|
||||
<Compile Include="lib\Providers\Qr\ImageChartsQRCodeProvider.php" />
|
||||
<Compile Include="lib\Providers\Qr\IQRCodeProvider.php" />
|
||||
<Compile Include="lib\Providers\Qr\QRException.php" />
|
||||
<Compile Include="lib\Providers\Qr\QRicketProvider.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\OpenSSLRNGProvider.php" />
|
||||
<Compile Include="lib\Providers\Rng\HashRNGProvider.php" />
|
||||
<Compile Include="lib\Providers\Rng\RNGException.php" />
|
||||
<Compile Include="lib\Providers\Time\HttpTimeProvider.php" />
|
||||
<Compile Include="lib\Providers\Time\ITimeProvider.php" />
|
||||
<Compile Include="lib\Providers\Time\LocalMachineTimeProvider.php" />
|
||||
<Compile Include="lib\Providers\Time\NTPTimeProvider.php" />
|
||||
<Compile Include="lib\Providers\Time\TimeException.php" />
|
||||
<Compile Include="lib\TwoFactorAuth.php" />
|
||||
<Compile Include=".gitignore" />
|
||||
<Compile Include="README.md" />
|
||||
<Compile Include="lib\TwoFactorAuthException.php" />
|
||||
<Compile Include="tests\TwoFactorAuthTest.php" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="lib\" />
|
||||
<Folder Include="lib\Providers\" />
|
||||
<Folder Include="lib\Providers\Time\" />
|
||||
<Folder Include="lib\Providers\Qr\" />
|
||||
<Folder Include="lib\Providers\Rng\" />
|
||||
<Folder Include="demo\" />
|
||||
<Folder Include="tests\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include=".travis.yml" />
|
||||
<Content Include="composer.json" />
|
||||
<Content Include="composer.lock" />
|
||||
<Content Include="logo.png" />
|
||||
<Content Include="multifactorauthforeveryone.png" />
|
||||
<Content Include="LICENSE" />
|
||||
<Content Include="phpunit.xml" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,22 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.30723.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{A0786B88-2ADB-4C21-ABE8-AA2D79766269}") = "TwoFactorAuth", "TwoFactorAuth.phpproj", "{E569F53A-A604-4579-91CE-4E35B27DA47B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E569F53A-A604-4579-91CE-4E35B27DA47B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E569F53A-A604-4579-91CE-4E35B27DA47B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E569F53A-A604-4579-91CE-4E35B27DA47B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E569F53A-A604-4579-91CE-4E35B27DA47B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -61,20 +61,5 @@
|
||||
"test": [
|
||||
"XDEBUG_MODE=coverage phpunit"
|
||||
]
|
||||
},
|
||||
"archive": {
|
||||
"exclude": [
|
||||
"/.github/",
|
||||
"/demo/",
|
||||
"/docs/",
|
||||
"/tests/",
|
||||
"/testsDependency/",
|
||||
"/.gitignore",
|
||||
"/logo.png",
|
||||
"/multifactorauthforeveryone.png",
|
||||
"/phpunit.xml",
|
||||
"/TwoFactorAuth.phpproj",
|
||||
"/TwoFactorAuth.sln"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,15 +21,7 @@ Argument | Default value | Use
|
||||
|
||||
### RNG providers
|
||||
|
||||
This library also comes with some [Random Number Generator (RNG)](https://en.wikipedia.org/wiki/Random_number_generation) providers. The RNG provider generates a number of random bytes and returns these bytes as a string. These values are then used to create the secret. By default (no RNG provider specified) TwoFactorAuth will try to determine the best available RNG provider to use in this order.
|
||||
|
||||
1. [CSRNGProvider](https://github.com/RobThree/TwoFactorAuth/blob/master/lib/Providers/Rng/CSRNGProvider.php) for PHP7+
|
||||
2. [OpenSSLRNGProvider](https://github.com/RobThree/TwoFactorAuth/blob/master/lib/Providers/Rng/OpenSSLRNGProvider.php) where openssl is available
|
||||
3. [HashRNGProvider](https://github.com/RobThree/TwoFactorAuth/blob/master/lib/Providers/Rng/HashRNGProvider.php) **non-cryptographically secure** fallback
|
||||
|
||||
Each of these RNG providers have some constructor arguments that allow you to tweak some of the settings to use when creating the random bytes.
|
||||
|
||||
You can also implement your own by implementing the [`IRNGProvider` interface](https://github.com/RobThree/TwoFactorAuth/blob/master/lib/Providers/Rng/IRNGProvider.php).
|
||||
Should you feel the need to use a CSPRNG different than `random_bytes()`, you can use the `rngprovider` argument of the constructor to provide an object implementing the [`IRNGProvider`](https://github.com/RobThree/TwoFactorAuth/blob/master/lib/Providers/Rng/IRNGProvider.php) interface.
|
||||
|
||||
### Time providers
|
||||
|
||||
|
||||
@@ -13,12 +13,4 @@ class CSRNGProvider implements IRNGProvider
|
||||
{
|
||||
return random_bytes($bytecount); // PHP7+
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCryptographicallySecure(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace RobThree\Auth\Providers\Rng;
|
||||
|
||||
use function in_array;
|
||||
|
||||
class HashRNGProvider implements IRNGProvider
|
||||
{
|
||||
public function __construct(private readonly string $algorithm = 'sha256')
|
||||
{
|
||||
$algos = array_values(hash_algos());
|
||||
if (!in_array($this->algorithm, $algos, true)) {
|
||||
throw new RNGException('Unsupported algorithm specified');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRandomBytes(int $bytecount): string
|
||||
{
|
||||
$result = '';
|
||||
$hash = mt_rand();
|
||||
for ($i = 0; $i < $bytecount; $i++) {
|
||||
$hash = hash($this->algorithm, $hash . mt_rand(), true);
|
||||
$result .= $hash[mt_rand(0, strlen($hash) - 1)];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCryptographicallySecure(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,4 @@ namespace RobThree\Auth\Providers\Rng;
|
||||
interface IRNGProvider
|
||||
{
|
||||
public function getRandomBytes(int $bytecount): string;
|
||||
|
||||
public function isCryptographicallySecure(): bool;
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace RobThree\Auth\Providers\Rng;
|
||||
|
||||
class OpenSSLRNGProvider implements IRNGProvider
|
||||
{
|
||||
public function __construct(private readonly bool $requirestrong = true)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRandomBytes(int $bytecount): string
|
||||
{
|
||||
// will throw an Exception on failure
|
||||
return openssl_random_pseudo_bytes($bytecount, $crypto_strong);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCryptographicallySecure(): bool
|
||||
{
|
||||
return $this->requirestrong;
|
||||
}
|
||||
}
|
||||
+5
-41
@@ -4,12 +4,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace RobThree\Auth;
|
||||
|
||||
use function hash_equals;
|
||||
|
||||
use RobThree\Auth\Providers\Qr\IQRCodeProvider;
|
||||
use RobThree\Auth\Providers\Qr\QRServerProvider;
|
||||
use RobThree\Auth\Providers\Rng\CSRNGProvider;
|
||||
use RobThree\Auth\Providers\Rng\HashRNGProvider;
|
||||
use RobThree\Auth\Providers\Rng\IRNGProvider;
|
||||
use RobThree\Auth\Providers\Rng\OpenSSLRNGProvider;
|
||||
use RobThree\Auth\Providers\Time\HttpTimeProvider;
|
||||
use RobThree\Auth\Providers\Time\ITimeProvider;
|
||||
use RobThree\Auth\Providers\Time\LocalMachineTimeProvider;
|
||||
@@ -52,14 +52,11 @@ class TwoFactorAuth
|
||||
/**
|
||||
* Create a new secret
|
||||
*/
|
||||
public function createSecret(int $bits = 80, bool $requirecryptosecure = true): string
|
||||
public function createSecret(int $bits = 80): string
|
||||
{
|
||||
$secret = '';
|
||||
$bytes = (int)ceil($bits / 5); // We use 5 bits of each byte (since we have a 32-character 'alphabet' / BASE32)
|
||||
$rngprovider = $this->getRngProvider();
|
||||
if ($requirecryptosecure && !$rngprovider->isCryptographicallySecure()) {
|
||||
throw new TwoFactorAuthException('RNG provider is not cryptographically secure');
|
||||
}
|
||||
$rnd = $rngprovider->getRandomBytes($bytes);
|
||||
for ($i = 0; $i < $bytes; $i++) {
|
||||
$secret .= self::$_base32[ord($rnd[$i]) & 31]; //Mask out left 3 bits for 0-31 values
|
||||
@@ -99,7 +96,7 @@ class TwoFactorAuth
|
||||
for ($i = -$discrepancy; $i <= $discrepancy; $i++) {
|
||||
$ts = $timestamp + ($i * $this->period);
|
||||
$slice = $this->getTimeSlice($ts);
|
||||
$timeslice = $this->codeEquals($this->getCode($secret, $ts), $code) ? $slice : $timeslice;
|
||||
$timeslice = hash_equals($this->getCode($secret, $ts), $code) ? $slice : $timeslice;
|
||||
}
|
||||
|
||||
return $timeslice > 0;
|
||||
@@ -175,19 +172,7 @@ class TwoFactorAuth
|
||||
*/
|
||||
public function getRngProvider(): IRNGProvider
|
||||
{
|
||||
if ($this->rngprovider !== null) {
|
||||
return $this->rngprovider;
|
||||
}
|
||||
if (function_exists('random_bytes')) {
|
||||
return $this->rngprovider = new CSRNGProvider();
|
||||
}
|
||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||
return $this->rngprovider = new OpenSSLRNGProvider();
|
||||
}
|
||||
if (function_exists('hash')) {
|
||||
return $this->rngprovider = new HashRNGProvider();
|
||||
}
|
||||
throw new TwoFactorAuthException('Unable to find a suited RNGProvider');
|
||||
return $this->rngprovider ??= new CSRNGProvider();
|
||||
}
|
||||
|
||||
public function getTimeProvider(): ITimeProvider
|
||||
@@ -196,27 +181,6 @@ class TwoFactorAuth
|
||||
return $this->timeprovider ??= new LocalMachineTimeProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* Timing-attack safe comparison of 2 codes (see http://blog.ircmaxell.com/2014/11/its-all-about-time.html)
|
||||
*/
|
||||
private function codeEquals(string $safe, string $user): bool
|
||||
{
|
||||
if (function_exists('hash_equals')) {
|
||||
return hash_equals($safe, $user);
|
||||
}
|
||||
// In general, it's not possible to prevent length leaks. So it's OK to leak the length. The important part is that
|
||||
// we don't leak information about the difference of the two strings.
|
||||
if (strlen($safe) === strlen($user)) {
|
||||
$result = 0;
|
||||
$strlen = strlen($safe);
|
||||
for ($i = 0; $i < $strlen; $i++) {
|
||||
$result |= (ord($safe[$i]) ^ ord($user[$i]));
|
||||
}
|
||||
return $result === 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getTime(?int $time = null): int
|
||||
{
|
||||
return $time ?? $this->getTimeProvider()->getTime();
|
||||
|
||||
@@ -11,19 +11,11 @@ class CSRNGProviderTest extends TestCase
|
||||
{
|
||||
use NeedsRngLengths;
|
||||
|
||||
/**
|
||||
* @requires function random_bytes
|
||||
*/
|
||||
public function testCSRNGProvidersReturnExpectedNumberOfBytes(): void
|
||||
{
|
||||
if (function_exists('random_bytes')) {
|
||||
$rng = new CSRNGProvider();
|
||||
foreach ($this->rngTestLengths as $l) {
|
||||
$this->assertSame($l, strlen($rng->getRandomBytes($l)));
|
||||
}
|
||||
$this->assertTrue($rng->isCryptographicallySecure());
|
||||
} else {
|
||||
$this->expectNotToPerformAssertions();
|
||||
$rng = new CSRNGProvider();
|
||||
foreach ($this->rngTestLengths as $l) {
|
||||
$this->assertSame($l, strlen($rng->getRandomBytes($l)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Providers\Rng;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RobThree\Auth\Providers\Rng\HashRNGProvider;
|
||||
|
||||
class HashRNGProviderTest extends TestCase
|
||||
{
|
||||
use NeedsRngLengths;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testHashRNGProvidersReturnExpectedNumberOfBytes()
|
||||
{
|
||||
$rng = new HashRNGProvider();
|
||||
foreach ($this->rngTestLengths as $l) {
|
||||
$this->assertSame($l, strlen($rng->getRandomBytes($l)));
|
||||
}
|
||||
|
||||
$this->assertFalse($rng->isCryptographicallySecure());
|
||||
}
|
||||
}
|
||||
@@ -7,46 +7,12 @@ namespace Tests\Providers\Rng;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RobThree\Auth\Algorithm;
|
||||
use RobThree\Auth\TwoFactorAuth;
|
||||
use RobThree\Auth\TwoFactorAuthException;
|
||||
|
||||
class IRNGProviderTest extends TestCase
|
||||
{
|
||||
public function testCreateSecretThrowsOnInsecureRNGProvider(): void
|
||||
public function testCreateSecret(): void
|
||||
{
|
||||
$rng = new TestRNGProvider();
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, Algorithm::Sha1, null, $rng);
|
||||
|
||||
$this->expectException(TwoFactorAuthException::class);
|
||||
$tfa->createSecret();
|
||||
}
|
||||
|
||||
public function testCreateSecretOverrideSecureDoesNotThrowOnInsecureRNG(): void
|
||||
{
|
||||
$rng = new TestRNGProvider();
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, Algorithm::Sha1, null, $rng);
|
||||
$this->assertSame('ABCDEFGHIJKLMNOP', $tfa->createSecret(80, false));
|
||||
}
|
||||
|
||||
public function testCreateSecretDoesNotThrowOnSecureRNGProvider(): void
|
||||
{
|
||||
$rng = new TestRNGProvider(true);
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, Algorithm::Sha1, null, $rng);
|
||||
$this->assertSame('ABCDEFGHIJKLMNOP', $tfa->createSecret());
|
||||
}
|
||||
|
||||
public function testCreateSecretGeneratesDesiredAmountOfEntropy(): void
|
||||
{
|
||||
$rng = new TestRNGProvider(true);
|
||||
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, Algorithm::Sha1, null, $rng);
|
||||
$this->assertSame('A', $tfa->createSecret(5));
|
||||
$this->assertSame('AB', $tfa->createSecret(6));
|
||||
$this->assertSame('ABCDEFGHIJKLMNOPQRSTUVWXYZ', $tfa->createSecret(128));
|
||||
$this->assertSame('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(160));
|
||||
$this->assertSame('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(320));
|
||||
$this->assertSame('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567A', $tfa->createSecret(321));
|
||||
$tfa = new TwoFactorAuth('Test', 6, 30, Algorithm::Sha1, null, null);
|
||||
$this->assertIsString($tfa->createSecret());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Providers\Rng;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RobThree\Auth\Providers\Rng\OpenSSLRNGProvider;
|
||||
|
||||
class OpenSSLRNGProviderTest extends TestCase
|
||||
{
|
||||
use NeedsRngLengths;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes()
|
||||
{
|
||||
$rng = new OpenSSLRNGProvider(true);
|
||||
foreach ($this->rngTestLengths as $l) {
|
||||
$this->assertSame($l, strlen($rng->getRandomBytes($l)));
|
||||
}
|
||||
|
||||
$this->assertTrue($rng->isCryptographicallySecure());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testNonStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes()
|
||||
{
|
||||
$rng = new OpenSSLRNGProvider(false);
|
||||
foreach ($this->rngTestLengths as $l) {
|
||||
$this->assertSame($l, strlen($rng->getRandomBytes($l)));
|
||||
}
|
||||
|
||||
$this->assertFalse($rng->isCryptographicallySecure());
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Providers\Rng;
|
||||
|
||||
use RobThree\Auth\Providers\Rng\IRNGProvider;
|
||||
|
||||
class TestRNGProvider implements IRNGProvider
|
||||
{
|
||||
public function __construct(private readonly bool $isSecure = false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRandomBytes(int $bytecount): string
|
||||
{
|
||||
$result = '';
|
||||
|
||||
for ($i = 0; $i < $bytecount; $i++) {
|
||||
$result .= chr($i);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCryptographicallySecure(): bool
|
||||
{
|
||||
return $this->isSecure;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user