221 * @throws SodiumException |
221 * @throws SodiumException |
222 * @throws TypeError |
222 * @throws TypeError |
223 */ |
223 */ |
224 protected static function context() |
224 protected static function context() |
225 { |
225 { |
226 $ctx = new SplFixedArray(5); |
226 $ctx = new SplFixedArray(6); |
227 $ctx[0] = new SplFixedArray(8); // h |
227 $ctx[0] = new SplFixedArray(8); // h |
228 $ctx[1] = new SplFixedArray(2); // t |
228 $ctx[1] = new SplFixedArray(2); // t |
229 $ctx[2] = new SplFixedArray(2); // f |
229 $ctx[2] = new SplFixedArray(2); // f |
230 $ctx[3] = new SplFixedArray(256); // buf |
230 $ctx[3] = new SplFixedArray(256); // buf |
231 $ctx[4] = 0; // buflen |
231 $ctx[4] = 0; // buflen |
|
232 $ctx[5] = 0; // last_node (uint8_t) |
232 |
233 |
233 for ($i = 8; $i--;) { |
234 for ($i = 8; $i--;) { |
234 $ctx[0][$i] = self::$iv[$i]; |
235 $ctx[0][$i] = self::$iv[$i]; |
235 } |
236 } |
236 for ($i = 256; $i--;) { |
237 for ($i = 256; $i--;) { |
480 /** |
481 /** |
481 * @internal You should not use this directly from another application |
482 * @internal You should not use this directly from another application |
482 * |
483 * |
483 * @param SplFixedArray|null $key |
484 * @param SplFixedArray|null $key |
484 * @param int $outlen |
485 * @param int $outlen |
|
486 * @param SplFixedArray|null $salt |
|
487 * @param SplFixedArray|null $personal |
485 * @return SplFixedArray |
488 * @return SplFixedArray |
486 * @throws SodiumException |
489 * @throws SodiumException |
487 * @throws TypeError |
490 * @throws TypeError |
488 * @psalm-suppress MixedArgument |
491 * @psalm-suppress MixedArgument |
489 * @psalm-suppress MixedAssignment |
492 * @psalm-suppress MixedAssignment |
490 * @psalm-suppress MixedArrayAccess |
493 * @psalm-suppress MixedArrayAccess |
491 * @psalm-suppress MixedArrayAssignment |
494 * @psalm-suppress MixedArrayAssignment |
492 * @psalm-suppress MixedMethodCall |
495 * @psalm-suppress MixedMethodCall |
493 */ |
496 */ |
494 public static function init($key = null, $outlen = 64) |
497 public static function init( |
495 { |
498 $key = null, |
|
499 $outlen = 64, |
|
500 $salt = null, |
|
501 $personal = null |
|
502 ) { |
496 self::pseudoConstructor(); |
503 self::pseudoConstructor(); |
497 $klen = 0; |
504 $klen = 0; |
498 |
505 |
499 if ($key !== null) { |
506 if ($key !== null) { |
500 if (count($key) > 64) { |
507 if (count($key) > 64) { |
508 } |
515 } |
509 |
516 |
510 $ctx = self::context(); |
517 $ctx = self::context(); |
511 |
518 |
512 $p = new SplFixedArray(64); |
519 $p = new SplFixedArray(64); |
|
520 // Zero our param buffer... |
513 for ($i = 64; --$i;) { |
521 for ($i = 64; --$i;) { |
514 $p[$i] = 0; |
522 $p[$i] = 0; |
515 } |
523 } |
516 |
524 |
517 $p[0] = $outlen; // digest_length |
525 $p[0] = $outlen; // digest_length |
518 $p[1] = $klen; // key_length |
526 $p[1] = $klen; // key_length |
519 $p[2] = 1; // fanout |
527 $p[2] = 1; // fanout |
520 $p[3] = 1; // depth |
528 $p[3] = 1; // depth |
521 |
529 |
|
530 if ($salt instanceof SplFixedArray) { |
|
531 // salt: [32] through [47] |
|
532 for ($i = 0; $i < 16; ++$i) { |
|
533 $p[32 + $i] = (int) $salt[$i]; |
|
534 } |
|
535 } |
|
536 if ($personal instanceof SplFixedArray) { |
|
537 // personal: [48] through [63] |
|
538 for ($i = 0; $i < 16; ++$i) { |
|
539 $p[48 + $i] = (int) $personal[$i]; |
|
540 } |
|
541 } |
|
542 |
522 $ctx[0][0] = self::xor64( |
543 $ctx[0][0] = self::xor64( |
523 $ctx[0][0], |
544 $ctx[0][0], |
524 self::load64($p, 0) |
545 self::load64($p, 0) |
525 ); |
546 ); |
526 |
547 |
|
548 if ($salt instanceof SplFixedArray || $personal instanceof SplFixedArray) { |
|
549 // We need to do what blake2b_init_param() does: |
|
550 for ($i = 1; $i < 8; ++$i) { |
|
551 $ctx[0][$i] = self::xor64( |
|
552 $ctx[0][$i], |
|
553 self::load64($p, $i << 3) |
|
554 ); |
|
555 } |
|
556 } |
|
557 |
527 if ($klen > 0 && $key instanceof SplFixedArray) { |
558 if ($klen > 0 && $key instanceof SplFixedArray) { |
528 $block = new SplFixedArray(128); |
559 $block = new SplFixedArray(128); |
529 for ($i = 128; $i--;) { |
560 for ($i = 128; $i--;) { |
530 $block[$i] = 0; |
561 $block[$i] = 0; |
531 } |
562 } |
532 for ($i = $klen; $i--;) { |
563 for ($i = $klen; $i--;) { |
533 $block[$i] = $key[$i]; |
564 $block[$i] = $key[$i]; |
534 } |
565 } |
535 self::update($ctx, $block, 128); |
566 self::update($ctx, $block, 128); |
|
567 $ctx[4] = 128; |
536 } |
568 } |
537 |
569 |
538 return $ctx; |
570 return $ctx; |
539 } |
571 } |
540 |
572 |
593 if (!($ctxA[$i] instanceof ParagonIE_Sodium_Core32_Int64)) { |
625 if (!($ctxA[$i] instanceof ParagonIE_Sodium_Core32_Int64)) { |
594 throw new TypeError('Not an instance of Int64'); |
626 throw new TypeError('Not an instance of Int64'); |
595 } |
627 } |
596 /** @var ParagonIE_Sodium_Core32_Int64 $ctxAi */ |
628 /** @var ParagonIE_Sodium_Core32_Int64 $ctxAi */ |
597 $ctxAi = $ctxA[$i]; |
629 $ctxAi = $ctxA[$i]; |
598 $str .= $ctxAi->toString(); |
630 $str .= $ctxAi->toReverseString(); |
599 } |
631 } |
600 |
632 |
601 # uint64_t t[2]; |
633 # uint64_t t[2]; |
602 # uint64_t f[2]; |
634 # uint64_t f[2]; |
603 for ($i = 1; $i < 3; ++$i) { |
635 for ($i = 1; $i < 3; ++$i) { |
606 /** @var ParagonIE_Sodium_Core32_Int64 $ctxA1 */ |
638 /** @var ParagonIE_Sodium_Core32_Int64 $ctxA1 */ |
607 $ctxA1 = $ctxA[0]; |
639 $ctxA1 = $ctxA[0]; |
608 /** @var ParagonIE_Sodium_Core32_Int64 $ctxA2 */ |
640 /** @var ParagonIE_Sodium_Core32_Int64 $ctxA2 */ |
609 $ctxA2 = $ctxA[1]; |
641 $ctxA2 = $ctxA[1]; |
610 |
642 |
611 $str .= $ctxA1->toString(); |
643 $str .= $ctxA1->toReverseString(); |
612 $str .= $ctxA2->toString(); |
644 $str .= $ctxA2->toReverseString(); |
613 } |
645 } |
614 |
646 |
615 # uint8_t buf[2 * 128]; |
647 # uint8_t buf[2 * 128]; |
616 $str .= self::SplFixedArrayToString($ctx[3]); |
648 $str .= self::SplFixedArrayToString($ctx[3]); |
617 |
649 |
622 $str .= implode('', array( |
654 $str .= implode('', array( |
623 self::intToChr($ctx4 & 0xff), |
655 self::intToChr($ctx4 & 0xff), |
624 self::intToChr(($ctx4 >> 8) & 0xff), |
656 self::intToChr(($ctx4 >> 8) & 0xff), |
625 self::intToChr(($ctx4 >> 16) & 0xff), |
657 self::intToChr(($ctx4 >> 16) & 0xff), |
626 self::intToChr(($ctx4 >> 24) & 0xff), |
658 self::intToChr(($ctx4 >> 24) & 0xff), |
|
659 "\x00\x00\x00\x00" |
|
660 /* |
627 self::intToChr(($ctx4 >> 32) & 0xff), |
661 self::intToChr(($ctx4 >> 32) & 0xff), |
628 self::intToChr(($ctx4 >> 40) & 0xff), |
662 self::intToChr(($ctx4 >> 40) & 0xff), |
629 self::intToChr(($ctx4 >> 48) & 0xff), |
663 self::intToChr(($ctx4 >> 48) & 0xff), |
630 self::intToChr(($ctx4 >> 56) & 0xff) |
664 self::intToChr(($ctx4 >> 56) & 0xff) |
|
665 */ |
631 )); |
666 )); |
632 # uint8_t last_node; |
667 # uint8_t last_node; |
633 return $str . "\x00"; |
668 return $str . self::intToChr($ctx[5]) . str_repeat("\x00", 23); |
634 } |
669 } |
635 |
670 |
636 /** |
671 /** |
637 * Creates an SplFixedArray containing other SplFixedArray elements, from |
672 * Creates an SplFixedArray containing other SplFixedArray elements, from |
638 * a string (compatible with \Sodium\crypto_generichash_{init, update, final}) |
673 * a string (compatible with \Sodium\crypto_generichash_{init, update, final}) |
650 { |
685 { |
651 $ctx = self::context(); |
686 $ctx = self::context(); |
652 |
687 |
653 # uint64_t h[8]; |
688 # uint64_t h[8]; |
654 for ($i = 0; $i < 8; ++$i) { |
689 for ($i = 0; $i < 8; ++$i) { |
655 $ctx[0][$i] = ParagonIE_Sodium_Core32_Int64::fromString( |
690 $ctx[0][$i] = ParagonIE_Sodium_Core32_Int64::fromReverseString( |
656 self::substr($string, (($i << 3) + 0), 8) |
691 self::substr($string, (($i << 3) + 0), 8) |
657 ); |
692 ); |
658 } |
693 } |
659 |
694 |
660 # uint64_t t[2]; |
695 # uint64_t t[2]; |
661 # uint64_t f[2]; |
696 # uint64_t f[2]; |
662 for ($i = 1; $i < 3; ++$i) { |
697 for ($i = 1; $i < 3; ++$i) { |
663 $ctx[$i][1] = ParagonIE_Sodium_Core32_Int64::fromString( |
698 $ctx[$i][1] = ParagonIE_Sodium_Core32_Int64::fromReverseString( |
664 self::substr($string, 72 + (($i - 1) << 4), 8) |
699 self::substr($string, 72 + (($i - 1) << 4), 8) |
665 ); |
700 ); |
666 $ctx[$i][0] = ParagonIE_Sodium_Core32_Int64::fromString( |
701 $ctx[$i][0] = ParagonIE_Sodium_Core32_Int64::fromReverseString( |
667 self::substr($string, 64 + (($i - 1) << 4), 8) |
702 self::substr($string, 64 + (($i - 1) << 4), 8) |
668 ); |
703 ); |
669 } |
704 } |
670 |
705 |
671 # uint8_t buf[2 * 128]; |
706 # uint8_t buf[2 * 128]; |
672 $ctx[3] = self::stringToSplFixedArray(self::substr($string, 96, 256)); |
707 $ctx[3] = self::stringToSplFixedArray(self::substr($string, 96, 256)); |
673 |
|
674 |
708 |
675 # uint8_t buf[2 * 128]; |
709 # uint8_t buf[2 * 128]; |
676 $int = 0; |
710 $int = 0; |
677 for ($i = 0; $i < 8; ++$i) { |
711 for ($i = 0; $i < 8; ++$i) { |
678 $int |= self::chrToInt($string[352 + $i]) << ($i << 3); |
712 $int |= self::chrToInt($string[352 + $i]) << ($i << 3); |