PluginProbe ʕ •ᴥ•ʔ
ShareThis Dashboard for Google Analytics / trunk
ShareThis Dashboard for Google Analytics vtrunk
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 / Base64.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
Base64.php
315 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 Base64
34 * [A-Z][a-z][0-9]+/
35 *
36 * @package ParagonIE\ConstantTime
37 */
38 abstract class Base64 implements EncoderInterface
39 {
40 /**
41 * Encode into Base64
42 *
43 * Base64 character set "[A-Z][a-z][0-9]+/"
44 *
45 * @param string $binString
46 * @return string
47 *
48 * @throws TypeError
49 */
50 public static function encode(string $binString): string
51 {
52 return static::doEncode($binString, true);
53 }
54
55 /**
56 * Encode into Base64, no = padding
57 *
58 * Base64 character set "[A-Z][a-z][0-9]+/"
59 *
60 * @param string $src
61 * @return string
62 *
63 * @throws TypeError
64 */
65 public static function encodeUnpadded(string $src): string
66 {
67 return static::doEncode($src, false);
68 }
69
70 /**
71 * @param string $src
72 * @param bool $pad Include = padding?
73 * @return string
74 *
75 * @throws TypeError
76 */
77 protected static function doEncode(string $src, bool $pad = true): string
78 {
79 $dest = '';
80 $srcLen = Binary::safeStrlen($src);
81 // Main loop (no padding):
82 for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
83 /** @var array<int, int> $chunk */
84 $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 3));
85 $b0 = $chunk[1];
86 $b1 = $chunk[2];
87 $b2 = $chunk[3];
88
89 $dest .=
90 static::encode6Bits( $b0 >> 2 ) .
91 static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
92 static::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
93 static::encode6Bits( $b2 & 63);
94 }
95 // The last chunk, which may have padding:
96 if ($i < $srcLen) {
97 /** @var array<int, int> $chunk */
98 $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
99 $b0 = $chunk[1];
100 if ($i + 1 < $srcLen) {
101 $b1 = $chunk[2];
102 $dest .=
103 static::encode6Bits($b0 >> 2) .
104 static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
105 static::encode6Bits(($b1 << 2) & 63);
106 if ($pad) {
107 $dest .= '=';
108 }
109 } else {
110 $dest .=
111 static::encode6Bits( $b0 >> 2) .
112 static::encode6Bits(($b0 << 4) & 63);
113 if ($pad) {
114 $dest .= '==';
115 }
116 }
117 }
118 return $dest;
119 }
120
121 /**
122 * decode from base64 into binary
123 *
124 * Base64 character set "./[A-Z][a-z][0-9]"
125 *
126 * @param string $encodedString
127 * @param bool $strictPadding
128 * @return string
129 *
130 * @throws RangeException
131 * @throws TypeError
132 * @psalm-suppress RedundantCondition
133 */
134 public static function decode(string $encodedString, bool $strictPadding = false): string
135 {
136 // Remove padding
137 $srcLen = Binary::safeStrlen($encodedString);
138 if ($srcLen === 0) {
139 return '';
140 }
141
142 if ($strictPadding) {
143 if (($srcLen & 3) === 0) {
144 if ($encodedString[$srcLen - 1] === '=') {
145 $srcLen--;
146 if ($encodedString[$srcLen - 1] === '=') {
147 $srcLen--;
148 }
149 }
150 }
151 if (($srcLen & 3) === 1) {
152 throw new RangeException(
153 'Incorrect padding'
154 );
155 }
156 if ($encodedString[$srcLen - 1] === '=') {
157 throw new RangeException(
158 'Incorrect padding'
159 );
160 }
161 } else {
162 $encodedString = \rtrim($encodedString, '=');
163 $srcLen = Binary::safeStrlen($encodedString);
164 }
165
166 $err = 0;
167 $dest = '';
168 // Main loop (no padding):
169 for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
170 /** @var array<int, int> $chunk */
171 $chunk = \unpack('C*', Binary::safeSubstr($encodedString, $i, 4));
172 $c0 = static::decode6Bits($chunk[1]);
173 $c1 = static::decode6Bits($chunk[2]);
174 $c2 = static::decode6Bits($chunk[3]);
175 $c3 = static::decode6Bits($chunk[4]);
176
177 $dest .= \pack(
178 'CCC',
179 ((($c0 << 2) | ($c1 >> 4)) & 0xff),
180 ((($c1 << 4) | ($c2 >> 2)) & 0xff),
181 ((($c2 << 6) | $c3 ) & 0xff)
182 );
183 $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
184 }
185 // The last chunk, which may have padding:
186 if ($i < $srcLen) {
187 /** @var array<int, int> $chunk */
188 $chunk = \unpack('C*', Binary::safeSubstr($encodedString, $i, $srcLen - $i));
189 $c0 = static::decode6Bits($chunk[1]);
190
191 if ($i + 2 < $srcLen) {
192 $c1 = static::decode6Bits($chunk[2]);
193 $c2 = static::decode6Bits($chunk[3]);
194 $dest .= \pack(
195 'CC',
196 ((($c0 << 2) | ($c1 >> 4)) & 0xff),
197 ((($c1 << 4) | ($c2 >> 2)) & 0xff)
198 );
199 $err |= ($c0 | $c1 | $c2) >> 8;
200 if ($strictPadding) {
201 $err |= ($c2 << 6) & 0xff;
202 }
203 } elseif ($i + 1 < $srcLen) {
204 $c1 = static::decode6Bits($chunk[2]);
205 $dest .= \pack(
206 'C',
207 ((($c0 << 2) | ($c1 >> 4)) & 0xff)
208 );
209 $err |= ($c0 | $c1) >> 8;
210 if ($strictPadding) {
211 $err |= ($c1 << 4) & 0xff;
212 }
213 } elseif ($strictPadding) {
214 $err |= 1;
215 }
216 }
217 $check = ($err === 0);
218 if (!$check) {
219 throw new RangeException(
220 'Base64::decode() only expects characters in the correct base64 alphabet'
221 );
222 }
223 return $dest;
224 }
225
226 /**
227 * @param string $encodedString
228 * @return string
229 */
230 public static function decodeNoPadding(string $encodedString): string
231 {
232 $srcLen = Binary::safeStrlen($encodedString);
233 if ($srcLen === 0) {
234 return '';
235 }
236 if (($srcLen & 3) === 0) {
237 if ($encodedString[$srcLen - 1] === '=') {
238 throw new InvalidArgumentException(
239 "decodeNoPadding() doesn't tolerate padding"
240 );
241 }
242 if (($srcLen & 3) > 1) {
243 if ($encodedString[$srcLen - 2] === '=') {
244 throw new InvalidArgumentException(
245 "decodeNoPadding() doesn't tolerate padding"
246 );
247 }
248 }
249 }
250 return static::decode(
251 $encodedString,
252 true
253 );
254 }
255
256 /**
257 * Uses bitwise operators instead of table-lookups to turn 6-bit integers
258 * into 8-bit integers.
259 *
260 * Base64 character set:
261 * [A-Z] [a-z] [0-9] + /
262 * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
263 *
264 * @param int $src
265 * @return int
266 */
267 protected static function decode6Bits(int $src): int
268 {
269 $ret = -1;
270
271 // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
272 $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
273
274 // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
275 $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
276
277 // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
278 $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
279
280 // if ($src == 0x2b) $ret += 62 + 1;
281 $ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63;
282
283 // if ($src == 0x2f) ret += 63 + 1;
284 $ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64;
285
286 return $ret;
287 }
288
289 /**
290 * Uses bitwise operators instead of table-lookups to turn 8-bit integers
291 * into 6-bit integers.
292 *
293 * @param int $src
294 * @return string
295 */
296 protected static function encode6Bits(int $src): string
297 {
298 $diff = 0x41;
299
300 // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
301 $diff += ((25 - $src) >> 8) & 6;
302
303 // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
304 $diff -= ((51 - $src) >> 8) & 75;
305
306 // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15
307 $diff -= ((61 - $src) >> 8) & 15;
308
309 // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3
310 $diff += ((62 - $src) >> 8) & 3;
311
312 return \pack('C', $src + $diff);
313 }
314 }
315