summaryrefslogtreecommitdiff
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.php103
1 files changed, 103 insertions, 0 deletions
diff --git a/vendor/spomky-labs/otphp/src/HOTP.php b/vendor/spomky-labs/otphp/src/HOTP.php
new file mode 100644
index 000000000..a2f4a2395
--- /dev/null
+++ b/vendor/spomky-labs/otphp/src/HOTP.php
@@ -0,0 +1,103 @@
+<?php
+
+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;
+
+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);
+ }
+
+ public static function create(?string $secret = null, int $counter = 0, string $digest = 'sha1', int $digits = 6): HOTPInterface
+ {
+ return new self($secret, $counter, $digest, $digits);
+ }
+
+ protected function setCounter(int $counter): void
+ {
+ $this->setParameter('counter', $counter);
+ }
+
+ public function getCounter(): int
+ {
+ return $this->getParameter('counter');
+ }
+
+ private function updateCounter(int $counter): void
+ {
+ $this->setCounter($counter);
+ }
+
+ public function getProvisioningUri(): string
+ {
+ return $this->generateURI('hotp', ['counter' => $this->getCounter()]);
+ }
+
+ /**
+ * If the counter is not provided, the OTP is verified at the actual counter.
+ */
+ public function verify(string $otp, ?int $counter = null, ?int $window = null): bool
+ {
+ Assertion::greaterOrEqualThan($counter, 0, 'The counter must be at least 0.');
+
+ if (null === $counter) {
+ $counter = $this->getCounter();
+ } elseif ($counter < $this->getCounter()) {
+ return false;
+ }
+
+ return $this->verifyOtpWithWindow($otp, $counter, $window);
+ }
+
+ private function getWindow(?int $window): int
+ {
+ return abs($window ?? 0);
+ }
+
+ private function verifyOtpWithWindow(string $otp, int $counter, ?int $window): bool
+ {
+ $window = $this->getWindow($window);
+
+ for ($i = $counter; $i <= $counter + $window; ++$i) {
+ if ($this->compareOTP($this->at($i), $otp)) {
+ $this->updateCounter($i + 1);
+
+ return true;
+ }
+ }
+
+ 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;
+ }
+}