Diff: STRATO-apps/wordpress_03/app/wp-includes/sodium_compat/src/Core/BLAKE2b.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + <?php
2 +
3 + if (class_exists('ParagonIE_Sodium_Core_BLAKE2b', false)) {
4 + return;
5 + }
6 +
7 + /**
8 + * Class ParagonIE_Sodium_Core_BLAKE2b
9 + *
10 + * Based on the work of Devi Mandiri in devi/salt.
11 + */
12 + abstract class ParagonIE_Sodium_Core_BLAKE2b extends ParagonIE_Sodium_Core_Util
13 + {
14 + /**
15 + * @var SplFixedArray
16 + */
17 + protected static $iv;
18 +
19 + /**
20 + * @var array<int, array<int, int>>
21 + */
22 + protected static $sigma = array(
23 + array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
24 + array( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3),
25 + array( 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4),
26 + array( 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8),
27 + array( 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13),
28 + array( 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9),
29 + array( 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11),
30 + array( 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10),
31 + array( 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5),
32 + array( 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0),
33 + array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
34 + array( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3)
35 + );
36 +
37 + const BLOCKBYTES = 128;
38 + const OUTBYTES = 64;
39 + const KEYBYTES = 64;
40 +
41 + /**
42 + * Turn two 32-bit integers into a fixed array representing a 64-bit integer.
43 + *
44 + * @internal You should not use this directly from another application
45 + *
46 + * @param int $high
47 + * @param int $low
48 + * @return SplFixedArray
49 + * @psalm-suppress MixedAssignment
50 + */
51 + public static function new64($high, $low)
52 + {
53 + if (PHP_INT_SIZE === 4) {
54 + throw new SodiumException("Error, use 32-bit");
55 + }
56 + $i64 = new SplFixedArray(2);
57 + $i64[0] = $high & 0xffffffff;
58 + $i64[1] = $low & 0xffffffff;
59 + return $i64;
60 + }
61 +
62 + /**
63 + * Convert an arbitrary number into an SplFixedArray of two 32-bit integers
64 + * that represents a 64-bit integer.
65 + *
66 + * @internal You should not use this directly from another application
67 + *
68 + * @param int $num
69 + * @return SplFixedArray
70 + */
71 + protected static function to64($num)
72 + {
73 + list($hi, $lo) = self::numericTo64BitInteger($num);
74 + return self::new64($hi, $lo);
75 + }
76 +
77 + /**
78 + * Adds two 64-bit integers together, returning their sum as a SplFixedArray
79 + * containing two 32-bit integers (representing a 64-bit integer).
80 + *
81 + * @internal You should not use this directly from another application
82 + *
83 + * @param SplFixedArray $x
84 + * @param SplFixedArray $y
85 + * @return SplFixedArray
86 + * @psalm-suppress MixedArgument
87 + * @psalm-suppress MixedAssignment
88 + * @psalm-suppress MixedOperand
89 + */
90 + protected static function add64($x, $y)
91 + {
92 + if (PHP_INT_SIZE === 4) {
93 + throw new SodiumException("Error, use 32-bit");
94 + }
95 + $l = ($x[1] + $y[1]) & 0xffffffff;
96 + return self::new64(
97 + (int) ($x[0] + $y[0] + (
98 + ($l < $x[1]) ? 1 : 0
99 + )),
100 + (int) $l
101 + );
102 + }
103 +
104 + /**
105 + * @internal You should not use this directly from another application
106 + *
107 + * @param SplFixedArray $x
108 + * @param SplFixedArray $y
109 + * @param SplFixedArray $z
110 + * @return SplFixedArray
111 + */
112 + protected static function add364($x, $y, $z)
113 + {
114 + return self::add64($x, self::add64($y, $z));
115 + }
116 +
117 + /**
118 + * @internal You should not use this directly from another application
119 + *
120 + * @param SplFixedArray $x
121 + * @param SplFixedArray $y
122 + * @return SplFixedArray
123 + * @throws SodiumException
124 + * @throws TypeError
125 + */
126 + protected static function xor64(SplFixedArray $x, SplFixedArray $y)
127 + {
128 + if (PHP_INT_SIZE === 4) {
129 + throw new SodiumException("Error, use 32-bit");
130 + }
131 + if (!is_numeric($x[0])) {
132 + throw new SodiumException('x[0] is not an integer');
133 + }
134 + if (!is_numeric($x[1])) {
135 + throw new SodiumException('x[1] is not an integer');
136 + }
137 + if (!is_numeric($y[0])) {
138 + throw new SodiumException('y[0] is not an integer');
139 + }
140 + if (!is_numeric($y[1])) {
141 + throw new SodiumException('y[1] is not an integer');
142 + }
143 + return self::new64(
144 + (int) (($x[0] ^ $y[0]) & 0xffffffff),
145 + (int) (($x[1] ^ $y[1]) & 0xffffffff)
146 + );
147 + }
148 +
149 + /**
150 + * @internal You should not use this directly from another application
151 + *
152 + * @param SplFixedArray $x
153 + * @param int $c
154 + * @return SplFixedArray
155 + * @psalm-suppress MixedAssignment
156 + */
157 + public static function rotr64($x, $c)
158 + {
159 + if (PHP_INT_SIZE === 4) {
160 + throw new SodiumException("Error, use 32-bit");
161 + }
162 + if ($c >= 64) {
163 + $c %= 64;
164 + }
165 + if ($c >= 32) {
166 + /** @var int $tmp */
167 + $tmp = $x[0];
168 + $x[0] = $x[1];
169 + $x[1] = $tmp;
170 + $c -= 32;
171 + }
172 + if ($c === 0) {
173 + return $x;
174 + }
175 +
176 + $l0 = 0;
177 + $c = 64 - $c;
178 +
179 + /** @var int $c */
180 + if ($c < 32) {
181 + $h0 = ((int) ($x[0]) << $c) | (
182 + (
183 + (int) ($x[1]) & ((1 << $c) - 1)
184 + <<
185 + (32 - $c)
186 + ) >> (32 - $c)
187 + );
188 + $l0 = (int) ($x[1]) << $c;
189 + } else {
190 + $h0 = (int) ($x[1]) << ($c - 32);
191 + }
192 +
193 + $h1 = 0;
194 + $c1 = 64 - $c;
195 +
196 + if ($c1 < 32) {
197 + $h1 = (int) ($x[0]) >> $c1;
198 + $l1 = ((int) ($x[1]) >> $c1) | ((int) ($x[0]) & ((1 << $c1) - 1)) << (32 - $c1);
199 + } else {
200 + $l1 = (int) ($x[0]) >> ($c1 - 32);
201 + }
202 +
203 + return self::new64($h0 | $h1, $l0 | $l1);
204 + }
205 +
206 + /**
207 + * @internal You should not use this directly from another application
208 + *
209 + * @param SplFixedArray $x
210 + * @return int
211 + * @psalm-suppress MixedOperand
212 + */
213 + protected static function flatten64($x)
214 + {
215 + return (int) ($x[0] * 4294967296 + $x[1]);
216 + }
217 +
218 + /**
219 + * @internal You should not use this directly from another application
220 + *
221 + * @param SplFixedArray $x
222 + * @param int $i
223 + * @return SplFixedArray
224 + * @psalm-suppress MixedArgument
225 + * @psalm-suppress MixedArrayOffset
226 + */
227 + protected static function load64(SplFixedArray $x, $i)
228 + {
229 + /** @var int $l */
230 + $l = (int) ($x[$i])
231 + | ((int) ($x[$i+1]) << 8)
232 + | ((int) ($x[$i+2]) << 16)
233 + | ((int) ($x[$i+3]) << 24);
234 + /** @var int $h */
235 + $h = (int) ($x[$i+4])
236 + | ((int) ($x[$i+5]) << 8)
237 + | ((int) ($x[$i+6]) << 16)
238 + | ((int) ($x[$i+7]) << 24);
239 + return self::new64($h, $l);
240 + }
241 +
242 + /**
243 + * @internal You should not use this directly from another application
244 + *
245 + * @param SplFixedArray $x
246 + * @param int $i
247 + * @param SplFixedArray $u
248 + * @return void
249 + * @psalm-suppress MixedAssignment
250 + */
251 + protected static function store64(SplFixedArray $x, $i, SplFixedArray $u)
252 + {
253 + $maxLength = $x->getSize() - 1;
254 + for ($j = 0; $j < 8; ++$j) {
255 + /*
256 + [0, 1, 2, 3, 4, 5, 6, 7]
257 + ... becomes ...
258 + [0, 0, 0, 0, 1, 1, 1, 1]
259 + */
260 + /** @var int $uIdx */
261 + $uIdx = ((7 - $j) & 4) >> 2;
262 + $x[$i] = ((int) ($u[$uIdx]) & 0xff);
263 + if (++$i > $maxLength) {
264 + return;
265 + }
266 + /** @psalm-suppress MixedOperand */
267 + $u[$uIdx] >>= 8;
268 + }
269 + }
270 +
271 + /**
272 + * This just sets the $iv static variable.
273 + *
274 + * @internal You should not use this directly from another application
275 + *
276 + * @return void
277 + */
278 + public static function pseudoConstructor()
279 + {
280 + static $called = false;
281 + if ($called) {
282 + return;
283 + }
284 + self::$iv = new SplFixedArray(8);
285 + self::$iv[0] = self::new64(0x6a09e667, 0xf3bcc908);
286 + self::$iv[1] = self::new64(0xbb67ae85, 0x84caa73b);
287 + self::$iv[2] = self::new64(0x3c6ef372, 0xfe94f82b);
288 + self::$iv[3] = self::new64(0xa54ff53a, 0x5f1d36f1);
289 + self::$iv[4] = self::new64(0x510e527f, 0xade682d1);
290 + self::$iv[5] = self::new64(0x9b05688c, 0x2b3e6c1f);
291 + self::$iv[6] = self::new64(0x1f83d9ab, 0xfb41bd6b);
292 + self::$iv[7] = self::new64(0x5be0cd19, 0x137e2179);
293 +
294 + $called = true;
295 + }
296 +
297 + /**
298 + * Returns a fresh BLAKE2 context.
299 + *
300 + * @internal You should not use this directly from another application
301 + *
302 + * @return SplFixedArray
303 + * @psalm-suppress MixedAssignment
304 + * @psalm-suppress MixedArrayAccess
305 + * @psalm-suppress MixedArrayAssignment
306 + */
307 + protected static function context()
308 + {
309 + $ctx = new SplFixedArray(6);
310 + $ctx[0] = new SplFixedArray(8); // h
311 + $ctx[1] = new SplFixedArray(2); // t
312 + $ctx[2] = new SplFixedArray(2); // f
313 + $ctx[3] = new SplFixedArray(256); // buf
314 + $ctx[4] = 0; // buflen
315 + $ctx[5] = 0; // last_node (uint8_t)
316 +
317 + for ($i = 8; $i--;) {
318 + $ctx[0][$i] = self::$iv[$i];
319 + }
320 + for ($i = 256; $i--;) {
321 + $ctx[3][$i] = 0;
322 + }
323 +
324 + $zero = self::new64(0, 0);
325 + $ctx[1][0] = $zero;
326 + $ctx[1][1] = $zero;
327 + $ctx[2][0] = $zero;
328 + $ctx[2][1] = $zero;
329 +
330 + return $ctx;
331 + }
332 +
333 + /**
334 + * @internal You should not use this directly from another application
335 + *
336 + * @param SplFixedArray $ctx
337 + * @param SplFixedArray $buf
338 + * @return void
339 + * @throws SodiumException
340 + * @throws TypeError
341 + * @psalm-suppress MixedArgument
342 + * @psalm-suppress MixedAssignment
343 + * @psalm-suppress MixedArrayAccess
344 + * @psalm-suppress MixedArrayAssignment
345 + * @psalm-suppress MixedArrayOffset
346 + */
347 + protected static function compress(SplFixedArray $ctx, SplFixedArray $buf)
348 + {
349 + $m = new SplFixedArray(16);
350 + $v = new SplFixedArray(16);
351 +
352 + for ($i = 16; $i--;) {
353 + $m[$i] = self::load64($buf, $i << 3);
354 + }
355 +
356 + for ($i = 8; $i--;) {
357 + $v[$i] = $ctx[0][$i];
358 + }
359 +
360 + $v[ 8] = self::$iv[0];
361 + $v[ 9] = self::$iv[1];
362 + $v[10] = self::$iv[2];
363 + $v[11] = self::$iv[3];
364 +
365 + $v[12] = self::xor64($ctx[1][0], self::$iv[4]);
366 + $v[13] = self::xor64($ctx[1][1], self::$iv[5]);
367 + $v[14] = self::xor64($ctx[2][0], self::$iv[6]);
368 + $v[15] = self::xor64($ctx[2][1], self::$iv[7]);
369 +
370 + for ($r = 0; $r < 12; ++$r) {
371 + $v = self::G($r, 0, 0, 4, 8, 12, $v, $m);
372 + $v = self::G($r, 1, 1, 5, 9, 13, $v, $m);
373 + $v = self::G($r, 2, 2, 6, 10, 14, $v, $m);
374 + $v = self::G($r, 3, 3, 7, 11, 15, $v, $m);
375 + $v = self::G($r, 4, 0, 5, 10, 15, $v, $m);
376 + $v = self::G($r, 5, 1, 6, 11, 12, $v, $m);
377 + $v = self::G($r, 6, 2, 7, 8, 13, $v, $m);
378 + $v = self::G($r, 7, 3, 4, 9, 14, $v, $m);
379 + }
380 +
381 + for ($i = 8; $i--;) {
382 + $ctx[0][$i] = self::xor64(
383 + $ctx[0][$i], self::xor64($v[$i], $v[$i+8])
384 + );
385 + }
386 + }
387 +
388 + /**
389 + * @internal You should not use this directly from another application
390 + *
391 + * @param int $r
392 + * @param int $i
393 + * @param int $a
394 + * @param int $b
395 + * @param int $c
396 + * @param int $d
397 + * @param SplFixedArray $v
398 + * @param SplFixedArray $m
399 + * @return SplFixedArray
400 + * @throws SodiumException
401 + * @throws TypeError
402 + * @psalm-suppress MixedArgument
403 + * @psalm-suppress MixedArrayOffset
404 + */
405 + public static function G($r, $i, $a, $b, $c, $d, SplFixedArray $v, SplFixedArray $m)
406 + {
407 + $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][$i << 1]]);
408 + $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 32);
409 + $v[$c] = self::add64($v[$c], $v[$d]);
410 + $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 24);
411 + $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][($i << 1) + 1]]);
412 + $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 16);
413 + $v[$c] = self::add64($v[$c], $v[$d]);
414 + $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 63);
415 + return $v;
416 + }
417 +
418 + /**
419 + * @internal You should not use this directly from another application
420 + *
421 + * @param SplFixedArray $ctx
422 + * @param int $inc
423 + * @return void
424 + * @throws SodiumException
425 + * @psalm-suppress MixedArgument
426 + * @psalm-suppress MixedArrayAccess
427 + * @psalm-suppress MixedArrayAssignment
428 + */
429 + public static function increment_counter($ctx, $inc)
430 + {
431 + if ($inc < 0) {
432 + throw new SodiumException('Increasing by a negative number makes no sense.');
433 + }
434 + $t = self::to64($inc);
435 + # S->t is $ctx[1] in our implementation
436 +
437 + # S->t[0] = ( uint64_t )( t >> 0 );
438 + $ctx[1][0] = self::add64($ctx[1][0], $t);
439 +
440 + # S->t[1] += ( S->t[0] < inc );
441 + if (self::flatten64($ctx[1][0]) < $inc) {
442 + $ctx[1][1] = self::add64($ctx[1][1], self::to64(1));
443 + }
444 + }
445 +
446 + /**
447 + * @internal You should not use this directly from another application
448 + *
449 + * @param SplFixedArray $ctx
450 + * @param SplFixedArray $p
451 + * @param int $plen
452 + * @return void
453 + * @throws SodiumException
454 + * @throws TypeError
455 + * @psalm-suppress MixedArgument
456 + * @psalm-suppress MixedAssignment
457 + * @psalm-suppress MixedArrayAccess
458 + * @psalm-suppress MixedArrayAssignment
459 + * @psalm-suppress MixedArrayOffset
460 + * @psalm-suppress MixedOperand
461 + */
462 + public static function update(SplFixedArray $ctx, SplFixedArray $p, $plen)
463 + {
464 + self::pseudoConstructor();
465 +
466 + $offset = 0;
467 + while ($plen > 0) {
468 + $left = $ctx[4];
469 + $fill = 256 - $left;
470 +
471 + if ($plen > $fill) {
472 + # memcpy( S->buf + left, in, fill ); /* Fill buffer */
473 + for ($i = $fill; $i--;) {
474 + $ctx[3][$i + $left] = $p[$i + $offset];
475 + }
476 +
477 + # S->buflen += fill;
478 + $ctx[4] += $fill;
479 +
480 + # blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
481 + self::increment_counter($ctx, 128);
482 +
483 + # blake2b_compress( S, S->buf ); /* Compress */
484 + self::compress($ctx, $ctx[3]);
485 +
486 + # memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); /* Shift buffer left */
487 + for ($i = 128; $i--;) {
488 + $ctx[3][$i] = $ctx[3][$i + 128];
489 + }
490 +
491 + # S->buflen -= BLAKE2B_BLOCKBYTES;
492 + $ctx[4] -= 128;
493 +
494 + # in += fill;
495 + $offset += $fill;
496 +
497 + # inlen -= fill;
498 + $plen -= $fill;
499 + } else {
500 + for ($i = $plen; $i--;) {
501 + $ctx[3][$i + $left] = $p[$i + $offset];
502 + }
503 + $ctx[4] += $plen;
504 + $offset += $plen;
505 + $plen -= $plen;
506 + }
507 + }
508 + }
509 +
510 + /**
511 + * @internal You should not use this directly from another application
512 + *
513 + * @param SplFixedArray $ctx
514 + * @param SplFixedArray $out
515 + * @return SplFixedArray
516 + * @throws SodiumException
517 + * @throws TypeError
518 + * @psalm-suppress MixedArgument
519 + * @psalm-suppress MixedAssignment
520 + * @psalm-suppress MixedArrayAccess
521 + * @psalm-suppress MixedArrayAssignment
522 + * @psalm-suppress MixedArrayOffset
523 + * @psalm-suppress MixedOperand
524 + */
525 + public static function finish(SplFixedArray $ctx, SplFixedArray $out)
526 + {
527 + self::pseudoConstructor();
528 + if ($ctx[4] > 128) {
529 + self::increment_counter($ctx, 128);
530 + self::compress($ctx, $ctx[3]);
531 + $ctx[4] -= 128;
532 + if ($ctx[4] > 128) {
533 + throw new SodiumException('Failed to assert that buflen <= 128 bytes');
534 + }
535 + for ($i = $ctx[4]; $i--;) {
536 + $ctx[3][$i] = $ctx[3][$i + 128];
537 + }
538 + }
539 +
540 + self::increment_counter($ctx, $ctx[4]);
541 + $ctx[2][0] = self::new64(0xffffffff, 0xffffffff);
542 +
543 + for ($i = 256 - $ctx[4]; $i--;) {
544 + $ctx[3][$i+$ctx[4]] = 0;
545 + }
546 +
547 + self::compress($ctx, $ctx[3]);
548 +
549 + $i = (int) (($out->getSize() - 1) / 8);
550 + for (; $i >= 0; --$i) {
551 + self::store64($out, $i << 3, $ctx[0][$i]);
552 + }
553 + return $out;
554 + }
555 +
556 + /**
557 + * @internal You should not use this directly from another application
558 + *
559 + * @param SplFixedArray|null $key
560 + * @param int $outlen
561 + * @param SplFixedArray|null $salt
562 + * @param SplFixedArray|null $personal
563 + * @return SplFixedArray
564 + * @throws SodiumException
565 + * @throws TypeError
566 + * @psalm-suppress MixedArgument
567 + * @psalm-suppress MixedAssignment
568 + * @psalm-suppress MixedArrayAccess
569 + * @psalm-suppress MixedArrayAssignment
570 + * @psalm-suppress MixedArrayOffset
571 + */
572 + public static function init(
573 + $key = null,
574 + $outlen = 64,
575 + $salt = null,
576 + $personal = null
577 + ) {
578 + self::pseudoConstructor();
579 + $klen = 0;
580 +
581 + if ($key !== null) {
582 + if (count($key) > 64) {
583 + throw new SodiumException('Invalid key size');
584 + }
585 + $klen = count($key);
586 + }
587 +
588 + if ($outlen > 64) {
589 + throw new SodiumException('Invalid output size');
590 + }
591 +
592 + $ctx = self::context();
593 +
594 + $p = new SplFixedArray(64);
595 + // Zero our param buffer...
596 + for ($i = 64; --$i;) {
597 + $p[$i] = 0;
598 + }
599 +
600 + $p[0] = $outlen; // digest_length
601 + $p[1] = $klen; // key_length
602 + $p[2] = 1; // fanout
603 + $p[3] = 1; // depth
604 +
605 + if ($salt instanceof SplFixedArray) {
606 + // salt: [32] through [47]
607 + for ($i = 0; $i < 16; ++$i) {
608 + $p[32 + $i] = (int) $salt[$i];
609 + }
610 + }
611 + if ($personal instanceof SplFixedArray) {
612 + // personal: [48] through [63]
613 + for ($i = 0; $i < 16; ++$i) {
614 + $p[48 + $i] = (int) $personal[$i];
615 + }
616 + }
617 +
618 + $ctx[0][0] = self::xor64(
619 + $ctx[0][0],
620 + self::load64($p, 0)
621 + );
622 + if ($salt instanceof SplFixedArray || $personal instanceof SplFixedArray) {
623 + // We need to do what blake2b_init_param() does:
624 + for ($i = 1; $i < 8; ++$i) {
625 + $ctx[0][$i] = self::xor64(
626 + $ctx[0][$i],
627 + self::load64($p, $i << 3)
628 + );
629 + }
630 + }
631 +
632 + if ($klen > 0 && $key instanceof SplFixedArray) {
633 + $block = new SplFixedArray(128);
634 + for ($i = 128; $i--;) {
635 + $block[$i] = 0;
636 + }
637 + for ($i = $klen; $i--;) {
638 + $block[$i] = $key[$i];
639 + }
640 + self::update($ctx, $block, 128);
641 + $ctx[4] = 128;
642 + }
643 +
644 + return $ctx;
645 + }
646 +
647 + /**
648 + * Convert a string into an SplFixedArray of integers
649 + *
650 + * @internal You should not use this directly from another application
651 + *
652 + * @param string $str
653 + * @return SplFixedArray
654 + * @psalm-suppress MixedArgumentTypeCoercion
655 + */
656 + public static function stringToSplFixedArray($str = '')
657 + {
658 + $values = unpack('C*', $str);
659 + return SplFixedArray::fromArray(array_values($values));
660 + }
661 +
662 + /**
663 + * Convert an SplFixedArray of integers into a string
664 + *
665 + * @internal You should not use this directly from another application
666 + *
667 + * @param SplFixedArray $a
668 + * @return string
669 + * @throws TypeError
670 + */
671 + public static function SplFixedArrayToString(SplFixedArray $a)
672 + {
673 + /**
674 + * @var array<int, int|string> $arr
675 + */
676 + $arr = $a->toArray();
677 + $c = $a->count();
678 + array_unshift($arr, str_repeat('C', $c));
679 + return (string) (call_user_func_array('pack', $arr));
680 + }
681 +
682 + /**
683 + * @internal You should not use this directly from another application
684 + *
685 + * @param SplFixedArray $ctx
686 + * @return string
687 + * @throws TypeError
688 + * @psalm-suppress MixedArgument
689 + * @psalm-suppress MixedAssignment
690 + * @psalm-suppress MixedArrayAccess
691 + * @psalm-suppress MixedArrayAssignment
692 + * @psalm-suppress MixedArrayOffset
693 + * @psalm-suppress MixedMethodCall
694 + */
695 + public static function contextToString(SplFixedArray $ctx)
696 + {
697 + $str = '';
698 + /** @var array<int, array<int, int>> $ctxA */
699 + $ctxA = $ctx[0]->toArray();
700 +
701 + # uint64_t h[8];
702 + for ($i = 0; $i < 8; ++$i) {
703 + $str .= self::store32_le($ctxA[$i][1]);
704 + $str .= self::store32_le($ctxA[$i][0]);
705 + }
706 +
707 + # uint64_t t[2];
708 + # uint64_t f[2];
709 + for ($i = 1; $i < 3; ++$i) {
710 + $ctxA = $ctx[$i]->toArray();
711 + $str .= self::store32_le($ctxA[0][1]);
712 + $str .= self::store32_le($ctxA[0][0]);
713 + $str .= self::store32_le($ctxA[1][1]);
714 + $str .= self::store32_le($ctxA[1][0]);
715 + }
716 +
717 + # uint8_t buf[2 * 128];
718 + $str .= self::SplFixedArrayToString($ctx[3]);
719 +
720 + /** @var int $ctx4 */
721 + $ctx4 = (int) $ctx[4];
722 +
723 + # size_t buflen;
724 + $str .= implode('', array(
725 + self::intToChr($ctx4 & 0xff),
726 + self::intToChr(($ctx4 >> 8) & 0xff),
727 + self::intToChr(($ctx4 >> 16) & 0xff),
728 + self::intToChr(($ctx4 >> 24) & 0xff),
729 + self::intToChr(($ctx4 >> 32) & 0xff),
730 + self::intToChr(($ctx4 >> 40) & 0xff),
731 + self::intToChr(($ctx4 >> 48) & 0xff),
732 + self::intToChr(($ctx4 >> 56) & 0xff)
733 + ));
734 + # uint8_t last_node;
735 + return $str . self::intToChr($ctx[5]) . str_repeat("\x00", 23);
736 + }
737 +
738 + /**
739 + * Creates an SplFixedArray containing other SplFixedArray elements, from
740 + * a string (compatible with \Sodium\crypto_generichash_{init, update, final})
741 + *
742 + * @internal You should not use this directly from another application
743 + *
744 + * @param string $string
745 + * @return SplFixedArray
746 + * @throws SodiumException
747 + * @throws TypeError
748 + * @psalm-suppress MixedArrayAssignment
749 + */
750 + public static function stringToContext($string)
751 + {
752 + $ctx = self::context();
753 +
754 + # uint64_t h[8];
755 + for ($i = 0; $i < 8; ++$i) {
756 + $ctx[0][$i] = SplFixedArray::fromArray(
757 + array(
758 + self::load_4(
759 + self::substr($string, (($i << 3) + 4), 4)
760 + ),
761 + self::load_4(
762 + self::substr($string, (($i << 3) + 0), 4)
763 + )
764 + )
765 + );
766 + }
767 +
768 + # uint64_t t[2];
769 + # uint64_t f[2];
770 + for ($i = 1; $i < 3; ++$i) {
771 + $ctx[$i][1] = SplFixedArray::fromArray(
772 + array(
773 + self::load_4(self::substr($string, 76 + (($i - 1) << 4), 4)),
774 + self::load_4(self::substr($string, 72 + (($i - 1) << 4), 4))
775 + )
776 + );
777 + $ctx[$i][0] = SplFixedArray::fromArray(
778 + array(
779 + self::load_4(self::substr($string, 68 + (($i - 1) << 4), 4)),
780 + self::load_4(self::substr($string, 64 + (($i - 1) << 4), 4))
781 + )
782 + );
783 + }
784 +
785 + # uint8_t buf[2 * 128];
786 + $ctx[3] = self::stringToSplFixedArray(self::substr($string, 96, 256));
787 +
788 + # uint8_t buf[2 * 128];
789 + $int = 0;
790 + for ($i = 0; $i < 8; ++$i) {
791 + $int |= self::chrToInt($string[352 + $i]) << ($i << 3);
792 + }
793 + $ctx[4] = $int;
794 +
795 + return $ctx;
796 + }
797 + }
798 +