[ Index ] |
PHP Cross Reference of WordPress |
[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 bool $strictPadding 313 * @return string (raw binary) 314 * @throws RangeException 315 * @throws TypeError 316 */ 317 public static function hex2bin($hexString, $strictPadding = false) 318 { 319 /* Type checks: */ 320 if (!is_string($hexString)) { 321 throw new TypeError('Argument 1 must be a string, ' . gettype($hexString) . ' given.'); 322 } 323 324 /** @var int $hex_pos */ 325 $hex_pos = 0; 326 /** @var string $bin */ 327 $bin = ''; 328 /** @var int $c_acc */ 329 $c_acc = 0; 330 /** @var int $hex_len */ 331 $hex_len = self::strlen($hexString); 332 /** @var int $state */ 333 $state = 0; 334 if (($hex_len & 1) !== 0) { 335 if ($strictPadding) { 336 throw new RangeException( 337 'Expected an even number of hexadecimal characters' 338 ); 339 } else { 340 $hexString = '0' . $hexString; 341 ++$hex_len; 342 } 343 } 344 345 $chunk = unpack('C*', $hexString); 346 while ($hex_pos < $hex_len) { 347 ++$hex_pos; 348 /** @var int $c */ 349 $c = $chunk[$hex_pos]; 350 /** @var int $c_num */ 351 $c_num = $c ^ 48; 352 /** @var int $c_num0 */ 353 $c_num0 = ($c_num - 10) >> 8; 354 /** @var int $c_alpha */ 355 $c_alpha = ($c & ~32) - 55; 356 /** @var int $c_alpha0 */ 357 $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8; 358 if (($c_num0 | $c_alpha0) === 0) { 359 throw new RangeException( 360 'hex2bin() only expects hexadecimal characters' 361 ); 362 } 363 /** @var int $c_val */ 364 $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0); 365 if ($state === 0) { 366 $c_acc = $c_val * 16; 367 } else { 368 $bin .= pack('C', $c_acc | $c_val); 369 } 370 $state ^= 1; 371 } 372 return $bin; 373 } 374 375 /** 376 * Turn an array of integers into a string 377 * 378 * @internal You should not use this directly from another application 379 * 380 * @param array<int, int> $ints 381 * @return string 382 */ 383 public static function intArrayToString(array $ints) 384 { 385 /** @var array<int, int> $args */ 386 $args = $ints; 387 foreach ($args as $i => $v) { 388 $args[$i] = (int) ($v & 0xff); 389 } 390 array_unshift($args, str_repeat('C', count($ints))); 391 return (string) (call_user_func_array('pack', $args)); 392 } 393 394 /** 395 * Cache-timing-safe variant of ord() 396 * 397 * @internal You should not use this directly from another application 398 * 399 * @param int $int 400 * @return string 401 * @throws TypeError 402 */ 403 public static function intToChr($int) 404 { 405 return pack('C', $int); 406 } 407 408 /** 409 * Load a 3 character substring into an integer 410 * 411 * @internal You should not use this directly from another application 412 * 413 * @param string $string 414 * @return int 415 * @throws RangeException 416 * @throws TypeError 417 */ 418 public static function load_3($string) 419 { 420 /* Type checks: */ 421 if (!is_string($string)) { 422 throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.'); 423 } 424 425 /* Input validation: */ 426 if (self::strlen($string) < 3) { 427 throw new RangeException( 428 'String must be 3 bytes or more; ' . self::strlen($string) . ' given.' 429 ); 430 } 431 /** @var array<int, int> $unpacked */ 432 $unpacked = unpack('V', $string . "\0"); 433 return (int) ($unpacked[1] & 0xffffff); 434 } 435 436 /** 437 * Load a 4 character substring into an integer 438 * 439 * @internal You should not use this directly from another application 440 * 441 * @param string $string 442 * @return int 443 * @throws RangeException 444 * @throws TypeError 445 */ 446 public static function load_4($string) 447 { 448 /* Type checks: */ 449 if (!is_string($string)) { 450 throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.'); 451 } 452 453 /* Input validation: */ 454 if (self::strlen($string) < 4) { 455 throw new RangeException( 456 'String must be 4 bytes or more; ' . self::strlen($string) . ' given.' 457 ); 458 } 459 /** @var array<int, int> $unpacked */ 460 $unpacked = unpack('V', $string); 461 return (int) $unpacked[1]; 462 } 463 464 /** 465 * Load a 8 character substring into an integer 466 * 467 * @internal You should not use this directly from another application 468 * 469 * @param string $string 470 * @return int 471 * @throws RangeException 472 * @throws SodiumException 473 * @throws TypeError 474 */ 475 public static function load64_le($string) 476 { 477 /* Type checks: */ 478 if (!is_string($string)) { 479 throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.'); 480 } 481 482 /* Input validation: */ 483 if (self::strlen($string) < 4) { 484 throw new RangeException( 485 'String must be 4 bytes or more; ' . self::strlen($string) . ' given.' 486 ); 487 } 488 if (PHP_VERSION_ID >= 50603 && PHP_INT_SIZE === 8) { 489 /** @var array<int, int> $unpacked */ 490 $unpacked = unpack('P', $string); 491 return (int) $unpacked[1]; 492 } 493 494 /** @var int $result */ 495 $result = (self::chrToInt($string[0]) & 0xff); 496 $result |= (self::chrToInt($string[1]) & 0xff) << 8; 497 $result |= (self::chrToInt($string[2]) & 0xff) << 16; 498 $result |= (self::chrToInt($string[3]) & 0xff) << 24; 499 $result |= (self::chrToInt($string[4]) & 0xff) << 32; 500 $result |= (self::chrToInt($string[5]) & 0xff) << 40; 501 $result |= (self::chrToInt($string[6]) & 0xff) << 48; 502 $result |= (self::chrToInt($string[7]) & 0xff) << 56; 503 return (int) $result; 504 } 505 506 /** 507 * @internal You should not use this directly from another application 508 * 509 * @param string $left 510 * @param string $right 511 * @return int 512 * @throws SodiumException 513 * @throws TypeError 514 */ 515 public static function memcmp($left, $right) 516 { 517 if (self::hashEquals($left, $right)) { 518 return 0; 519 } 520 return -1; 521 } 522 523 /** 524 * Multiply two integers in constant-time 525 * 526 * Micro-architecture timing side-channels caused by how your CPU 527 * implements multiplication are best prevented by never using the 528 * multiplication operators and ensuring that our code always takes 529 * the same number of operations to complete, regardless of the values 530 * of $a and $b. 531 * 532 * @internal You should not use this directly from another application 533 * 534 * @param int $a 535 * @param int $b 536 * @param int $size Limits the number of operations (useful for small, 537 * constant operands) 538 * @return int 539 */ 540 public static function mul($a, $b, $size = 0) 541 { 542 if (ParagonIE_Sodium_Compat::$fastMult) { 543 return (int) ($a * $b); 544 } 545 546 static $defaultSize = null; 547 /** @var int $defaultSize */ 548 if (!$defaultSize) { 549 /** @var int $defaultSize */ 550 $defaultSize = (PHP_INT_SIZE << 3) - 1; 551 } 552 if ($size < 1) { 553 /** @var int $size */ 554 $size = $defaultSize; 555 } 556 /** @var int $size */ 557 558 $c = 0; 559 560 /** 561 * Mask is either -1 or 0. 562 * 563 * -1 in binary looks like 0x1111 ... 1111 564 * 0 in binary looks like 0x0000 ... 0000 565 * 566 * @var int 567 */ 568 $mask = -(($b >> ((int) $defaultSize)) & 1); 569 570 /** 571 * Ensure $b is a positive integer, without creating 572 * a branching side-channel 573 * 574 * @var int $b 575 */ 576 $b = ($b & ~$mask) | ($mask & -$b); 577 578 /** 579 * Unless $size is provided: 580 * 581 * This loop always runs 32 times when PHP_INT_SIZE is 4. 582 * This loop always runs 64 times when PHP_INT_SIZE is 8. 583 */ 584 for ($i = $size; $i >= 0; --$i) { 585 $c += (int) ($a & -($b & 1)); 586 $a <<= 1; 587 $b >>= 1; 588 } 589 $c = (int) @($c & -1); 590 591 /** 592 * If $b was negative, we then apply the same value to $c here. 593 * It doesn't matter much if $a was negative; the $c += above would 594 * have produced a negative integer to begin with. But a negative $b 595 * makes $b >>= 1 never return 0, so we would end up with incorrect 596 * results. 597 * 598 * The end result is what we'd expect from integer multiplication. 599 */ 600 return (int) (($c & ~$mask) | ($mask & -$c)); 601 } 602 603 /** 604 * Convert any arbitrary numbers into two 32-bit integers that represent 605 * a 64-bit integer. 606 * 607 * @internal You should not use this directly from another application 608 * 609 * @param int|float $num 610 * @return array<int, int> 611 */ 612 public static function numericTo64BitInteger($num) 613 { 614 $high = 0; 615 /** @var int $low */ 616 if (PHP_INT_SIZE === 4) { 617 $low = (int) $num; 618 } else { 619 $low = $num & 0xffffffff; 620 } 621 622 if ((+(abs($num))) >= 1) { 623 if ($num > 0) { 624 /** @var int $high */ 625 $high = min((+(floor($num/4294967296))), 4294967295); 626 } else { 627 /** @var int $high */ 628 $high = ~~((+(ceil(($num - (+((~~($num)))))/4294967296)))); 629 } 630 } 631 return array((int) $high, (int) $low); 632 } 633 634 /** 635 * Store a 24-bit integer into a string, treating it as big-endian. 636 * 637 * @internal You should not use this directly from another application 638 * 639 * @param int $int 640 * @return string 641 * @throws TypeError 642 */ 643 public static function store_3($int) 644 { 645 /* Type checks: */ 646 if (!is_int($int)) { 647 if (is_numeric($int)) { 648 $int = (int) $int; 649 } else { 650 throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); 651 } 652 } 653 /** @var string $packed */ 654 $packed = pack('N', $int); 655 return self::substr($packed, 1, 3); 656 } 657 658 /** 659 * Store a 32-bit integer into a string, treating it as little-endian. 660 * 661 * @internal You should not use this directly from another application 662 * 663 * @param int $int 664 * @return string 665 * @throws TypeError 666 */ 667 public static function store32_le($int) 668 { 669 /* Type checks: */ 670 if (!is_int($int)) { 671 if (is_numeric($int)) { 672 $int = (int) $int; 673 } else { 674 throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); 675 } 676 } 677 678 /** @var string $packed */ 679 $packed = pack('V', $int); 680 return $packed; 681 } 682 683 /** 684 * Store a 32-bit integer into a string, treating it as big-endian. 685 * 686 * @internal You should not use this directly from another application 687 * 688 * @param int $int 689 * @return string 690 * @throws TypeError 691 */ 692 public static function store_4($int) 693 { 694 /* Type checks: */ 695 if (!is_int($int)) { 696 if (is_numeric($int)) { 697 $int = (int) $int; 698 } else { 699 throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); 700 } 701 } 702 703 /** @var string $packed */ 704 $packed = pack('N', $int); 705 return $packed; 706 } 707 708 /** 709 * Stores a 64-bit integer as an string, treating it as little-endian. 710 * 711 * @internal You should not use this directly from another application 712 * 713 * @param int $int 714 * @return string 715 * @throws TypeError 716 */ 717 public static function store64_le($int) 718 { 719 /* Type checks: */ 720 if (!is_int($int)) { 721 if (is_numeric($int)) { 722 $int = (int) $int; 723 } else { 724 throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); 725 } 726 } 727 728 if (PHP_INT_SIZE === 8) { 729 if (PHP_VERSION_ID >= 50603) { 730 /** @var string $packed */ 731 $packed = pack('P', $int); 732 return $packed; 733 } 734 return self::intToChr($int & 0xff) . 735 self::intToChr(($int >> 8) & 0xff) . 736 self::intToChr(($int >> 16) & 0xff) . 737 self::intToChr(($int >> 24) & 0xff) . 738 self::intToChr(($int >> 32) & 0xff) . 739 self::intToChr(($int >> 40) & 0xff) . 740 self::intToChr(($int >> 48) & 0xff) . 741 self::intToChr(($int >> 56) & 0xff); 742 } 743 if ($int > PHP_INT_MAX) { 744 list($hiB, $int) = self::numericTo64BitInteger($int); 745 } else { 746 $hiB = 0; 747 } 748 return 749 self::intToChr(($int ) & 0xff) . 750 self::intToChr(($int >> 8) & 0xff) . 751 self::intToChr(($int >> 16) & 0xff) . 752 self::intToChr(($int >> 24) & 0xff) . 753 self::intToChr($hiB & 0xff) . 754 self::intToChr(($hiB >> 8) & 0xff) . 755 self::intToChr(($hiB >> 16) & 0xff) . 756 self::intToChr(($hiB >> 24) & 0xff); 757 } 758 759 /** 760 * Safe string length 761 * 762 * @internal You should not use this directly from another application 763 * 764 * @ref mbstring.func_overload 765 * 766 * @param string $str 767 * @return int 768 * @throws TypeError 769 */ 770 public static function strlen($str) 771 { 772 /* Type checks: */ 773 if (!is_string($str)) { 774 throw new TypeError('String expected'); 775 } 776 777 return (int) ( 778 self::isMbStringOverride() 779 ? mb_strlen($str, '8bit') 780 : strlen($str) 781 ); 782 } 783 784 /** 785 * Turn a string into an array of integers 786 * 787 * @internal You should not use this directly from another application 788 * 789 * @param string $string 790 * @return array<int, int> 791 * @throws TypeError 792 */ 793 public static function stringToIntArray($string) 794 { 795 if (!is_string($string)) { 796 throw new TypeError('String expected'); 797 } 798 /** 799 * @var array<int, int> 800 */ 801 $values = array_values( 802 unpack('C*', $string) 803 ); 804 return $values; 805 } 806 807 /** 808 * Safe substring 809 * 810 * @internal You should not use this directly from another application 811 * 812 * @ref mbstring.func_overload 813 * 814 * @param string $str 815 * @param int $start 816 * @param int $length 817 * @return string 818 * @throws TypeError 819 */ 820 public static function substr($str, $start = 0, $length = null) 821 { 822 /* Type checks: */ 823 if (!is_string($str)) { 824 throw new TypeError('String expected'); 825 } 826 827 if ($length === 0) { 828 return ''; 829 } 830 831 if (self::isMbStringOverride()) { 832 if (PHP_VERSION_ID < 50400 && $length === null) { 833 $length = self::strlen($str); 834 } 835 $sub = (string) mb_substr($str, $start, $length, '8bit'); 836 } elseif ($length === null) { 837 $sub = (string) substr($str, $start); 838 } else { 839 $sub = (string) substr($str, $start, $length); 840 } 841 if ($sub !== '') { 842 return $sub; 843 } 844 return ''; 845 } 846 847 /** 848 * Compare a 16-character byte string in constant time. 849 * 850 * @internal You should not use this directly from another application 851 * 852 * @param string $a 853 * @param string $b 854 * @return bool 855 * @throws SodiumException 856 * @throws TypeError 857 */ 858 public static function verify_16($a, $b) 859 { 860 /* Type checks: */ 861 if (!is_string($a)) { 862 throw new TypeError('String expected'); 863 } 864 if (!is_string($b)) { 865 throw new TypeError('String expected'); 866 } 867 return self::hashEquals( 868 self::substr($a, 0, 16), 869 self::substr($b, 0, 16) 870 ); 871 } 872 873 /** 874 * Compare a 32-character byte string in constant time. 875 * 876 * @internal You should not use this directly from another application 877 * 878 * @param string $a 879 * @param string $b 880 * @return bool 881 * @throws SodiumException 882 * @throws TypeError 883 */ 884 public static function verify_32($a, $b) 885 { 886 /* Type checks: */ 887 if (!is_string($a)) { 888 throw new TypeError('String expected'); 889 } 890 if (!is_string($b)) { 891 throw new TypeError('String expected'); 892 } 893 return self::hashEquals( 894 self::substr($a, 0, 32), 895 self::substr($b, 0, 32) 896 ); 897 } 898 899 /** 900 * Calculate $a ^ $b for two strings. 901 * 902 * @internal You should not use this directly from another application 903 * 904 * @param string $a 905 * @param string $b 906 * @return string 907 * @throws TypeError 908 */ 909 public static function xorStrings($a, $b) 910 { 911 /* Type checks: */ 912 if (!is_string($a)) { 913 throw new TypeError('Argument 1 must be a string'); 914 } 915 if (!is_string($b)) { 916 throw new TypeError('Argument 2 must be a string'); 917 } 918 919 return (string) ($a ^ $b); 920 } 921 922 /** 923 * Returns whether or not mbstring.func_overload is in effect. 924 * 925 * @internal You should not use this directly from another application 926 * 927 * Note: MB_OVERLOAD_STRING === 2, but we don't reference the constant 928 * (for nuisance-free PHP 8 support) 929 * 930 * @return bool 931 */ 932 protected static function isMbStringOverride() 933 { 934 static $mbstring = null; 935 936 if ($mbstring === null) { 937 if (!defined('MB_OVERLOAD_STRING')) { 938 $mbstring = false; 939 return $mbstring; 940 } 941 $mbstring = extension_loaded('mbstring') 942 && defined('MB_OVERLOAD_STRING') 943 && 944 ((int) (ini_get('mbstring.func_overload')) & 2); 945 // MB_OVERLOAD_STRING === 2 946 } 947 /** @var bool $mbstring */ 948 949 return $mbstring; 950 } 951 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Dec 24 01:00:02 2024 | Cross-referenced by PHPXref 0.7.1 |