PluginProbe ʕ •ᴥ•ʔ
ShareThis Dashboard for Google Analytics / 3.2.0
ShareThis Dashboard for Google Analytics v3.2.0
3.3.2 trunk 1.0.7 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.1 2.1.2 2.1.3 2.1.4 2.1.5 2.2.5 2.3.5 2.3.6 2.3.7 2.3.8 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 3.0.0 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.3.0 3.3.1
googleanalytics / lib / analytics-admin / vendor / paragonie / constant_time_encoding / src / Base32.php
googleanalytics / lib / analytics-admin / vendor / paragonie / constant_time_encoding / src Last commit date
Base32.php 3 years ago Base32Hex.php 3 years ago Base64.php 3 years ago Base64DotSlash.php 3 years ago Base64DotSlashOrdered.php 3 years ago Base64UrlSafe.php 3 years ago Binary.php 3 years ago EncoderInterface.php 3 years ago Encoding.php 3 years ago Hex.php 3 years ago RFC4648.php 3 years ago
Base32.php
520 lines
1 <?php
2 declare(strict_types=1);
3 namespace ParagonIE\ConstantTime;
4
5 use InvalidArgumentException;
6 use RangeException;
7 use TypeError;
8
9 /**
10 * Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
11 * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a copy
14 * of this software and associated documentation files (the "Software"), to deal
15 * in the Software without restriction, including without limitation the rights
16 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 * copies of the Software, and to permit persons to whom the Software is
18 * furnished to do so, subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included in all
21 * copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 * SOFTWARE.
30 */
31
32 /**
33 * Class Base32
34 * [A-Z][2-7]
35 *
36 * @package ParagonIE\ConstantTime
37 */
38 abstract class Base32 implements EncoderInterface
39 {
40 /**
41 * Decode a Base32-encoded string into raw binary
42 *
43 * @param string $encodedString
44 * @param bool $strictPadding
45 * @return string
46 */
47 public static function decode(string $encodedString, bool $strictPadding = false): string
48 {
49 return static::doDecode($encodedString, false, $strictPadding);
50 }
51
52 /**
53 * Decode an uppercase Base32-encoded string into raw binary
54 *
55 * @param string $src
56 * @param bool $strictPadding
57 * @return string
58 */
59 public static function decodeUpper(string $src, bool $strictPadding = false): string
60 {
61 return static::doDecode($src, true, $strictPadding);
62 }
63
64 /**
65 * Encode into Base32 (RFC 4648)
66 *
67 * @param string $binString
68 * @return string
69 * @throws TypeError
70 */
71 public static function encode(string $binString): string
72 {
73 return static::doEncode($binString, false, true);
74 }
75 /**
76 * Encode into Base32 (RFC 4648)
77 *
78 * @param string $src
79 * @return string
80 * @throws TypeError
81 */
82 public static function encodeUnpadded(string $src): string
83 {
84 return static::doEncode($src, false, false);
85 }
86
87 /**
88 * Encode into uppercase Base32 (RFC 4648)
89 *
90 * @param string $src
91 * @return string
92 * @throws TypeError
93 */
94 public static function encodeUpper(string $src): string
95 {
96 return static::doEncode($src, true, true);
97 }
98
99 /**
100 * Encode into uppercase Base32 (RFC 4648)
101 *
102 * @param string $src
103 * @return string
104 * @throws TypeError
105 */
106 public static function encodeUpperUnpadded(string $src): string
107 {
108 return static::doEncode($src, true, false);
109 }
110
111 /**
112 * Uses bitwise operators instead of table-lookups to turn 5-bit integers
113 * into 8-bit integers.
114 *
115 * @param int $src
116 * @return int
117 */
118 protected static function decode5Bits(int $src): int
119 {
120 $ret = -1;
121
122 // if ($src > 96 && $src < 123) $ret += $src - 97 + 1; // -64
123 $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 96);
124
125 // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
126 $ret += (((0x31 - $src) & ($src - 0x38)) >> 8) & ($src - 23);
127
128 return $ret;
129 }
130
131 /**
132 * Uses bitwise operators instead of table-lookups to turn 5-bit integers
133 * into 8-bit integers.
134 *
135 * Uppercase variant.
136 *
137 * @param int $src
138 * @return int
139 */
140 protected static function decode5BitsUpper(int $src): int
141 {
142 $ret = -1;
143
144 // if ($src > 64 && $src < 91) $ret += $src - 65 + 1; // -64
145 $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
146
147 // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
148 $ret += (((0x31 - $src) & ($src - 0x38)) >> 8) & ($src - 23);
149
150 return $ret;
151 }
152
153 /**
154 * Uses bitwise operators instead of table-lookups to turn 8-bit integers
155 * into 5-bit integers.
156 *
157 * @param int $src
158 * @return string
159 */
160 protected static function encode5Bits(int $src): string
161 {
162 $diff = 0x61;
163
164 // if ($src > 25) $ret -= 72;
165 $diff -= ((25 - $src) >> 8) & 73;
166
167 return \pack('C', $src + $diff);
168 }
169
170 /**
171 * Uses bitwise operators instead of table-lookups to turn 8-bit integers
172 * into 5-bit integers.
173 *
174 * Uppercase variant.
175 *
176 * @param int $src
177 * @return string
178 */
179 protected static function encode5BitsUpper(int $src): string
180 {
181 $diff = 0x41;
182
183 // if ($src > 25) $ret -= 40;
184 $diff -= ((25 - $src) >> 8) & 41;
185
186 return \pack('C', $src + $diff);
187 }
188
189 /**
190 * @param string $encodedString
191 * @param bool $upper
192 * @return string
193 */
194 public static function decodeNoPadding(string $encodedString, bool $upper = false): string
195 {
196 $srcLen = Binary::safeStrlen($encodedString);
197 if ($srcLen === 0) {
198 return '';
199 }
200 if (($srcLen & 7) === 0) {
201 for ($j = 0; $j < 7 && $j < $srcLen; ++$j) {
202 if ($encodedString[$srcLen - $j - 1] === '=') {
203 throw new InvalidArgumentException(
204 "decodeNoPadding() doesn't tolerate padding"
205 );
206 }
207 }
208 }
209 return static::doDecode(
210 $encodedString,
211 $upper,
212 true
213 );
214 }
215
216 /**
217 * Base32 decoding
218 *
219 * @param string $src
220 * @param bool $upper
221 * @param bool $strictPadding
222 * @return string
223 *
224 * @throws TypeError
225 * @psalm-suppress RedundantCondition
226 */
227 protected static function doDecode(
228 string $src,
229 bool $upper = false,
230 bool $strictPadding = false
231 ): string {
232 // We do this to reduce code duplication:
233 $method = $upper
234 ? 'decode5BitsUpper'
235 : 'decode5Bits';
236
237 // Remove padding
238 $srcLen = Binary::safeStrlen($src);
239 if ($srcLen === 0) {
240 return '';
241 }
242 if ($strictPadding) {
243 if (($srcLen & 7) === 0) {
244 for ($j = 0; $j < 7; ++$j) {
245 if ($src[$srcLen - 1] === '=') {
246 $srcLen--;
247 } else {
248 break;
249 }
250 }
251 }
252 if (($srcLen & 7) === 1) {
253 throw new RangeException(
254 'Incorrect padding'
255 );
256 }
257 } else {
258 $src = \rtrim($src, '=');
259 $srcLen = Binary::safeStrlen($src);
260 }
261
262 $err = 0;
263 $dest = '';
264 // Main loop (no padding):
265 for ($i = 0; $i + 8 <= $srcLen; $i += 8) {
266 /** @var array<int, int> $chunk */
267 $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 8));
268 /** @var int $c0 */
269 $c0 = static::$method($chunk[1]);
270 /** @var int $c1 */
271 $c1 = static::$method($chunk[2]);
272 /** @var int $c2 */
273 $c2 = static::$method($chunk[3]);
274 /** @var int $c3 */
275 $c3 = static::$method($chunk[4]);
276 /** @var int $c4 */
277 $c4 = static::$method($chunk[5]);
278 /** @var int $c5 */
279 $c5 = static::$method($chunk[6]);
280 /** @var int $c6 */
281 $c6 = static::$method($chunk[7]);
282 /** @var int $c7 */
283 $c7 = static::$method($chunk[8]);
284
285 $dest .= \pack(
286 'CCCCC',
287 (($c0 << 3) | ($c1 >> 2) ) & 0xff,
288 (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
289 (($c3 << 4) | ($c4 >> 1) ) & 0xff,
290 (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff,
291 (($c6 << 5) | ($c7 ) ) & 0xff
292 );
293 $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6 | $c7) >> 8;
294 }
295 // The last chunk, which may have padding:
296 if ($i < $srcLen) {
297 /** @var array<int, int> $chunk */
298 $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
299 /** @var int $c0 */
300 $c0 = static::$method($chunk[1]);
301
302 if ($i + 6 < $srcLen) {
303 /** @var int $c1 */
304 $c1 = static::$method($chunk[2]);
305 /** @var int $c2 */
306 $c2 = static::$method($chunk[3]);
307 /** @var int $c3 */
308 $c3 = static::$method($chunk[4]);
309 /** @var int $c4 */
310 $c4 = static::$method($chunk[5]);
311 /** @var int $c5 */
312 $c5 = static::$method($chunk[6]);
313 /** @var int $c6 */
314 $c6 = static::$method($chunk[7]);
315
316 $dest .= \pack(
317 'CCCC',
318 (($c0 << 3) | ($c1 >> 2) ) & 0xff,
319 (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
320 (($c3 << 4) | ($c4 >> 1) ) & 0xff,
321 (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff
322 );
323 $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6) >> 8;
324 if ($strictPadding) {
325 $err |= ($c6 << 5) & 0xff;
326 }
327 } elseif ($i + 5 < $srcLen) {
328 /** @var int $c1 */
329 $c1 = static::$method($chunk[2]);
330 /** @var int $c2 */
331 $c2 = static::$method($chunk[3]);
332 /** @var int $c3 */
333 $c3 = static::$method($chunk[4]);
334 /** @var int $c4 */
335 $c4 = static::$method($chunk[5]);
336 /** @var int $c5 */
337 $c5 = static::$method($chunk[6]);
338
339 $dest .= \pack(
340 'CCCC',
341 (($c0 << 3) | ($c1 >> 2) ) & 0xff,
342 (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
343 (($c3 << 4) | ($c4 >> 1) ) & 0xff,
344 (($c4 << 7) | ($c5 << 2) ) & 0xff
345 );
346 $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5) >> 8;
347 } elseif ($i + 4 < $srcLen) {
348 /** @var int $c1 */
349 $c1 = static::$method($chunk[2]);
350 /** @var int $c2 */
351 $c2 = static::$method($chunk[3]);
352 /** @var int $c3 */
353 $c3 = static::$method($chunk[4]);
354 /** @var int $c4 */
355 $c4 = static::$method($chunk[5]);
356
357 $dest .= \pack(
358 'CCC',
359 (($c0 << 3) | ($c1 >> 2) ) & 0xff,
360 (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
361 (($c3 << 4) | ($c4 >> 1) ) & 0xff
362 );
363 $err |= ($c0 | $c1 | $c2 | $c3 | $c4) >> 8;
364 if ($strictPadding) {
365 $err |= ($c4 << 7) & 0xff;
366 }
367 } elseif ($i + 3 < $srcLen) {
368 /** @var int $c1 */
369 $c1 = static::$method($chunk[2]);
370 /** @var int $c2 */
371 $c2 = static::$method($chunk[3]);
372 /** @var int $c3 */
373 $c3 = static::$method($chunk[4]);
374
375 $dest .= \pack(
376 'CC',
377 (($c0 << 3) | ($c1 >> 2) ) & 0xff,
378 (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff
379 );
380 $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
381 if ($strictPadding) {
382 $err |= ($c3 << 4) & 0xff;
383 }
384 } elseif ($i + 2 < $srcLen) {
385 /** @var int $c1 */
386 $c1 = static::$method($chunk[2]);
387 /** @var int $c2 */
388 $c2 = static::$method($chunk[3]);
389
390 $dest .= \pack(
391 'CC',
392 (($c0 << 3) | ($c1 >> 2) ) & 0xff,
393 (($c1 << 6) | ($c2 << 1) ) & 0xff
394 );
395 $err |= ($c0 | $c1 | $c2) >> 8;
396 if ($strictPadding) {
397 $err |= ($c2 << 6) & 0xff;
398 }
399 } elseif ($i + 1 < $srcLen) {
400 /** @var int $c1 */
401 $c1 = static::$method($chunk[2]);
402
403 $dest .= \pack(
404 'C',
405 (($c0 << 3) | ($c1 >> 2) ) & 0xff
406 );
407 $err |= ($c0 | $c1) >> 8;
408 if ($strictPadding) {
409 $err |= ($c1 << 6) & 0xff;
410 }
411 } else {
412 $dest .= \pack(
413 'C',
414 (($c0 << 3) ) & 0xff
415 );
416 $err |= ($c0) >> 8;
417 }
418 }
419 $check = ($err === 0);
420 if (!$check) {
421 throw new RangeException(
422 'Base32::doDecode() only expects characters in the correct base32 alphabet'
423 );
424 }
425 return $dest;
426 }
427
428 /**
429 * Base32 Encoding
430 *
431 * @param string $src
432 * @param bool $upper
433 * @param bool $pad
434 * @return string
435 * @throws TypeError
436 */
437 protected static function doEncode(string $src, bool $upper = false, $pad = true): string
438 {
439 // We do this to reduce code duplication:
440 $method = $upper
441 ? 'encode5BitsUpper'
442 : 'encode5Bits';
443
444 $dest = '';
445 $srcLen = Binary::safeStrlen($src);
446
447 // Main loop (no padding):
448 for ($i = 0; $i + 5 <= $srcLen; $i += 5) {
449 /** @var array<int, int> $chunk */
450 $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 5));
451 $b0 = $chunk[1];
452 $b1 = $chunk[2];
453 $b2 = $chunk[3];
454 $b3 = $chunk[4];
455 $b4 = $chunk[5];
456 $dest .=
457 static::$method( ($b0 >> 3) & 31) .
458 static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
459 static::$method((($b1 >> 1) ) & 31) .
460 static::$method((($b1 << 4) | ($b2 >> 4)) & 31) .
461 static::$method((($b2 << 1) | ($b3 >> 7)) & 31) .
462 static::$method((($b3 >> 2) ) & 31) .
463 static::$method((($b3 << 3) | ($b4 >> 5)) & 31) .
464 static::$method( $b4 & 31);
465 }
466 // The last chunk, which may have padding:
467 if ($i < $srcLen) {
468 /** @var array<int, int> $chunk */
469 $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
470 $b0 = $chunk[1];
471 if ($i + 3 < $srcLen) {
472 $b1 = $chunk[2];
473 $b2 = $chunk[3];
474 $b3 = $chunk[4];
475 $dest .=
476 static::$method( ($b0 >> 3) & 31) .
477 static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
478 static::$method((($b1 >> 1) ) & 31) .
479 static::$method((($b1 << 4) | ($b2 >> 4)) & 31) .
480 static::$method((($b2 << 1) | ($b3 >> 7)) & 31) .
481 static::$method((($b3 >> 2) ) & 31) .
482 static::$method((($b3 << 3) ) & 31);
483 if ($pad) {
484 $dest .= '=';
485 }
486 } elseif ($i + 2 < $srcLen) {
487 $b1 = $chunk[2];
488 $b2 = $chunk[3];
489 $dest .=
490 static::$method( ($b0 >> 3) & 31) .
491 static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
492 static::$method((($b1 >> 1) ) & 31) .
493 static::$method((($b1 << 4) | ($b2 >> 4)) & 31) .
494 static::$method((($b2 << 1) ) & 31);
495 if ($pad) {
496 $dest .= '===';
497 }
498 } elseif ($i + 1 < $srcLen) {
499 $b1 = $chunk[2];
500 $dest .=
501 static::$method( ($b0 >> 3) & 31) .
502 static::$method((($b0 << 2) | ($b1 >> 6)) & 31) .
503 static::$method((($b1 >> 1) ) & 31) .
504 static::$method((($b1 << 4) ) & 31);
505 if ($pad) {
506 $dest .= '====';
507 }
508 } else {
509 $dest .=
510 static::$method( ($b0 >> 3) & 31) .
511 static::$method( ($b0 << 2) & 31);
512 if ($pad) {
513 $dest .= '======';
514 }
515 }
516 }
517 return $dest;
518 }
519 }
520