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 RangeException; |
|
- | 6 | use TypeError; |
|
- | 7 | ||
5 | /** |
8 | /** |
6 | * Copyright (c) 2016 - 2018 Paragon Initiative Enterprises. |
9 | * Copyright (c) 2016 - 2022 Paragon Initiative Enterprises. |
7 | * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com) |
10 | * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com) |
8 | * |
11 | * |
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
12 | * 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 |
13 | * of this software and associated documentation files (the "Software"), to deal |
11 | * in the Software without restriction, including without limitation the rights |
14 | * in the Software without restriction, including without limitation the rights |
Line 35... | Line 38... | ||
35 | * Convert a binary string into a hexadecimal string without cache-timing |
38 | * Convert a binary string into a hexadecimal string without cache-timing |
36 | * leaks |
39 | * leaks |
37 | * |
40 | * |
38 | * @param string $binString (raw binary) |
41 | * @param string $binString (raw binary) |
39 | * @return string |
42 | * @return string |
40 | * @throws \TypeError |
43 | * @throws TypeError |
41 | */ |
44 | */ |
42 | public static function encode(string $binString): string |
45 | public static function encode(string $binString): string |
43 | { |
46 | { |
44 | $hex = ''; |
47 | $hex = ''; |
45 | $len = Binary::safeStrlen($binString); |
48 | $len = Binary::safeStrlen($binString); |
46 | for ($i = 0; $i < $len; ++$i) { |
49 | for ($i = 0; $i < $len; ++$i) { |
47 | /** @var array<int, int> $chunk */ |
50 | /** @var array<int, int> $chunk */ |
48 | $chunk = \unpack('C', Binary::safeSubstr($binString, $i, 1)); |
51 | $chunk = \unpack('C', $binString[$i]); |
49 | $c = $chunk[1] & 0xf; |
52 | $c = $chunk[1] & 0xf; |
50 | $b = $chunk[1] >> 4; |
53 | $b = $chunk[1] >> 4; |
51 | 54 | ||
52 | $hex .= pack( |
55 | $hex .= \pack( |
53 | 'CC', |
56 | 'CC', |
54 | (87 + $b + ((($b - 10) >> 8) & ~38)), |
57 | (87 + $b + ((($b - 10) >> 8) & ~38)), |
55 | (87 + $c + ((($c - 10) >> 8) & ~38)) |
58 | (87 + $c + ((($c - 10) >> 8) & ~38)) |
56 | ); |
59 | ); |
57 | } |
60 | } |
Line 62... | Line 65... | ||
62 | * Convert a binary string into a hexadecimal string without cache-timing |
65 | * Convert a binary string into a hexadecimal string without cache-timing |
63 | * leaks, returning uppercase letters (as per RFC 4648) |
66 | * leaks, returning uppercase letters (as per RFC 4648) |
64 | * |
67 | * |
65 | * @param string $binString (raw binary) |
68 | * @param string $binString (raw binary) |
66 | * @return string |
69 | * @return string |
67 | * @throws \TypeError |
70 | * @throws TypeError |
68 | */ |
71 | */ |
69 | public static function encodeUpper(string $binString): string |
72 | public static function encodeUpper(string $binString): string |
70 | { |
73 | { |
71 | $hex = ''; |
74 | $hex = ''; |
72 | $len = Binary::safeStrlen($binString); |
75 | $len = Binary::safeStrlen($binString); |
73 | 76 | ||
74 | for ($i = 0; $i < $len; ++$i) { |
77 | for ($i = 0; $i < $len; ++$i) { |
75 | /** @var array<int, int> $chunk */ |
78 | /** @var array<int, int> $chunk */ |
76 | $chunk = \unpack('C', Binary::safeSubstr($binString, $i, 2)); |
79 | $chunk = \unpack('C', $binString[$i]); |
77 | $c = $chunk[1] & 0xf; |
80 | $c = $chunk[1] & 0xf; |
78 | $b = $chunk[1] >> 4; |
81 | $b = $chunk[1] >> 4; |
79 | 82 | ||
80 | $hex .= pack( |
83 | $hex .= \pack( |
81 | 'CC', |
84 | 'CC', |
82 | (55 + $b + ((($b - 10) >> 8) & ~6)), |
85 | (55 + $b + ((($b - 10) >> 8) & ~6)), |
83 | (55 + $c + ((($c - 10) >> 8) & ~6)) |
86 | (55 + $c + ((($c - 10) >> 8) & ~6)) |
84 | ); |
87 | ); |
85 | } |
88 | } |
Line 91... | Line 94... | ||
91 | * leaks |
94 | * leaks |
92 | * |
95 | * |
93 | * @param string $encodedString |
96 | * @param string $encodedString |
94 | * @param bool $strictPadding |
97 | * @param bool $strictPadding |
95 | * @return string (raw binary) |
98 | * @return string (raw binary) |
96 | * @throws \RangeException |
99 | * @throws RangeException |
97 | */ |
100 | */ |
- | 101 | public static function decode( |
|
- | 102 | string $encodedString, |
|
98 | public static function decode(string $encodedString, bool $strictPadding = false): string |
103 | bool $strictPadding = false |
99 | { |
104 | ): string { |
100 | $hex_pos = 0; |
105 | $hex_pos = 0; |
101 | $bin = ''; |
106 | $bin = ''; |
102 | $c_acc = 0; |
107 | $c_acc = 0; |
103 | $hex_len = Binary::safeStrlen($encodedString); |
108 | $hex_len = Binary::safeStrlen($encodedString); |
104 | $state = 0; |
109 | $state = 0; |
105 | if (($hex_len & 1) !== 0) { |
110 | if (($hex_len & 1) !== 0) { |
106 | if ($strictPadding) { |
111 | if ($strictPadding) { |
107 | throw new \RangeException( |
112 | throw new RangeException( |
108 | 'Expected an even number of hexadecimal characters' |
113 | 'Expected an even number of hexadecimal characters' |
109 | ); |
114 | ); |
110 | } else { |
115 | } else { |
111 | $encodedString = '0' . $encodedString; |
116 | $encodedString = '0' . $encodedString; |
112 | ++$hex_len; |
117 | ++$hex_len; |
Line 122... | Line 127... | ||
122 | $c_num0 = ($c_num - 10) >> 8; |
127 | $c_num0 = ($c_num - 10) >> 8; |
123 | $c_alpha = ($c & ~32) - 55; |
128 | $c_alpha = ($c & ~32) - 55; |
124 | $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8; |
129 | $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8; |
125 | 130 | ||
126 | if (($c_num0 | $c_alpha0) === 0) { |
131 | if (($c_num0 | $c_alpha0) === 0) { |
127 | throw new \RangeException( |
132 | throw new RangeException( |
128 | 'Expected hexadecimal character' |
133 | 'Expected hexadecimal character' |
129 | ); |
134 | ); |
130 | } |
135 | } |
131 | $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0); |
136 | $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0); |
132 | if ($state === 0) { |
137 | if ($state === 0) { |