[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 3 if (class_exists('ParagonIE_Sodium_Core_Util', false)) { 4 return; 5 } 6 7 /** 8 * Class ParagonIE_Sodium_Core_Util 9 */ 10 abstract class ParagonIE_Sodium_Core_Util 11 { 12 /** 13 * @param int $integer 14 * @param int $size (16, 32, 64) 15 * @return int 16 */ 17 public static function abs($integer, $size = 0) 18 { 19 /** @var int $realSize */ 20 $realSize = (PHP_INT_SIZE << 3) - 1; 21 if ($size) { 22 --$size; 23 } else { 24 /** @var int $size */ 25 $size = $realSize; 26 } 27 28 $negative = -(($integer >> $size) & 1); 29 return (int) ( 30 ($integer ^ $negative) 31 + 32 (($negative >> $realSize) & 1) 33 ); 34 } 35 36 /** 37 * Convert a binary string into a hexadecimal string without cache-timing 38 * leaks 39 * 40 * @internal You should not use this directly from another application 41 * 42 * @param string $binaryString (raw binary) 43 * @return string 44 * @throws TypeError 45 */ 46 public static function bin2hex($binaryString) 47 { 48 /* Type checks: */ 49 if (!is_string($binaryString)) { 50 throw new TypeError('Argument 1 must be a string, ' . gettype($binaryString) . ' given.'); 51 } 52 53 $hex = ''; 54 $len = self::strlen($binaryString); 55 for ($i = 0; $i < $len; ++$i) { 56 /** @var array<int, int> $chunk */ 57 $chunk = unpack('C', $binaryString[$i]); 58 /** @var int $c */ 59 $c = $chunk[1] & 0xf; 60 /** @var int $b */ 61 $b = $chunk[1] >> 4; 62 $hex .= pack( 63 'CC', 64 (87 + $b + ((($b - 10) >> 8) & ~38)), 65 (87 + $c + ((($c - 10) >> 8) & ~38)) 66 ); 67 } 68 return $hex; 69 } 70 71 /** 72 * Convert a binary string into a hexadecimal string without cache-timing 73 * leaks, returning uppercase letters (as per RFC 4648) 74 * 75 * @internal You should not use this directly from another application 76 * 77 * @param string $bin_string (raw binary) 78 * @return string 79 * @throws TypeError 80 */ 81 public static function bin2hexUpper($bin_string) 82 { 83 $hex = ''; 84 $len = self::strlen($bin_string); 85 for ($i = 0; $i < $len; ++$i) { 86 /** @var array<int, int> $chunk */ 87 $chunk = unpack('C', $bin_string[$i]); 88 /** 89 * Lower 16 bits 90 * 91 * @var int $c 92 */ 93 $c = $chunk[1] & 0xf; 94 95 /** 96 * Upper 16 bits 97 * @var int $b 98 */ 99 $b = $chunk[1] >> 4; 100 101 /** 102 * Use pack() and binary operators to turn the two integers 103 * into hexadecimal characters. We don't use chr() here, because 104 * it uses a lookup table internally and we want to avoid 105 * cache-timing side-channels. 106 */ 107 $hex .= pack( 108 'CC', 109 (55 + $b + ((($b - 10) >> 8) & ~6)), 110 (55 + $c + ((($c - 10) >> 8) & ~6)) 111 ); 112 } 113 return $hex; 114 } 115 116 /** 117 * Cache-timing-safe variant of ord() 118 * 119 * @internal You should not use this directly from another application 120 * 121 * @param string $chr 122 * @return int 123 * @throws SodiumException 124 * @throws TypeError 125 */ 126 public static function chrToInt($chr) 127 { 128 /* Type checks: */ 129 if (!is_string($chr)) { 130 throw new TypeError('Argument 1 must be a string, ' . gettype($chr) . ' given.'); 131 } 132 if (self::strlen($chr) !== 1) { 133 throw new SodiumException('chrToInt() expects a string that is exactly 1 character long'); 134 } 135 /** @var array<int, int> $chunk */ 136 $chunk = unpack('C', $chr); 137 return (int) ($chunk[1]); 138 } 139 140 /** 141 * Compares two strings. 142 * 143 * @internal You should not use this directly from another application 144 * 145 * @param string $left 146 * @param string $right 147 * @param int $len 148 * @return int 149 * @throws SodiumException 150 * @throws TypeError 151 */ 152 public static function compare($left, $right, $len = null) 153 { 154 $leftLen = self::strlen($left); 155 $rightLen = self::strlen($right); 156 if ($len === null) { 157 $len = max($leftLen, $rightLen); 158 $left = str_pad($left, $len, "\x00", STR_PAD_RIGHT); 159 $right = str_pad($right, $len, "\x00", STR_PAD_RIGHT); 160 } 161 162 $gt = 0; 163 $eq = 1; 164 $i = $len; 165 while ($i !== 0) { 166 --$i; 167 $gt |= ((self::chrToInt($right[$i]) - self::chrToInt($left[$i])) >> 8) & $eq; 168 $eq &= ((self::chrToInt($right[$i]) ^ self::chrToInt($left[$i])) - 1) >> 8; 169 } 170 return ($gt + $gt + $eq) - 1; 171 } 172 173 /** 174 * If a variable does not match a given type, throw a TypeError. 175 * 176 * @param mixed $mixedVar 177 * @param string $type 178 * @param int $argumentIndex 179 * @throws TypeError 180 * @throws SodiumException 181 * @return void 182 */ 183 public static function declareScalarType(&$mixedVar = null, $type = 'void', $argumentIndex = 0) 184 { 185 if (func_num_args() === 0) { 186 /* Tautology, by default */ 187 return; 188 } 189 if (func_num_args() === 1) { 190 throw new TypeError('Declared void, but passed a variable'); 191 } 192 $realType = strtolower(gettype($mixedVar)); 193 $type = strtolower($type); 194 switch ($type) { 195 case 'null': 196 if ($mixedVar !== null) { 197 throw new TypeError('Argument ' . $argumentIndex . ' must be null, ' . $realType . ' given.'); 198 } 199 break; 200 case 'integer': 201 case 'int': 202 $allow = array('int', 'integer'); 203 if (!in_array($type, $allow)) { 204 throw new TypeError('Argument ' . $argumentIndex . ' must be an integer, ' . $realType . ' given.'); 205 } 206 $mixedVar = (int) $mixedVar; 207 break; 208 case 'boolean': 209 case 'bool': 210 $allow = array('bool', 'boolean'); 211 if (!in_array($type, $allow)) { 212 throw new TypeError('Argument ' . $argumentIndex . ' must be a boolean, ' . $realType . ' given.'); 213 } 214 $mixedVar = (bool) $mixedVar; 215 break; 216 case 'string': 217 if (!is_string($mixedVar)) { 218 throw new TypeError('Argument ' . $argumentIndex . ' must be a string, ' . $realType . ' given.'); 219 } 220 $mixedVar = (string) $mixedVar; 221 break; 222 case 'decimal': 223 case 'double': 224 case 'float': 225 $allow = array('decimal', 'double', 'float'); 226 if (!in_array($type, $allow)) { 227 throw new TypeError('Argument ' . $argumentIndex . ' must be a float, ' . $realType . ' given.'); 228 } 229 $mixedVar = (float) $mixedVar; 230 break; 231 case 'object': 232 if (!is_object($mixedVar)) { 233 throw new TypeError('Argument ' . $argumentIndex . ' must be an object, ' . $realType . ' given.'); 234 } 235 break; 236 case 'array': 237 if (!is_array($mixedVar)) { 238 if (is_object($mixedVar)) { 239 if ($mixedVar instanceof ArrayAccess) { 240 return; 241 } 242 } 243 throw new TypeError('Argument ' . $argumentIndex . ' must be an array, ' . $realType . ' given.'); 244 } 245 break; 246 default: 247 throw new SodiumException('Unknown type (' . $realType .') does not match expect type (' . $type . ')'); 248 } 249 } 250 251 /** 252 * Evaluate whether or not two strings are equal (in constant-time) 253 * 254 * @param string $left 255 * @param string $right 256 * @return bool 257 * @throws SodiumException 258 * @throws TypeError 259 */ 260 public static function hashEquals($left, $right) 261 { 262 /* Type checks: */ 263 if (!is_string($left)) { 264 throw new TypeError('Argument 1 must be a string, ' . gettype($left) . ' given.'); 265 } 266 if (!is_string($right)) { 267 throw new TypeError('Argument 2 must be a string, ' . gettype($right) . ' given.'); 268 } 269 270 if (is_callable('hash_equals')) { 271 return hash_equals($left, $right); 272 } 273 $d = 0; 274 /** @var int $len */ 275 $len = self::strlen($left); 276 if ($len !== self::strlen($right)) { 277 return false; 278 } 279 for ($i = 0; $i < $len; ++$i) { 280 $d |= self::chrToInt($left[$i]) ^ self::chrToInt($right[$i]); 281 } 282 283 if ($d !== 0) { 284 return false; 285 } 286 return $left === $right; 287 } 288 289 /** 290 * Catch hash_update() failures and throw instead of silently proceeding 291 * 292 * @param HashContext|resource &$hs 293 * @param string $data 294 * @return void 295 * @throws SodiumException 296 * @psalm-suppress PossiblyInvalidArgument 297 */ 298 protected static function hash_update(&$hs, $data) 299 { 300 if (!hash_update($hs, $data)) { 301 throw new SodiumException('hash_update() failed'); 302 } 303 } 304 305 /** 306 * Convert a hexadecimal string into a binary string without cache-timing 307 * leaks 308 * 309 * @internal You should not use this directly from another application 310 * 311 * @param string $hexString 312 * @param string $ignore 313 * @param bool $strictPadding 314 * @return string (raw binary) 315 * @throws RangeException 316 * @throws TypeError 317 */ 318 public static function hex2bin($hexString, $ignore = '', $strictPadding = false) 319 { 320 /* Type checks: */ 321 if (!is_string($hexString)) { 322 throw new TypeError('Argument 1 must be a string, ' . gettype($hexString) . ' given.'); 323 } 324 if (!is_string($ignore)) { 325 throw new TypeError('Argument 2 must be a string, ' . gettype($hexString) . ' given.'); 326 } 327 328 $hex_pos = 0; 329 $bin = ''; 330 $c_acc = 0; 331 $hex_len = self::strlen($hexString); 332 $state = 0; 333 if (($hex_len & 1) !== 0) { 334 if ($strictPadding) { 335 throw new RangeException( 336 'Expected an even number of hexadecimal characters' 337 ); 338 } else { 339 $hexString = '0' . $hexString; 340 ++$hex_len; 341 } 342 } 343 344 $chunk = unpack('C*', $hexString); 345 while ($hex_pos < $hex_len) { 346 ++$hex_pos; 347 /** @var int $c */ 348 $c = $chunk[$hex_pos]; 349 $c_num = $c ^ 48; 350 $c_num0 = ($c_num - 10) >> 8; 351 $c_alpha = ($c & ~32) - 55; 352 $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8; 353 if (($c_num0 | $c_alpha0) === 0) { 354 if ($ignore && $state === 0 && strpos($ignore, self::intToChr($c)) !== false) { 355 continue; 356 } 357 throw new RangeException( 358 'hex2bin() only expects hexadecimal characters' 359 ); 360 } 361 $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0); 362 if ($state === 0) { 363 $c_acc = $c_val * 16; 364 } else { 365 $bin .= pack('C', $c_acc | $c_val); 366 } 367 $state ^= 1; 368 } 369 return $bin; 370 } 371 372 /** 373 * Turn an array of integers into a string 374 * 375 * @internal You should not use this directly from another application 376 * 377 * @param array<int, int> $ints 378 * @return string 379 */ 380 public static function intArrayToString(array $ints) 381 { 382 $args = $ints; 383 foreach ($args as $i => $v) { 384 $args[$i] = (int) ($v & 0xff); 385 } 386 array_unshift($args, str_repeat('C', count($ints))); 387 return (string) (call_user_func_array('pack', $args)); 388 } 389 390 /** 391 * Cache-timing-safe variant of ord() 392 * 393 * @internal You should not use this directly from another application 394 * 395 * @param int $int 396 * @return string 397 * @throws TypeError 398 */ 399 public static function intToChr($int) 400 { 401 return pack('C', $int); 402 } 403 404 /** 405 * Load a 3 character substring into an integer 406 * 407 * @internal You should not use this directly from another application 408 * 409 * @param string $string 410 * @return int 411 * @throws RangeException 412 * @throws TypeError 413 */ 414 public static function load_3($string) 415 { 416 /* Type checks: */ 417 if (!is_string($string)) { 418 throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.'); 419 } 420 421 /* Input validation: */ 422 if (self::strlen($string) < 3) { 423 throw new RangeException( 424 'String must be 3 bytes or more; ' . self::strlen($string) . ' given.' 425 ); 426 } 427 /** @var array<int, int> $unpacked */ 428 $unpacked = unpack('V', $string . "\0"); 429 return (int) ($unpacked[1] & 0xffffff); 430 } 431 432 /** 433 * Load a 4 character substring into an integer 434 * 435 * @internal You should not use this directly from another application 436 * 437 * @param string $string 438 * @return int 439 * @throws RangeException 440 * @throws TypeError 441 */ 442 public static function load_4($string) 443 { 444 /* Type checks: */ 445 if (!is_string($string)) { 446 throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.'); 447 } 448 449 /* Input validation: */ 450 if (self::strlen($string) < 4) { 451 throw new RangeException( 452 'String must be 4 bytes or more; ' . self::strlen($string) . ' given.' 453 ); 454 } 455 /** @var array<int, int> $unpacked */ 456 $unpacked = unpack('V', $string); 457 return (int) $unpacked[1]; 458 } 459 460 /** 461 * Load a 8 character substring into an integer 462 * 463 * @internal You should not use this directly from another application 464 * 465 * @param string $string 466 * @return int 467 * @throws RangeException 468 * @throws SodiumException 469 * @throws TypeError 470 */ 471 public static function load64_le($string) 472 { 473 /* Type checks: */ 474 if (!is_string($string)) { 475 throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.'); 476 } 477 478 /* Input validation: */ 479 if (self::strlen($string) < 4) { 480 throw new RangeException( 481 'String must be 4 bytes or more; ' . self::strlen($string) . ' given.' 482 ); 483 } 484 if (PHP_VERSION_ID >= 50603 && PHP_INT_SIZE === 8) { 485 /** @var array<int, int> $unpacked */ 486 $unpacked = unpack('P', $string); 487 return (int) $unpacked[1]; 488 } 489 490 /** @var int $result */ 491 $result = (self::chrToInt($string[0]) & 0xff); 492 $result |= (self::chrToInt($string[1]) & 0xff) << 8; 493 $result |= (self::chrToInt($string[2]) & 0xff) << 16; 494 $result |= (self::chrToInt($string[3]) & 0xff) << 24; 495 $result |= (self::chrToInt($string[4]) & 0xff) << 32; 496 $result |= (self::chrToInt($string[5]) & 0xff) << 40; 497 $result |= (self::chrToInt($string[6]) & 0xff) << 48; 498 $result |= (self::chrToInt($string[7]) & 0xff) << 56; 499 return (int) $result; 500 } 501 502 /** 503 * @internal You should not use this directly from another application 504 * 505 * @param string $left 506 * @param string $right 507 * @return int 508 * @throws SodiumException 509 * @throws TypeError 510 */ 511 public static function memcmp($left, $right) 512 { 513 if (self::hashEquals($left, $right)) { 514 return 0; 515 } 516 return -1; 517 } 518 519 /** 520 * Multiply two integers in constant-time 521 * 522 * Micro-architecture timing side-channels caused by how your CPU 523 * implements multiplication are best prevented by never using the 524 * multiplication operators and ensuring that our code always takes 525 * the same number of operations to complete, regardless of the values 526 * of $a and $b. 527 * 528 * @internal You should not use this directly from another application 529 * 530 * @param int $a 531 * @param int $b 532 * @param int $size Limits the number of operations (useful for small, 533 * constant operands) 534 * @return int 535 */ 536 public static function mul($a, $b, $size = 0) 537 { 538 if (ParagonIE_Sodium_Compat::$fastMult) { 539 return (int) ($a * $b); 540 } 541 542 static $defaultSize = null; 543 /** @var int $defaultSize */ 544 if (!$defaultSize) { 545 /** @var int $defaultSize */ 546 $defaultSize = (PHP_INT_SIZE << 3) - 1; 547 } 548 if ($size < 1) { 549 /** @var int $size */ 550 $size = $defaultSize; 551 } 552 /** @var int $size */ 553 554 $c = 0; 555 556 /** 557 * Mask is either -1 or 0. 558 * 559 * -1 in binary looks like 0x1111 ... 1111 560 * 0 in binary looks like 0x0000 ... 0000 561 * 562 * @var int 563 */ 564 $mask = -(($b >> ((int) $defaultSize)) & 1); 565 566 /** 567 * Ensure $b is a positive integer, without creating 568 * a branching side-channel 569 * 570 * @var int $b 571 */ 572 $b = ($b & ~$mask) | ($mask & -$b); 573 574 /** 575 * Unless $size is provided: 576 * 577 * This loop always runs 32 times when PHP_INT_SIZE is 4. 578 * This loop always runs 64 times when PHP_INT_SIZE is 8. 579 */ 580 for ($i = $size; $i >= 0; --$i) { 581 $c += (int) ($a & -($b & 1)); 582 $a <<= 1; 583 $b >>= 1; 584 } 585 $c = (int) @($c & -1); 586 587 /** 588 * If $b was negative, we then apply the same value to $c here. 589 * It doesn't matter much if $a was negative; the $c += above would 590 * have produced a negative integer to begin with. But a negative $b 591 * makes $b >>= 1 never return 0, so we would end up with incorrect 592 * results. 593 * 594 * The end result is what we'd expect from integer multiplication. 595 */ 596 return (int) (($c & ~$mask) | ($mask & -$c)); 597 } 598 599 /** 600 * Convert any arbitrary numbers into two 32-bit integers that represent 601 * a 64-bit integer. 602 * 603 * @internal You should not use this directly from another application 604 * 605 * @param int|float $num 606 * @return array<int, int> 607 */ 608 public static function numericTo64BitInteger($num) 609 { 610 $high = 0; 611 /** @var int $low */ 612 if (PHP_INT_SIZE === 4) { 613 $low = (int) $num; 614 } else { 615 $low = $num & 0xffffffff; 616 } 617 618 if ((+(abs($num))) >= 1) { 619 if ($num > 0) { 620 /** @var int $high */ 621 $high = min((+(floor($num/4294967296))), 4294967295); 622 } else { 623 /** @var int $high */ 624 $high = ~~((+(ceil(($num - (+((~~($num)))))/4294967296)))); 625 } 626 } 627 return array((int) $high, (int) $low); 628 } 629 630 /** 631 * Store a 24-bit integer into a string, treating it as big-endian. 632 * 633 * @internal You should not use this directly from another application 634 * 635 * @param int $int 636 * @return string 637 * @throws TypeError 638 */ 639 public static function store_3($int) 640 { 641 /* Type checks: */ 642 if (!is_int($int)) { 643 if (is_numeric($int)) { 644 $int = (int) $int; 645 } else { 646 throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); 647 } 648 } 649 /** @var string $packed */ 650 $packed = pack('N', $int); 651 return self::substr($packed, 1, 3); 652 } 653 654 /** 655 * Store a 32-bit integer into a string, treating it as little-endian. 656 * 657 * @internal You should not use this directly from another application 658 * 659 * @param int $int 660 * @return string 661 * @throws TypeError 662 */ 663 public static function store32_le($int) 664 { 665 /* Type checks: */ 666 if (!is_int($int)) { 667 if (is_numeric($int)) { 668 $int = (int) $int; 669 } else { 670 throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); 671 } 672 } 673 674 /** @var string $packed */ 675 $packed = pack('V', $int); 676 return $packed; 677 } 678 679 /** 680 * Store a 32-bit integer into a string, treating it as big-endian. 681 * 682 * @internal You should not use this directly from another application 683 * 684 * @param int $int 685 * @return string 686 * @throws TypeError 687 */ 688 public static function store_4($int) 689 { 690 /* Type checks: */ 691 if (!is_int($int)) { 692 if (is_numeric($int)) { 693 $int = (int) $int; 694 } else { 695 throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); 696 } 697 } 698 699 /** @var string $packed */ 700 $packed = pack('N', $int); 701 return $packed; 702 } 703 704 /** 705 * Stores a 64-bit integer as an string, treating it as little-endian. 706 * 707 * @internal You should not use this directly from another application 708 * 709 * @param int $int 710 * @return string 711 * @throws TypeError 712 */ 713 public static function store64_le($int) 714 { 715 /* Type checks: */ 716 if (!is_int($int)) { 717 if (is_numeric($int)) { 718 $int = (int) $int; 719 } else { 720 throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); 721 } 722 } 723 724 if (PHP_INT_SIZE === 8) { 725 if (PHP_VERSION_ID >= 50603) { 726 /** @var string $packed */ 727 $packed = pack('P', $int); 728 return $packed; 729 } 730 return self::intToChr($int & 0xff) . 731 self::intToChr(($int >> 8) & 0xff) . 732 self::intToChr(($int >> 16) & 0xff) . 733 self::intToChr(($int >> 24) & 0xff) . 734 self::intToChr(($int >> 32) & 0xff) . 735 self::intToChr(($int >> 40) & 0xff) . 736 self::intToChr(($int >> 48) & 0xff) . 737 self::intToChr(($int >> 56) & 0xff); 738 } 739 if ($int > PHP_INT_MAX) { 740 list($hiB, $int) = self::numericTo64BitInteger($int); 741 } else { 742 $hiB = 0; 743 } 744 return 745 self::intToChr(($int ) & 0xff) . 746 self::intToChr(($int >> 8) & 0xff) . 747 self::intToChr(($int >> 16) & 0xff) . 748 self::intToChr(($int >> 24) & 0xff) . 749 self::intToChr($hiB & 0xff) . 750 self::intToChr(($hiB >> 8) & 0xff) . 751 self::intToChr(($hiB >> 16) & 0xff) . 752 self::intToChr(($hiB >> 24) & 0xff); 753 } 754 755 /** 756 * Safe string length 757 * 758 * @internal You should not use this directly from another application 759 * 760 * @ref mbstring.func_overload 761 * 762 * @param string $str 763 * @return int 764 * @throws TypeError 765 */ 766 public static function strlen($str) 767 { 768 /* Type checks: */ 769 if (!is_string($str)) { 770 throw new TypeError('String expected'); 771 } 772 773 return (int) ( 774 self::isMbStringOverride() 775 ? mb_strlen($str, '8bit') 776 : strlen($str) 777 ); 778 } 779 780 /** 781 * Turn a string into an array of integers 782 * 783 * @internal You should not use this directly from another application 784 * 785 * @param string $string 786 * @return array<int, int> 787 * @throws TypeError 788 */ 789 public static function stringToIntArray($string) 790 { 791 if (!is_string($string)) { 792 throw new TypeError('String expected'); 793 } 794 /** 795 * @var array<int, int> 796 */ 797 $values = array_values( 798 unpack('C*', $string) 799 ); 800 return $values; 801 } 802 803 /** 804 * Safe substring 805 * 806 * @internal You should not use this directly from another application 807 * 808 * @ref mbstring.func_overload 809 * 810 * @param string $str 811 * @param int $start 812 * @param int $length 813 * @return string 814 * @throws TypeError 815 */ 816 public static function substr($str, $start = 0, $length = null) 817 { 818 /* Type checks: */ 819 if (!is_string($str)) { 820 throw new TypeError('String expected'); 821 } 822 823 if ($length === 0) { 824 return ''; 825 } 826 827 if (self::isMbStringOverride()) { 828 if (PHP_VERSION_ID < 50400 && $length === null) { 829 $length = self::strlen($str); 830 } 831 $sub = (string) mb_substr($str, $start, $length, '8bit'); 832 } elseif ($length === null) { 833 $sub = (string) substr($str, $start); 834 } else { 835 $sub = (string) substr($str, $start, $length); 836 } 837 if ($sub !== '') { 838 return $sub; 839 } 840 return ''; 841 } 842 843 /** 844 * Compare a 16-character byte string in constant time. 845 * 846 * @internal You should not use this directly from another application 847 * 848 * @param string $a 849 * @param string $b 850 * @return bool 851 * @throws SodiumException 852 * @throws TypeError 853 */ 854 public static function verify_16($a, $b) 855 { 856 /* Type checks: */ 857 if (!is_string($a)) { 858 throw new TypeError('String expected'); 859 } 860 if (!is_string($b)) { 861 throw new TypeError('String expected'); 862 } 863 return self::hashEquals( 864 self::substr($a, 0, 16), 865 self::substr($b, 0, 16) 866 ); 867 } 868 869 /** 870 * Compare a 32-character byte string in constant time. 871 * 872 * @internal You should not use this directly from another application 873 * 874 * @param string $a 875 * @param string $b 876 * @return bool 877 * @throws SodiumException 878 * @throws TypeError 879 */ 880 public static function verify_32($a, $b) 881 { 882 /* Type checks: */ 883 if (!is_string($a)) { 884 throw new TypeError('String expected'); 885 } 886 if (!is_string($b)) { 887 throw new TypeError('String expected'); 888 } 889 return self::hashEquals( 890 self::substr($a, 0, 32), 891 self::substr($b, 0, 32) 892 ); 893 } 894 895 /** 896 * Calculate $a ^ $b for two strings. 897 * 898 * @internal You should not use this directly from another application 899 * 900 * @param string $a 901 * @param string $b 902 * @return string 903 * @throws TypeError 904 */ 905 public static function xorStrings($a, $b) 906 { 907 /* Type checks: */ 908 if (!is_string($a)) { 909 throw new TypeError('Argument 1 must be a string'); 910 } 911 if (!is_string($b)) { 912 throw new TypeError('Argument 2 must be a string'); 913 } 914 915 return (string) ($a ^ $b); 916 } 917 918 /** 919 * Returns whether or not mbstring.func_overload is in effect. 920 * 921 * @internal You should not use this directly from another application 922 * 923 * Note: MB_OVERLOAD_STRING === 2, but we don't reference the constant 924 * (for nuisance-free PHP 8 support) 925 * 926 * @return bool 927 */ 928 protected static function isMbStringOverride() 929 { 930 static $mbstring = null; 931 932 if ($mbstring === null) { 933 if (!defined('MB_OVERLOAD_STRING')) { 934 $mbstring = false; 935 return $mbstring; 936 } 937 $mbstring = extension_loaded('mbstring') 938 && defined('MB_OVERLOAD_STRING') 939 && 940 ((int) (ini_get('mbstring.func_overload')) & 2); 941 // MB_OVERLOAD_STRING === 2 942 } 943 /** @var bool $mbstring */ 944 945 return $mbstring; 946 } 947 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Fri Apr 19 08:20:01 2024 | Cross-referenced by PHPXref |