Skip to content

Commit e08b0a5

Browse files
committed
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
2 parents 83c7449 + ecef270 commit e08b0a5

16 files changed

+25
-385
lines changed

.gitattributes

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/.github/ export-ignore
2+
/demo/ export-ignore
3+
/docs/ export-ignore
4+
/tests/ export-ignore
5+
/testsDependency/ export-ignore
6+
/.gitattributes export-ignore
7+
/.gitignore export-ignore
8+
/.php-cs-fixer.dist.php export-ignore
9+
/logo.png export-ignore
10+
/multifactorauthforeveryone.png export-ignore
11+
/phpstan.neon export-ignore
12+
/phpunit.xml export-ignore

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ You can make use of the included [Endroid](https://robthree.github.io/TwoFactorA
1919

2020
* Requires PHP version >=8.2
2121
* [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.
22-
* [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.
2322

2423
Optionally, you may need:
2524

@@ -42,6 +41,7 @@ If you need more in-depth information about the configuration available then you
4241
## Integrations
4342

4443
- [CakePHP 3](https://github.com/andrej-griniuk/cakephp-two-factor-auth)
44+
- [CI4-Auth: a user, group, role and permission management library for Codeigniter 4](https://github.com/glewe/ci4-auth)
4545

4646
## License
4747

TwoFactorAuth.phpproj

-69
This file was deleted.

TwoFactorAuth.sln

-22
This file was deleted.

composer.json

-15
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,5 @@
6161
"test": [
6262
"XDEBUG_MODE=coverage phpunit"
6363
]
64-
},
65-
"archive": {
66-
"exclude": [
67-
"/.github/",
68-
"/demo/",
69-
"/docs/",
70-
"/tests/",
71-
"/testsDependency/",
72-
"/.gitignore",
73-
"/logo.png",
74-
"/multifactorauthforeveryone.png",
75-
"/phpunit.xml",
76-
"/TwoFactorAuth.phpproj",
77-
"/TwoFactorAuth.sln"
78-
]
7964
}
8065
}

docs/optional-configuration.md

+1-9
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,7 @@ Argument | Default value | Use
2121

2222
### RNG providers
2323

24-
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.
25-
26-
1. [CSRNGProvider](https://github.com/RobThree/TwoFactorAuth/blob/master/lib/Providers/Rng/CSRNGProvider.php) for PHP7+
27-
2. [OpenSSLRNGProvider](https://github.com/RobThree/TwoFactorAuth/blob/master/lib/Providers/Rng/OpenSSLRNGProvider.php) where openssl is available
28-
3. [HashRNGProvider](https://github.com/RobThree/TwoFactorAuth/blob/master/lib/Providers/Rng/HashRNGProvider.php) **non-cryptographically secure** fallback
29-
30-
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.
31-
32-
You can also implement your own by implementing the [`IRNGProvider` interface](https://github.com/RobThree/TwoFactorAuth/blob/master/lib/Providers/Rng/IRNGProvider.php).
24+
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.
3325

3426
### Time providers
3527

lib/Providers/Rng/CSRNGProvider.php

-8
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,4 @@ public function getRandomBytes(int $bytecount): string
1313
{
1414
return random_bytes($bytecount); // PHP7+
1515
}
16-
17-
/**
18-
* {@inheritdoc}
19-
*/
20-
public function isCryptographicallySecure(): bool
21-
{
22-
return true;
23-
}
2416
}

lib/Providers/Rng/HashRNGProvider.php

-40
This file was deleted.

lib/Providers/Rng/IRNGProvider.php

-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,4 @@
77
interface IRNGProvider
88
{
99
public function getRandomBytes(int $bytecount): string;
10-
11-
public function isCryptographicallySecure(): bool;
1210
}

lib/Providers/Rng/OpenSSLRNGProvider.php

-29
This file was deleted.

lib/TwoFactorAuth.php

+5-41
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55
namespace RobThree\Auth;
66

7+
use function hash_equals;
8+
79
use RobThree\Auth\Providers\Qr\IQRCodeProvider;
810
use RobThree\Auth\Providers\Qr\QRServerProvider;
911
use RobThree\Auth\Providers\Rng\CSRNGProvider;
10-
use RobThree\Auth\Providers\Rng\HashRNGProvider;
1112
use RobThree\Auth\Providers\Rng\IRNGProvider;
12-
use RobThree\Auth\Providers\Rng\OpenSSLRNGProvider;
1313
use RobThree\Auth\Providers\Time\HttpTimeProvider;
1414
use RobThree\Auth\Providers\Time\ITimeProvider;
1515
use RobThree\Auth\Providers\Time\LocalMachineTimeProvider;
@@ -52,14 +52,11 @@ public function __construct(
5252
/**
5353
* Create a new secret
5454
*/
55-
public function createSecret(int $bits = 80, bool $requirecryptosecure = true): string
55+
public function createSecret(int $bits = 80): string
5656
{
5757
$secret = '';
5858
$bytes = (int)ceil($bits / 5); // We use 5 bits of each byte (since we have a 32-character 'alphabet' / BASE32)
5959
$rngprovider = $this->getRngProvider();
60-
if ($requirecryptosecure && !$rngprovider->isCryptographicallySecure()) {
61-
throw new TwoFactorAuthException('RNG provider is not cryptographically secure');
62-
}
6360
$rnd = $rngprovider->getRandomBytes($bytes);
6461
for ($i = 0; $i < $bytes; $i++) {
6562
$secret .= self::$_base32[ord($rnd[$i]) & 31]; //Mask out left 3 bits for 0-31 values
@@ -99,7 +96,7 @@ public function verifyCode(string $secret, string $code, int $discrepancy = 1, ?
9996
for ($i = -$discrepancy; $i <= $discrepancy; $i++) {
10097
$ts = $timestamp + ($i * $this->period);
10198
$slice = $this->getTimeSlice($ts);
102-
$timeslice = $this->codeEquals($this->getCode($secret, $ts), $code) ? $slice : $timeslice;
99+
$timeslice = hash_equals($this->getCode($secret, $ts), $code) ? $slice : $timeslice;
103100
}
104101

105102
return $timeslice > 0;
@@ -175,19 +172,7 @@ public function getQrCodeProvider(): IQRCodeProvider
175172
*/
176173
public function getRngProvider(): IRNGProvider
177174
{
178-
if ($this->rngprovider !== null) {
179-
return $this->rngprovider;
180-
}
181-
if (function_exists('random_bytes')) {
182-
return $this->rngprovider = new CSRNGProvider();
183-
}
184-
if (function_exists('openssl_random_pseudo_bytes')) {
185-
return $this->rngprovider = new OpenSSLRNGProvider();
186-
}
187-
if (function_exists('hash')) {
188-
return $this->rngprovider = new HashRNGProvider();
189-
}
190-
throw new TwoFactorAuthException('Unable to find a suited RNGProvider');
175+
return $this->rngprovider ??= new CSRNGProvider();
191176
}
192177

193178
public function getTimeProvider(): ITimeProvider
@@ -196,27 +181,6 @@ public function getTimeProvider(): ITimeProvider
196181
return $this->timeprovider ??= new LocalMachineTimeProvider();
197182
}
198183

199-
/**
200-
* Timing-attack safe comparison of 2 codes (see http://blog.ircmaxell.com/2014/11/its-all-about-time.html)
201-
*/
202-
private function codeEquals(string $safe, string $user): bool
203-
{
204-
if (function_exists('hash_equals')) {
205-
return hash_equals($safe, $user);
206-
}
207-
// In general, it's not possible to prevent length leaks. So it's OK to leak the length. The important part is that
208-
// we don't leak information about the difference of the two strings.
209-
if (strlen($safe) === strlen($user)) {
210-
$result = 0;
211-
$strlen = strlen($safe);
212-
for ($i = 0; $i < $strlen; $i++) {
213-
$result |= (ord($safe[$i]) ^ ord($user[$i]));
214-
}
215-
return $result === 0;
216-
}
217-
return false;
218-
}
219-
220184
private function getTime(?int $time = null): int
221185
{
222186
return $time ?? $this->getTimeProvider()->getTime();

tests/Providers/Rng/CSRNGProviderTest.php

+3-11
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,11 @@ class CSRNGProviderTest extends TestCase
1111
{
1212
use NeedsRngLengths;
1313

14-
/**
15-
* @requires function random_bytes
16-
*/
1714
public function testCSRNGProvidersReturnExpectedNumberOfBytes(): void
1815
{
19-
if (function_exists('random_bytes')) {
20-
$rng = new CSRNGProvider();
21-
foreach ($this->rngTestLengths as $l) {
22-
$this->assertSame($l, strlen($rng->getRandomBytes($l)));
23-
}
24-
$this->assertTrue($rng->isCryptographicallySecure());
25-
} else {
26-
$this->expectNotToPerformAssertions();
16+
$rng = new CSRNGProvider();
17+
foreach ($this->rngTestLengths as $l) {
18+
$this->assertSame($l, strlen($rng->getRandomBytes($l)));
2719
}
2820
}
2921
}

tests/Providers/Rng/HashRNGProviderTest.php

-26
This file was deleted.

0 commit comments

Comments
 (0)