: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @internal You should not use this directly from another application
* @throws SodiumException
public static function memcmp($left, $right)
if (self::hashEquals($left, $right)) {
* Multiply two integers in constant-time
* Micro-architecture timing side-channels caused by how your CPU
* implements multiplication are best prevented by never using the
* multiplication operators and ensuring that our code always takes
* the same number of operations to complete, regardless of the values
* @internal You should not use this directly from another application
* @param int $size Limits the number of operations (useful for small,
public static function mul($a, $b, $size = 0)
if (ParagonIE_Sodium_Compat::$fastMult) {
static $defaultSize = null;
/** @var int $defaultSize */
/** @var int $defaultSize */
$defaultSize = (PHP_INT_SIZE << 3) - 1;
* Mask is either -1 or 0.
* -1 in binary looks like 0x1111 ... 1111
* 0 in binary looks like 0x0000 ... 0000
$mask = -(($b >> ((int) $defaultSize)) & 1);
* Ensure $b is a positive integer, without creating
* a branching side-channel
$b = ($b & ~$mask) | ($mask & -$b);
* Unless $size is provided:
* This loop always runs 32 times when PHP_INT_SIZE is 4.
* This loop always runs 64 times when PHP_INT_SIZE is 8.
for ($i = $size; $i >= 0; --$i) {
$c += (int) ($a & -($b & 1));
* If $b was negative, we then apply the same value to $c here.
* It doesn't matter much if $a was negative; the $c += above would
* have produced a negative integer to begin with. But a negative $b
* makes $b >>= 1 never return 0, so we would end up with incorrect
* The end result is what we'd expect from integer multiplication.
return (int) (($c & ~$mask) | ($mask & -$c));
* Convert any arbitrary numbers into two 32-bit integers that represent
* @internal You should not use this directly from another application
* @return array<int, int>
public static function numericTo64BitInteger($num)
if (PHP_INT_SIZE === 4) {
$low = $num & 0xffffffff;
if ((+(abs($num))) >= 1) {
$high = min((+(floor($num/4294967296))), 4294967295);
$high = ~~((+(ceil(($num - (+((~~($num)))))/4294967296))));
return array((int) $high, (int) $low);
* Store a 24-bit integer into a string, treating it as big-endian.
* @internal You should not use this directly from another application
public static function store_3($int)
throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.');
/** @var string $packed */
$packed = pack('N', $int);
return self::substr($packed, 1, 3);
* Store a 32-bit integer into a string, treating it as little-endian.
* @internal You should not use this directly from another application
public static function store32_le($int)
throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.');
/** @var string $packed */
$packed = pack('V', $int);
* Store a 32-bit integer into a string, treating it as big-endian.
* @internal You should not use this directly from another application
public static function store_4($int)
throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.');
/** @var string $packed */
$packed = pack('N', $int);
* Stores a 64-bit integer as an string, treating it as little-endian.
* @internal You should not use this directly from another application
public static function store64_le($int)
throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.');
if (PHP_INT_SIZE === 8) {
if (PHP_VERSION_ID >= 50603) {
/** @var string $packed */
$packed = pack('P', $int);
return self::intToChr($int & 0xff) .
self::intToChr(($int >> 8) & 0xff) .
self::intToChr(($int >> 16) & 0xff) .
self::intToChr(($int >> 24) & 0xff) .
self::intToChr(($int >> 32) & 0xff) .
self::intToChr(($int >> 40) & 0xff) .
self::intToChr(($int >> 48) & 0xff) .
self::intToChr(($int >> 56) & 0xff);
if ($int > PHP_INT_MAX) {
list($hiB, $int) = self::numericTo64BitInteger($int);
self::intToChr(($int ) & 0xff) .
self::intToChr(($int >> 8) & 0xff) .
self::intToChr(($int >> 16) & 0xff) .
self::intToChr(($int >> 24) & 0xff) .
self::intToChr($hiB & 0xff) .
self::intToChr(($hiB >> 8) & 0xff) .
self::intToChr(($hiB >> 16) & 0xff) .
self::intToChr(($hiB >> 24) & 0xff);
* @internal You should not use this directly from another application
* @ref mbstring.func_overload
public static function strlen($str)
throw new TypeError('String expected');
self::isMbStringOverride()
? mb_strlen($str, '8bit')
* Turn a string into an array of integers
* @internal You should not use this directly from another application
* @return array<int, int>
public static function stringToIntArray($string)
if (!is_string($string)) {
throw new TypeError('String expected');
* @internal You should not use this directly from another application
* @ref mbstring.func_overload
public static function substr($str, $start = 0, $length = null)
throw new TypeError('String expected');
if (self::isMbStringOverride()) {
if (PHP_VERSION_ID < 50400 && $length === null) {
$length = self::strlen($str);
$sub = (string) mb_substr($str, $start, $length, '8bit');
} elseif ($length === null) {
$sub = (string) substr($str, $start);
$sub = (string) substr($str, $start, $length);
* Compare a 16-character byte string in constant time.
* @internal You should not use this directly from another application
* @throws SodiumException
public static function verify_16($a, $b)
throw new TypeError('String expected');
throw new TypeError('String expected');
* Compare a 32-character byte string in constant time.
* @internal You should not use this directly from another application
* @throws SodiumException
public static function verify_32($a, $b)
throw new TypeError('String expected');
throw new TypeError('String expected');
* Calculate $a ^ $b for two strings.
* @internal You should not use this directly from another application
public static function xorStrings($a, $b)
throw new TypeError('Argument 1 must be a string');
throw new TypeError('Argument 2 must be a string');
return (string) ($a ^ $b);
* Returns whether or not mbstring.func_overload is in effect.
* @internal You should not use this directly from another application
* Note: MB_OVERLOAD_STRING === 2, but we don't reference the constant
* (for nuisance-free PHP 8 support)
protected static function isMbStringOverride()
if ($mbstring === null) {
if (!defined('MB_OVERLOAD_STRING')) {
$mbstring = extension_loaded('mbstring')
&& defined('MB_OVERLOAD_STRING')
((int) (ini_get('mbstring.func_overload')) & 2);
// MB_OVERLOAD_STRING === 2
/** @var bool $mbstring */