Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
otpalgorithm.php
1<?php
2
4
8
9abstract class OtpAlgorithm
10{
11 protected static $type = 'undefined';
12 protected $digest = 'sha1';
13 protected $digits = 6;
14 protected $secret = null;
15 protected $appScheme = 'otpauth';
16 protected $requireTwoCode = true;
17
28 abstract public function verify($input, $params = null);
29
38 abstract public function getSyncParameters($inputA, $inputB);
39
45 public function isTwoCodeRequired()
46 {
48 }
49
56 public function setSecret($secret)
57 {
58 $this->secret = $secret;
59
60 // Backward compatibility. Use sha256 for eToken with 256bits key
61 if (strlen($this->secret) > 25)
62 {
63 $this->digest = 'sha256';
64 }
65
66 return $this;
67 }
68
74 public function getSecret()
75 {
76 return $this->secret;
77 }
78
88 public function generateUri($label, array $opts = [])
89 {
90 $positionalOpts = [
91 // Don't change order!
92 'secret' => Base32::encode($this->getSecret()),
93 ];
94
95 $opts['algorithm'] = $this->getDigest();
96 // Digest must be in upper case for some OTP apps (e.g. Google Authenticator for iOS)
97 $opts['algorithm'] = mb_strtoupper($opts['algorithm']);
98 $opts['digits'] = $this->getDigits();
99
100 ksort($opts);
101
102 // Some devices require a specific order for some parameters (e.g. Microsoft Authenticator require "secret" at first place %) )
103 $opts = array_merge(
104 $positionalOpts,
105 $opts
106 );
107
108 $params = http_build_query($opts, '', '&', PHP_QUERY_RFC3986);
109
110 return sprintf(
111 '%s://%s/%s?%s',
112 $this->getAppScheme(),
113 $this->getType(),
114 rawurlencode($label),
115 $params
116 );
117 }
118
125 public function generateOTP($counter)
126 {
127 $hash = hash_hmac($this->getDigest(), static::toByte($counter), $this->getSecret());
128 $hmac = [];
129 foreach (str_split($hash, 2) as $hex)
130 {
131 $hmac[] = hexdec($hex);
132 }
133
134 $offset = $hmac[count($hmac) - 1] & 0xf;
135 $code = ($hmac[$offset] & 0x7F) << 24;
136 $code |= ($hmac[$offset + 1] & 0xFF) << 16;
137 $code |= ($hmac[$offset + 2] & 0xFF) << 8;
138 $code |= ($hmac[$offset + 3] & 0xFF);
139
140 $otp = $code % pow(10, $this->getDigits());
141 return str_pad($otp, $this->getDigits(), '0', STR_PAD_LEFT);
142 }
143
150 protected static function toByte($value)
151 {
152 $result = [];
153 while ($value > 0)
154 {
155 $result[] = chr($value & 0xFF);
156 $value >>= 8;
157 }
158
159 return str_pad(implode(array_reverse($result)), 8, "\000", STR_PAD_LEFT);
160 }
161
170 protected function isStringsEqual($expected, $actual)
171 {
172 if (!is_string($expected))
173 {
174 throw new ArgumentTypeException('expected', 'string');
175 }
176
177 if (!is_string($actual))
178 {
179 throw new ArgumentTypeException('actual', 'string');
180 }
181
182 $lenExpected = strlen($expected);
183 $lenActual = strlen($actual);
184
185 $status = $lenExpected ^ $lenActual;
186 $len = min($lenExpected, $lenActual);
187 for ($i = 0; $i < $len; $i++)
188 {
189 $status |= ord($expected[$i]) ^ ord($actual[$i]);
190 }
191
192 return $status === 0;
193 }
194
201 public function getDigest()
202 {
203 return $this->digest;
204 }
205
211 public function getDigits()
212 {
213 return $this->digits;
214 }
215
221 public function getType()
222 {
223 return static::$type;
224 }
225
232 public function getAppScheme()
233 {
234 return $this->appScheme;
235 }
236}
generateUri($label, array $opts=[])
static encode($string)
Definition base32.php:60