aboutsummaryrefslogtreecommitdiff
path: root/vendor/spomky-labs/otphp/src/HOTP.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/spomky-labs/otphp/src/HOTP.php')
-rw-r--r--vendor/spomky-labs/otphp/src/HOTP.php128
1 files changed, 81 insertions, 47 deletions
diff --git a/vendor/spomky-labs/otphp/src/HOTP.php b/vendor/spomky-labs/otphp/src/HOTP.php
index a2f4a2395..835de35f3 100644
--- a/vendor/spomky-labs/otphp/src/HOTP.php
+++ b/vendor/spomky-labs/otphp/src/HOTP.php
@@ -2,60 +2,78 @@
declare(strict_types=1);
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2014-2019 Spomky-Labs
- *
- * This software may be modified and distributed under the terms
- * of the MIT license. See the LICENSE file for details.
- */
-
namespace OTPHP;
-use Assert\Assertion;
+use InvalidArgumentException;
+use function is_int;
+/**
+ * @see \OTPHP\Test\HOTPTest
+ */
final class HOTP extends OTP implements HOTPInterface
{
- protected function __construct(?string $secret, int $counter, string $digest, int $digits)
- {
- parent::__construct($secret, $digest, $digits);
- $this->setCounter($counter);
+ private const DEFAULT_WINDOW = 0;
+
+ public static function create(
+ null|string $secret = null,
+ int $counter = self::DEFAULT_COUNTER,
+ string $digest = self::DEFAULT_DIGEST,
+ int $digits = self::DEFAULT_DIGITS
+ ): self {
+ $htop = $secret !== null
+ ? self::createFromSecret($secret)
+ : self::generate()
+ ;
+ $htop->setCounter($counter);
+ $htop->setDigest($digest);
+ $htop->setDigits($digits);
+
+ return $htop;
}
- public static function create(?string $secret = null, int $counter = 0, string $digest = 'sha1', int $digits = 6): HOTPInterface
+ public static function createFromSecret(string $secret): self
{
- return new self($secret, $counter, $digest, $digits);
+ $htop = new self($secret);
+ $htop->setCounter(self::DEFAULT_COUNTER);
+ $htop->setDigest(self::DEFAULT_DIGEST);
+ $htop->setDigits(self::DEFAULT_DIGITS);
+
+ return $htop;
}
- protected function setCounter(int $counter): void
+ public static function generate(): self
{
- $this->setParameter('counter', $counter);
+ return self::createFromSecret(self::generateSecret());
}
+ /**
+ * @return 0|positive-int
+ */
public function getCounter(): int
{
- return $this->getParameter('counter');
- }
+ $value = $this->getParameter('counter');
+ (is_int($value) && $value >= 0) || throw new InvalidArgumentException('Invalid "counter" parameter.');
- private function updateCounter(int $counter): void
- {
- $this->setCounter($counter);
+ return $value;
}
public function getProvisioningUri(): string
{
- return $this->generateURI('hotp', ['counter' => $this->getCounter()]);
+ return $this->generateURI('hotp', [
+ 'counter' => $this->getCounter(),
+ ]);
}
/**
* If the counter is not provided, the OTP is verified at the actual counter.
+ *
+ * @param null|0|positive-int $counter
*/
- public function verify(string $otp, ?int $counter = null, ?int $window = null): bool
+ public function verify(string $otp, null|int $counter = null, null|int $window = null): bool
{
- Assertion::greaterOrEqualThan($counter, 0, 'The counter must be at least 0.');
+ $counter >= 0 || throw new InvalidArgumentException('The counter must be at least 0.');
- if (null === $counter) {
+ if ($counter === null) {
$counter = $this->getCounter();
} elseif ($counter < $this->getCounter()) {
return false;
@@ -64,12 +82,45 @@ final class HOTP extends OTP implements HOTPInterface
return $this->verifyOtpWithWindow($otp, $counter, $window);
}
- private function getWindow(?int $window): int
+ public function setCounter(int $counter): void
+ {
+ $this->setParameter('counter', $counter);
+ }
+
+ /**
+ * @return array<non-empty-string, callable>
+ */
+ protected function getParameterMap(): array
+ {
+ return [...parent::getParameterMap(), ...[
+ 'counter' => static function (mixed $value): int {
+ $value = (int) $value;
+ $value >= 0 || throw new InvalidArgumentException('Counter must be at least 0.');
+
+ return $value;
+ },
+ ]];
+ }
+
+ private function updateCounter(int $counter): void
+ {
+ $this->setCounter($counter);
+ }
+
+ /**
+ * @param null|0|positive-int $window
+ */
+ private function getWindow(null|int $window): int
{
- return abs($window ?? 0);
+ return abs($window ?? self::DEFAULT_WINDOW);
}
- private function verifyOtpWithWindow(string $otp, int $counter, ?int $window): bool
+ /**
+ * @param non-empty-string $otp
+ * @param 0|positive-int $counter
+ * @param null|0|positive-int $window
+ */
+ private function verifyOtpWithWindow(string $otp, int $counter, null|int $window): bool
{
$window = $this->getWindow($window);
@@ -83,21 +134,4 @@ final class HOTP extends OTP implements HOTPInterface
return false;
}
-
- /**
- * @return array<string, mixed>
- */
- protected function getParameterMap(): array
- {
- $v = array_merge(
- parent::getParameterMap(),
- ['counter' => function ($value): int {
- Assertion::greaterOrEqualThan((int) $value, 0, 'Counter must be at least 0.');
-
- return (int) $value;
- }]
- );
-
- return $v;
- }
}