* * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Da\TwoFA\Support; use Da\TwoFA\Contracts\TotpEncoderInterface; use Da\TwoFA\Traits\SecretValidationTrait; use Da\TwoFA\Validator\SecretKeyValidator; use ParagonIE\ConstantTime\Base32; class Encoder implements TotpEncoderInterface { use SecretValidationTrait; /** * Encoder constructor. * * @param SecretKeyValidator|null $secretKeyValidator */ public function __construct(SecretKeyValidator $secretKeyValidator = null) { $this->secretKeyValidator = $secretKeyValidator ?: new SecretKeyValidator(); } /** * @inheritdoc */ public function generateBase32RandomKey($length = 16, $prefix = '') { $secret = $prefix ? $this->toBase32($prefix) : ''; $secret = $this->strPadBase32($secret, $length); $this->validateSecret($secret); return $secret; } /** * @inheritdoc */ public function toBase32($value) { $encoded = Base32::encodeUpper($value); return str_replace('=', '', $encoded); } /** * @inheritdoc */ public function fromBase32($value) { $value = strtoupper($value); $this->validateSecret($value); return Base32::decodeUpper($value); } /** * Get a random number. * * @param $from * @param $to * * @return int */ protected function getRandomNumber($from = 0, $to = 31) { return random_int($from, $to); } /** * Pad string with random base 32 chars. * * @param $string * @param $length * * @return string */ private function strPadBase32($string, $length) { for ($i = 0; $i < $length; $i++) { $string .= substr('234567QWERTYUIOPASDFGHJKLZXCVBNM', $this->getRandomNumber(), 1); } return $string; } }