Subversion Repositories oidplus

Rev

Rev 827 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 827 Rev 874
Line 1... Line 1...
1
<?php
1
<?php
2
declare(strict_types=1);
2
declare(strict_types=1);
3
namespace ParagonIE\ConstantTime;
3
namespace ParagonIE\ConstantTime;
4
 
4
 
-
 
5
use InvalidArgumentException;
-
 
6
use RangeException;
-
 
7
use TypeError;
-
 
8
 
5
/**
9
/**
6
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
10
 *  Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
7
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
11
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
8
 *
12
 *
9
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
13
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
10
 *  of this software and associated documentation files (the "Software"), to deal
14
 *  of this software and associated documentation files (the "Software"), to deal
11
 *  in the Software without restriction, including without limitation the rights
15
 *  in the Software without restriction, including without limitation the rights
Line 60... Line 64...
60
    /**
64
    /**
61
     * Encode into Base32 (RFC 4648)
65
     * Encode into Base32 (RFC 4648)
62
     *
66
     *
63
     * @param string $binString
67
     * @param string $binString
64
     * @return string
68
     * @return string
65
     * @throws \TypeError
69
     * @throws TypeError
66
     */
70
     */
67
    public static function encode(string $binString): string
71
    public static function encode(string $binString): string
68
    {
72
    {
69
        return static::doEncode($binString, false, true);
73
        return static::doEncode($binString, false, true);
70
    }
74
    }
71
    /**
75
    /**
72
     * Encode into Base32 (RFC 4648)
76
     * Encode into Base32 (RFC 4648)
73
     *
77
     *
74
     * @param string $src
78
     * @param string $src
75
     * @return string
79
     * @return string
76
     * @throws \TypeError
80
     * @throws TypeError
77
     */
81
     */
78
    public static function encodeUnpadded(string $src): string
82
    public static function encodeUnpadded(string $src): string
79
    {
83
    {
80
        return static::doEncode($src, false, false);
84
        return static::doEncode($src, false, false);
81
    }
85
    }
Line 83... Line 87...
83
    /**
87
    /**
84
     * Encode into uppercase Base32 (RFC 4648)
88
     * Encode into uppercase Base32 (RFC 4648)
85
     *
89
     *
86
     * @param string $src
90
     * @param string $src
87
     * @return string
91
     * @return string
88
     * @throws \TypeError
92
     * @throws TypeError
89
     */
93
     */
90
    public static function encodeUpper(string $src): string
94
    public static function encodeUpper(string $src): string
91
    {
95
    {
92
        return static::doEncode($src, true, true);
96
        return static::doEncode($src, true, true);
93
    }
97
    }
Line 95... Line 99...
95
    /**
99
    /**
96
     * Encode into uppercase Base32 (RFC 4648)
100
     * Encode into uppercase Base32 (RFC 4648)
97
     *
101
     *
98
     * @param string $src
102
     * @param string $src
99
     * @return string
103
     * @return string
100
     * @throws \TypeError
104
     * @throws TypeError
101
     */
105
     */
102
    public static function encodeUpperUnpadded(string $src): string
106
    public static function encodeUpperUnpadded(string $src): string
103
    {
107
    {
104
        return static::doEncode($src, true, false);
108
        return static::doEncode($src, true, false);
105
    }
109
    }
Line 180... Line 184...
180
        $diff -= ((25 - $src) >> 8) & 41;
184
        $diff -= ((25 - $src) >> 8) & 41;
181
 
185
 
182
        return \pack('C', $src + $diff);
186
        return \pack('C', $src + $diff);
183
    }
187
    }
184
 
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
    }
185
 
215
 
186
    /**
216
    /**
187
     * Base32 decoding
217
     * Base32 decoding
188
     *
218
     *
189
     * @param string $src
219
     * @param string $src
190
     * @param bool $upper
220
     * @param bool $upper
191
     * @param bool $strictPadding
221
     * @param bool $strictPadding
192
     * @return string
222
     * @return string
-
 
223
     *
193
     * @throws \TypeError
224
     * @throws TypeError
194
     * @psalm-suppress RedundantCondition
225
     * @psalm-suppress RedundantCondition
195
     */
226
     */
196
    protected static function doDecode(string $src, bool $upper = false, bool $strictPadding = false): string
227
    protected static function doDecode(
-
 
228
        string $src,
-
 
229
        bool $upper = false,
-
 
230
        bool $strictPadding = false
197
    {
231
    ): string {
198
        // We do this to reduce code duplication:
232
        // We do this to reduce code duplication:
199
        $method = $upper
233
        $method = $upper
200
            ? 'decode5BitsUpper'
234
            ? 'decode5BitsUpper'
201
            : 'decode5Bits';
235
            : 'decode5Bits';
202
 
236
 
Line 214... Line 248...
214
                        break;
248
                        break;
215
                    }
249
                    }
216
                }
250
                }
217
            }
251
            }
218
            if (($srcLen & 7) === 1) {
252
            if (($srcLen & 7) === 1) {
219
                throw new \RangeException(
253
                throw new RangeException(
220
                    'Incorrect padding'
254
                    'Incorrect padding'
221
                );
255
                );
222
            }
256
            }
223
        } else {
257
        } else {
224
            $src = \rtrim($src, '=');
258
            $src = \rtrim($src, '=');
Line 285... Line 319...
285
                    (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
319
                    (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
286
                    (($c3 << 4) | ($c4 >> 1)             ) & 0xff,
320
                    (($c3 << 4) | ($c4 >> 1)             ) & 0xff,
287
                    (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff
321
                    (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff
288
                );
322
                );
289
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6) >> 8;
323
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6) >> 8;
-
 
324
                if ($strictPadding) {
-
 
325
                    $err |= ($c6 << 5) & 0xff;
-
 
326
                }
290
            } elseif ($i + 5 < $srcLen) {
327
            } elseif ($i + 5 < $srcLen) {
291
                /** @var int $c1 */
328
                /** @var int $c1 */
292
                $c1 = static::$method($chunk[2]);
329
                $c1 = static::$method($chunk[2]);
293
                /** @var int $c2 */
330
                /** @var int $c2 */
294
                $c2 = static::$method($chunk[3]);
331
                $c2 = static::$method($chunk[3]);
Line 322... Line 359...
322
                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff,
359
                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff,
323
                    (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
360
                    (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff,
324
                    (($c3 << 4) | ($c4 >> 1)             ) & 0xff
361
                    (($c3 << 4) | ($c4 >> 1)             ) & 0xff
325
                );
362
                );
326
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4) >> 8;
363
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4) >> 8;
-
 
364
                if ($strictPadding) {
-
 
365
                    $err |= ($c4 << 7) & 0xff;
-
 
366
                }
327
            } elseif ($i + 3 < $srcLen) {
367
            } elseif ($i + 3 < $srcLen) {
328
                /** @var int $c1 */
368
                /** @var int $c1 */
329
                $c1 = static::$method($chunk[2]);
369
                $c1 = static::$method($chunk[2]);
330
                /** @var int $c2 */
370
                /** @var int $c2 */
331
                $c2 = static::$method($chunk[3]);
371
                $c2 = static::$method($chunk[3]);
Line 336... Line 376...
336
                    'CC',
376
                    'CC',
337
                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff,
377
                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff,
338
                    (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff
378
                    (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff
339
                );
379
                );
340
                $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
380
                $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
-
 
381
                if ($strictPadding) {
-
 
382
                    $err |= ($c3 << 4) & 0xff;
-
 
383
                }
341
            } elseif ($i + 2 < $srcLen) {
384
            } elseif ($i + 2 < $srcLen) {
342
                /** @var int $c1 */
385
                /** @var int $c1 */
343
                $c1 = static::$method($chunk[2]);
386
                $c1 = static::$method($chunk[2]);
344
                /** @var int $c2 */
387
                /** @var int $c2 */
345
                $c2 = static::$method($chunk[3]);
388
                $c2 = static::$method($chunk[3]);
Line 348... Line 391...
348
                    'CC',
391
                    'CC',
349
                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff,
392
                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff,
350
                    (($c1 << 6) | ($c2 << 1)             ) & 0xff
393
                    (($c1 << 6) | ($c2 << 1)             ) & 0xff
351
                );
394
                );
352
                $err |= ($c0 | $c1 | $c2) >> 8;
395
                $err |= ($c0 | $c1 | $c2) >> 8;
-
 
396
                if ($strictPadding) {
-
 
397
                    $err |= ($c2 << 6) & 0xff;
-
 
398
                }
353
            } elseif ($i + 1 < $srcLen) {
399
            } elseif ($i + 1 < $srcLen) {
354
                /** @var int $c1 */
400
                /** @var int $c1 */
355
                $c1 = static::$method($chunk[2]);
401
                $c1 = static::$method($chunk[2]);
356
 
402
 
357
                $dest .= \pack(
403
                $dest .= \pack(
358
                    'C',
404
                    'C',
359
                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff
405
                    (($c0 << 3) | ($c1 >> 2)             ) & 0xff
360
                );
406
                );
361
                $err |= ($c0 | $c1) >> 8;
407
                $err |= ($c0 | $c1) >> 8;
-
 
408
                if ($strictPadding) {
-
 
409
                    $err |= ($c1 << 6) & 0xff;
-
 
410
                }
362
            } else {
411
            } else {
363
                $dest .= \pack(
412
                $dest .= \pack(
364
                    'C',
413
                    'C',
365
                    (($c0 << 3)                          ) & 0xff
414
                    (($c0 << 3)                          ) & 0xff
366
                );
415
                );
367
                $err |= ($c0) >> 8;
416
                $err |= ($c0) >> 8;
368
            }
417
            }
369
        }
418
        }
370
        $check = ($err === 0);
419
        $check = ($err === 0);
371
        if (!$check) {
420
        if (!$check) {
372
            throw new \RangeException(
421
            throw new RangeException(
373
                'Base32::doDecode() only expects characters in the correct base32 alphabet'
422
                'Base32::doDecode() only expects characters in the correct base32 alphabet'
374
            );
423
            );
375
        }
424
        }
376
        return $dest;
425
        return $dest;
377
    }
426
    }
Line 381... Line 430...
381
     *
430
     *
382
     * @param string $src
431
     * @param string $src
383
     * @param bool $upper
432
     * @param bool $upper
384
     * @param bool $pad
433
     * @param bool $pad
385
     * @return string
434
     * @return string
386
     * @throws \TypeError
435
     * @throws TypeError
387
     */
436
     */
388
    protected static function doEncode(string $src, bool $upper = false, $pad = true): string
437
    protected static function doEncode(string $src, bool $upper = false, $pad = true): string
389
    {
438
    {
390
        // We do this to reduce code duplication:
439
        // We do this to reduce code duplication:
391
        $method = $upper
440
        $method = $upper