![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/spomky-labs/otphp/src/ |
<?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; use ParagonIE\ConstantTime\Base32; use RuntimeException; use function Safe\ksort; use function Safe\sprintf; abstract class OTP implements OTPInterface { use ParameterTrait; protected function __construct(?string $secret, string $digest, int $digits) { $this->setSecret($secret); $this->setDigest($digest); $this->setDigits($digits); } public function getQrCodeUri(string $uri, string $placeholder): string { $provisioning_uri = urlencode($this->getProvisioningUri()); return str_replace($placeholder, $provisioning_uri, $uri); } /** * The OTP at the specified input. */ protected function generateOTP(int $input): string { $hash = hash_hmac($this->getDigest(), $this->intToByteString($input), $this->getDecodedSecret(), true); $hmac = array_values(unpack('C*', $hash)); $offset = ($hmac[\count($hmac) - 1] & 0xF); $code = ($hmac[$offset + 0] & 0x7F) << 24 | ($hmac[$offset + 1] & 0xFF) << 16 | ($hmac[$offset + 2] & 0xFF) << 8 | ($hmac[$offset + 3] & 0xFF); $otp = $code % (10 ** $this->getDigits()); return str_pad((string) $otp, $this->getDigits(), '0', STR_PAD_LEFT); } public function at(int $timestamp): string { return $this->generateOTP($timestamp); } /** * @param array<string, mixed> $options */ protected function filterOptions(array &$options): void { foreach (['algorithm' => 'sha1', 'period' => 30, 'digits' => 6] as $key => $default) { if (isset($options[$key]) && $default === $options[$key]) { unset($options[$key]); } } ksort($options); } /** * @param array<string, mixed> $options */ protected function generateURI(string $type, array $options): string { $label = $this->getLabel(); Assertion::string($label, 'The label is not set.'); Assertion::false($this->hasColon($label), 'Label must not contain a colon.'); $options = array_merge($options, $this->getParameters()); $this->filterOptions($options); $params = str_replace(['+', '%7E'], ['%20', '~'], http_build_query($options)); return sprintf('otpauth://%s/%s?%s', $type, rawurlencode((null !== $this->getIssuer() ? $this->getIssuer().':' : '').$label), $params); } private function getDecodedSecret(): string { try { return Base32::decodeUpper($this->getSecret()); } catch (\Exception $e) { throw new RuntimeException('Unable to decode the secret. Is it correctly base32 encoded?'); } } private function intToByteString(int $int): string { $result = []; while (0 !== $int) { $result[] = \chr($int & 0xFF); $int >>= 8; } return str_pad(implode(array_reverse($result)), 8, "\000", STR_PAD_LEFT); } protected function compareOTP(string $safe, string $user): bool { return hash_equals($safe, $user); } }