‪TYPO3CMS  11.5
RecoveryCodes.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
16 declare(strict_types=1);
17 
19 
23 
30 {
31  private const ‪MIN_LENGTH = 8;
32 
33  protected string ‪$mode;
35 
36  public function ‪__construct(string ‪$mode)
37  {
38  $this->mode = ‪$mode;
39  $this->passwordHashFactory = GeneralUtility::makeInstance(PasswordHashFactory::class);
40  }
41 
47  public function ‪generateRecoveryCodes(): array
48  {
49  $plainCodes = $this->‪generatePlainRecoveryCodes();
50  return array_combine($plainCodes, $this->‪generatedHashedRecoveryCodes($plainCodes));
51  }
52 
60  public function ‪generatePlainRecoveryCodes(int $length = 8, int $quantity = 8): array
61  {
62  if ($length < self::MIN_LENGTH) {
63  throw new \InvalidArgumentException(
64  $length . ' is not allowed as length for recovery codes. Must be at least ' . self::MIN_LENGTH,
65  1613666803
66  );
67  }
68 
69  $codes = [];
70  $random = GeneralUtility::makeInstance(Random::class);
71 
72  while ($quantity >= 1 && count($codes) < $quantity) {
73  $number = (int)hexdec($random->generateRandomHexString(16));
74  // We only want to work with positive integers
75  if ($number < 0) {
76  continue;
77  }
78  // Create a $length long string from the random number
79  $code = str_pad((string)($number % (10 ** $length)), $length, '0', STR_PAD_LEFT);
80  // Prevent duplicate codes which is however very unlikely to happen
81  if (!in_array($code, $codes, true)) {
82  $codes[] = $code;
83  }
84  }
85 
86  return $codes;
87  }
88 
95  public function ‪generatedHashedRecoveryCodes(array $codes): array
96  {
97  // Use the current default hash instance for hashing the recovery codes
98  $hashInstance = $this->passwordHashFactory->getDefaultHashInstance($this->mode);
99 
100  foreach ($codes as &$code) {
101  $code = $hashInstance->getHashedPassword($code);
102  }
103  unset($code);
104  return $codes;
105  }
106 
115  public function ‪verifyRecoveryCode(string $recoveryCode, array &$codes): bool
116  {
117  if ($codes === []) {
118  return false;
119  }
120 
121  // Get the hash instance which was initially used to generate these codes.
122  // This could differ from the current default hash instance. We however only need
123  // to check the first code since recovery codes can not be generated individually.
124  $hasInstance = $this->passwordHashFactory->get(reset($codes), $this->mode);
125 
126  foreach ($codes as $key => $code) {
127  // Compare hashed codes
128  if ($hasInstance->checkPassword($recoveryCode, $code)) {
129  // Unset the matching code
130  unset($codes[$key]);
131  return true;
132  }
133  }
134  return false;
135  }
136 }
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory
Definition: PasswordHashFactory.php:27
‪TYPO3\CMS\Core\Authentication\Mfa\Provider\RecoveryCodes
Definition: RecoveryCodes.php:30
‪TYPO3\CMS\Core\Authentication\Mfa\Provider
Definition: RecoveryCodes.php:18
‪TYPO3\CMS\Core\Authentication\Mfa\Provider\RecoveryCodes\generatePlainRecoveryCodes
‪string[] generatePlainRecoveryCodes(int $length=8, int $quantity=8)
Definition: RecoveryCodes.php:60
‪TYPO3\CMS\Core\Authentication\Mfa\Provider\RecoveryCodes\generatedHashedRecoveryCodes
‪array generatedHashedRecoveryCodes(array $codes)
Definition: RecoveryCodes.php:95
‪TYPO3\CMS\Core\Authentication\Mfa\Provider\RecoveryCodes\$passwordHashFactory
‪PasswordHashFactory $passwordHashFactory
Definition: RecoveryCodes.php:34
‪TYPO3\CMS\Core\Authentication\Mfa\Provider\RecoveryCodes\verifyRecoveryCode
‪bool verifyRecoveryCode(string $recoveryCode, array &$codes)
Definition: RecoveryCodes.php:115
‪TYPO3\CMS\Core\Authentication\Mfa\Provider\RecoveryCodes\__construct
‪__construct(string $mode)
Definition: RecoveryCodes.php:36
‪TYPO3\CMS\Core\Authentication\Mfa\Provider\RecoveryCodes\MIN_LENGTH
‪const MIN_LENGTH
Definition: RecoveryCodes.php:31
‪TYPO3\CMS\Core\Authentication\Mfa\Provider\RecoveryCodes\$mode
‪string $mode
Definition: RecoveryCodes.php:33
‪TYPO3\CMS\Core\Authentication\Mfa\Provider\RecoveryCodes\generateRecoveryCodes
‪array generateRecoveryCodes()
Definition: RecoveryCodes.php:47
‪TYPO3\CMS\Core\Crypto\Random
Definition: Random.php:24
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50