From 76f420e6b261eb08eda08f0ab73ba0c8de81afe4 Mon Sep 17 00:00:00 2001 From: Nicolas CARPi Date: Mon, 15 Apr 2024 21:40:19 +0200 Subject: [PATCH 1/8] add SensitiveParameter to sensitive arguments This change adds the PHP attribute SensitiveParameter to the secret holding variables. See: https://www.php.net/manual/en/class.sensitiveparameter This feature is only available in PHP 8.2, so the minimum php version required has been updated. Github Actions now use PHP 8.2 and 8.3 for the tests. The checkout action has been updated to v4, too. Fix issue #118 --- .github/workflows/test-bacon.yml | 4 ++-- .github/workflows/test-endroid.yml | 4 ++-- .github/workflows/test.yml | 4 ++-- CHANGELOG.md | 12 ++++++++++++ README.md | 2 +- TwoFactorAuth.phpproj | 2 +- composer.json | 2 +- lib/TwoFactorAuth.php | 6 +++--- 8 files changed, 24 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test-bacon.yml b/.github/workflows/test-bacon.yml index a4903ad..82faaaf 100644 --- a/.github/workflows/test-bacon.yml +++ b/.github/workflows/test-bacon.yml @@ -10,10 +10,10 @@ jobs: strategy: matrix: - php-version: ['8.1', '8.2'] + php-version: ['8.2', '8.3'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: diff --git a/.github/workflows/test-endroid.yml b/.github/workflows/test-endroid.yml index 23b3867..7312acb 100644 --- a/.github/workflows/test-endroid.yml +++ b/.github/workflows/test-endroid.yml @@ -10,11 +10,11 @@ jobs: strategy: matrix: - php-version: ['8.1', '8.2'] + php-version: ['8.2', '8.3'] endroid-version: ["^3","^4","^5"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a51e67e..e9564dc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,10 +10,10 @@ jobs: strategy: matrix: - php-version: ['8.1', '8.2'] + php-version: ['8.2', '8.3'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 11c01b5..86aa156 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # RobThree\TwoFactorAuth changelog +# Version 3.x + +## Breaking changes + +### PHP Version + +Version 3.x requires at least PHP 8.2. + +### Add SensitiveParameter + +The new attribute SensitiveParameter was added to the code, to prevent accidental leak of secrets in stack traces. + # Version 2.x ## Breaking changes diff --git a/README.md b/README.md index 96f566d..4c8ecd8 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ You can make use of the included [Endroid](https://robthree.github.io/TwoFactorA ## Requirements -* Requires PHP version >=8.1 +* 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. diff --git a/TwoFactorAuth.phpproj b/TwoFactorAuth.phpproj index 2a55b72..2ed68af 100644 --- a/TwoFactorAuth.phpproj +++ b/TwoFactorAuth.phpproj @@ -15,7 +15,7 @@ localhost http://localhost:41315/ PHP - 8.1 + 8.2 true diff --git a/composer.json b/composer.json index a3264a0..52884a0 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "source": "https://github.com/RobThree/TwoFactorAuth" }, "require": { - "php": ">=8.1.0" + "php": ">=8.2.0" }, "require-dev": { "phpunit/phpunit": "^9", diff --git a/lib/TwoFactorAuth.php b/lib/TwoFactorAuth.php index f3f867e..af917e3 100644 --- a/lib/TwoFactorAuth.php +++ b/lib/TwoFactorAuth.php @@ -69,7 +69,7 @@ class TwoFactorAuth /** * Calculate the code with given secret and point in time */ - public function getCode(string $secret, ?int $time = null): string + public function getCode(#[\SensitiveParameter] string $secret, ?int $time = null): string { $secretkey = $this->base32Decode($secret); @@ -107,7 +107,7 @@ class TwoFactorAuth /** * Get data-uri of QRCode */ - public function getQRCodeImageAsDataUri(string $label, string $secret, int $size = 200): string + public function getQRCodeImageAsDataUri(string $label, #[\SensitiveParameter] string $secret, int $size = 200): string { if ($size <= 0) { throw new TwoFactorAuthException('Size must be > 0'); @@ -153,7 +153,7 @@ class TwoFactorAuth /** * Builds a string to be encoded in a QR code */ - public function getQRText(string $label, string $secret): string + public function getQRText(string $label, #[\SensitiveParameter] string $secret): string { return 'otpauth://totp/' . rawurlencode($label) . '?secret=' . rawurlencode($secret) From 061a2a39b48bff88c43c116a1d709102c581e0bf Mon Sep 17 00:00:00 2001 From: Nicolas CARPi Date: Mon, 15 Apr 2024 21:42:23 +0200 Subject: [PATCH 2/8] don't include the sensitive param change in breaking changes section in changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86aa156..8d59041 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,9 @@ Version 3.x requires at least PHP 8.2. -### Add SensitiveParameter +## Other changes -The new attribute SensitiveParameter was added to the code, to prevent accidental leak of secrets in stack traces. +* The new PHP attribute SensitiveParameter was added to the code, to prevent accidental leak of secrets in stack traces. # Version 2.x From bba4c207c2af9009379e18922c50a2991953ac1c Mon Sep 17 00:00:00 2001 From: Nicolas CARPi Date: Mon, 15 Apr 2024 21:43:53 +0200 Subject: [PATCH 3/8] use global import --- lib/TwoFactorAuth.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/TwoFactorAuth.php b/lib/TwoFactorAuth.php index af917e3..0bc5685 100644 --- a/lib/TwoFactorAuth.php +++ b/lib/TwoFactorAuth.php @@ -14,6 +14,7 @@ use RobThree\Auth\Providers\Time\HttpTimeProvider; use RobThree\Auth\Providers\Time\ITimeProvider; use RobThree\Auth\Providers\Time\LocalMachineTimeProvider; use RobThree\Auth\Providers\Time\NTPTimeProvider; +use SensitiveParameter; // Based on / inspired by: https://github.com/PHPGangsta/GoogleAuthenticator // Algorithms, digits, period etc. explained: https://github.com/google/google-authenticator/wiki/Key-Uri-Format @@ -69,7 +70,7 @@ class TwoFactorAuth /** * Calculate the code with given secret and point in time */ - public function getCode(#[\SensitiveParameter] string $secret, ?int $time = null): string + public function getCode(#[SensitiveParameter] string $secret, ?int $time = null): string { $secretkey = $this->base32Decode($secret); @@ -107,7 +108,7 @@ class TwoFactorAuth /** * Get data-uri of QRCode */ - public function getQRCodeImageAsDataUri(string $label, #[\SensitiveParameter] string $secret, int $size = 200): string + public function getQRCodeImageAsDataUri(string $label, #[SensitiveParameter] string $secret, int $size = 200): string { if ($size <= 0) { throw new TwoFactorAuthException('Size must be > 0'); @@ -153,7 +154,7 @@ class TwoFactorAuth /** * Builds a string to be encoded in a QR code */ - public function getQRText(string $label, #[\SensitiveParameter] string $secret): string + public function getQRText(string $label, #[SensitiveParameter] string $secret): string { return 'otpauth://totp/' . rawurlencode($label) . '?secret=' . rawurlencode($secret) From 086a3758ec947da9a8680fe72cd5aba0b762bfa3 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 15 Apr 2024 21:23:58 +0100 Subject: [PATCH 4/8] Exclude useless files from dist archive #103 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cédric Anne --- .gitattributes | 14 ++++++++++++++ composer.json | 15 --------------- 2 files changed, 14 insertions(+), 15 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..40f5f7c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,14 @@ +/.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 +/TwoFactorAuth.phpproj export-ignore +/TwoFactorAuth.sln export-ignore diff --git a/composer.json b/composer.json index a3264a0..25c8135 100644 --- a/composer.json +++ b/composer.json @@ -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" - ] } } From 83c74492702ddd501d48f0b8bb26138386b75908 Mon Sep 17 00:00:00 2001 From: Nicolas CARPi Date: Mon, 15 Apr 2024 22:43:29 +0200 Subject: [PATCH 5/8] use a link in CHANGELOG.md for SensitiveParameter --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d59041..16c097d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ Version 3.x requires at least PHP 8.2. ## Other changes -* The new PHP attribute SensitiveParameter was added to the code, to prevent accidental leak of secrets in stack traces. +* The new PHP attribute [SensitiveParameter](https://www.php.net/manual/en/class.sensitiveparameter.php) was added to the code, to prevent accidental leak of secrets in stack traces. # Version 2.x From 323053bd52fb7e5242ca10b56efa2abbdb5b0387 Mon Sep 17 00:00:00 2001 From: Nicolas CARPi <3043706+NicolasCARPi@users.noreply.github.com> Date: Tue, 16 Apr 2024 15:44:25 +0200 Subject: [PATCH 6/8] delete files specific to code editors (#120) * delete files specific to code editors * remove TwoFactorAuth.phpproj * remove TwoFactorAuth.sln They are not used anymore. See https://github.com/RobThree/TwoFactorAuth/pull/119#issuecomment-2057777036 * remove deleted files from excluded files in composer.json --- .gitattributes | 2 -- TwoFactorAuth.phpproj | 69 ------------------------------------------- TwoFactorAuth.sln | 22 -------------- 3 files changed, 93 deletions(-) delete mode 100644 TwoFactorAuth.phpproj delete mode 100644 TwoFactorAuth.sln diff --git a/.gitattributes b/.gitattributes index 40f5f7c..7f7b718 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,5 +10,3 @@ /multifactorauthforeveryone.png export-ignore /phpstan.neon export-ignore /phpunit.xml export-ignore -/TwoFactorAuth.phpproj export-ignore -/TwoFactorAuth.sln export-ignore diff --git a/TwoFactorAuth.phpproj b/TwoFactorAuth.phpproj deleted file mode 100644 index 2a55b72..0000000 --- a/TwoFactorAuth.phpproj +++ /dev/null @@ -1,69 +0,0 @@ - - - - Debug - TwoFactorAuth - {e569f53a-a604-4579-91ce-4e35b27da47b} - TwoFactorAuth - Library - {A0786B88-2ADB-4C21-ABE8-AA2D79766269} - False - PHPDev - None - True - 41315 - localhost - http://localhost:41315/ - PHP - 8.1 - - - true - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TwoFactorAuth.sln b/TwoFactorAuth.sln deleted file mode 100644 index df901f6..0000000 --- a/TwoFactorAuth.sln +++ /dev/null @@ -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 From 194ecc28ebb3ea01485664e48a20cfecc3103e07 Mon Sep 17 00:00:00 2001 From: Nicolas CARPi <3043706+NicolasCARPi@users.noreply.github.com> Date: Tue, 16 Apr 2024 17:52:51 +0200 Subject: [PATCH 7/8] remove insecure rng providers and remove polyfill for hash_equals (#122) * remove insecure rng providers and remove the openssl provider. We now rely exclusively on random_bytes(), as there are no reasons not to. Fix #121 * remove the isSecure property of the test rng class * remove pointless test rng class we were testing a test class, which didn't make a lot of sense. * Revert "remove pointless test rng class" This reverts commit f6da6bee6db93b47a1a27f666543ea01c167cf5b. * Reapply "remove pointless test rng class" This reverts commit 06220d4a543b759f2d32e14d2f7b5fd61a8fe37c. * assing rng provider to class attribute this also aligns with other providers * remove polyfill for hash_equals --- README.md | 1 - docs/optional-configuration.md | 10 +--- lib/Providers/Rng/CSRNGProvider.php | 8 ---- lib/Providers/Rng/HashRNGProvider.php | 40 ---------------- lib/Providers/Rng/IRNGProvider.php | 2 - lib/Providers/Rng/OpenSSLRNGProvider.php | 29 ------------ lib/TwoFactorAuth.php | 46 ++----------------- tests/Providers/Rng/CSRNGProviderTest.php | 14 ++---- tests/Providers/Rng/HashRNGProviderTest.php | 26 ----------- tests/Providers/Rng/IRNGProviderTest.php | 40 ++-------------- .../Providers/Rng/OpenSSLRNGProviderTest.php | 39 ---------------- tests/Providers/Rng/TestRNGProvider.php | 36 --------------- 12 files changed, 12 insertions(+), 279 deletions(-) delete mode 100644 lib/Providers/Rng/HashRNGProvider.php delete mode 100644 lib/Providers/Rng/OpenSSLRNGProvider.php delete mode 100644 tests/Providers/Rng/HashRNGProviderTest.php delete mode 100644 tests/Providers/Rng/OpenSSLRNGProviderTest.php delete mode 100644 tests/Providers/Rng/TestRNGProvider.php diff --git a/README.md b/README.md index 96f566d..0731499 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,6 @@ You can make use of the included [Endroid](https://robthree.github.io/TwoFactorA * Requires PHP version >=8.1 * [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: diff --git a/docs/optional-configuration.md b/docs/optional-configuration.md index d3e2556..e10a279 100644 --- a/docs/optional-configuration.md +++ b/docs/optional-configuration.md @@ -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 diff --git a/lib/Providers/Rng/CSRNGProvider.php b/lib/Providers/Rng/CSRNGProvider.php index 97351f3..f078575 100644 --- a/lib/Providers/Rng/CSRNGProvider.php +++ b/lib/Providers/Rng/CSRNGProvider.php @@ -13,12 +13,4 @@ class CSRNGProvider implements IRNGProvider { return random_bytes($bytecount); // PHP7+ } - - /** - * {@inheritdoc} - */ - public function isCryptographicallySecure(): bool - { - return true; - } } diff --git a/lib/Providers/Rng/HashRNGProvider.php b/lib/Providers/Rng/HashRNGProvider.php deleted file mode 100644 index 20241da..0000000 --- a/lib/Providers/Rng/HashRNGProvider.php +++ /dev/null @@ -1,40 +0,0 @@ -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; - } -} diff --git a/lib/Providers/Rng/IRNGProvider.php b/lib/Providers/Rng/IRNGProvider.php index ed18453..08b7fa3 100644 --- a/lib/Providers/Rng/IRNGProvider.php +++ b/lib/Providers/Rng/IRNGProvider.php @@ -7,6 +7,4 @@ namespace RobThree\Auth\Providers\Rng; interface IRNGProvider { public function getRandomBytes(int $bytecount): string; - - public function isCryptographicallySecure(): bool; } diff --git a/lib/Providers/Rng/OpenSSLRNGProvider.php b/lib/Providers/Rng/OpenSSLRNGProvider.php deleted file mode 100644 index 4063847..0000000 --- a/lib/Providers/Rng/OpenSSLRNGProvider.php +++ /dev/null @@ -1,29 +0,0 @@ -requirestrong; - } -} diff --git a/lib/TwoFactorAuth.php b/lib/TwoFactorAuth.php index f3f867e..0133448 100644 --- a/lib/TwoFactorAuth.php +++ b/lib/TwoFactorAuth.php @@ -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; @@ -51,14 +51,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 @@ -98,7 +95,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; @@ -174,19 +171,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 @@ -195,27 +180,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(); diff --git a/tests/Providers/Rng/CSRNGProviderTest.php b/tests/Providers/Rng/CSRNGProviderTest.php index 64f66e8..39739e9 100644 --- a/tests/Providers/Rng/CSRNGProviderTest.php +++ b/tests/Providers/Rng/CSRNGProviderTest.php @@ -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))); } } } diff --git a/tests/Providers/Rng/HashRNGProviderTest.php b/tests/Providers/Rng/HashRNGProviderTest.php deleted file mode 100644 index 4a71930..0000000 --- a/tests/Providers/Rng/HashRNGProviderTest.php +++ /dev/null @@ -1,26 +0,0 @@ -rngTestLengths as $l) { - $this->assertSame($l, strlen($rng->getRandomBytes($l))); - } - - $this->assertFalse($rng->isCryptographicallySecure()); - } -} diff --git a/tests/Providers/Rng/IRNGProviderTest.php b/tests/Providers/Rng/IRNGProviderTest.php index 7ff40c8..fd2c742 100644 --- a/tests/Providers/Rng/IRNGProviderTest.php +++ b/tests/Providers/Rng/IRNGProviderTest.php @@ -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()); } } diff --git a/tests/Providers/Rng/OpenSSLRNGProviderTest.php b/tests/Providers/Rng/OpenSSLRNGProviderTest.php deleted file mode 100644 index 368c7cc..0000000 --- a/tests/Providers/Rng/OpenSSLRNGProviderTest.php +++ /dev/null @@ -1,39 +0,0 @@ -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()); - } -} diff --git a/tests/Providers/Rng/TestRNGProvider.php b/tests/Providers/Rng/TestRNGProvider.php deleted file mode 100644 index c166c66..0000000 --- a/tests/Providers/Rng/TestRNGProvider.php +++ /dev/null @@ -1,36 +0,0 @@ -isSecure; - } -} From ecef270ba77739e161228101751195a07ad50b83 Mon Sep 17 00:00:00 2001 From: Nicolas CARPi <3043706+NicolasCARPi@users.noreply.github.com> Date: Tue, 16 Apr 2024 18:16:48 +0200 Subject: [PATCH 8/8] add CI4-auth link in README. fix #107 (#123) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0731499..30f56f6 100644 --- a/README.md +++ b/README.md @@ -41,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