: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if (self::useNewSodiumAPI()) {
return sodium_crypto_stream($len, $nonce, $key);
if (self::use_fallback('crypto_stream')) {
return (string) call_user_func('\\Sodium\\crypto_stream', $len, $nonce, $key);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Core32_XSalsa20::xsalsa20($len, $nonce, $key);
return ParagonIE_Sodium_Core_XSalsa20::xsalsa20($len, $nonce, $key);
* DANGER! UNAUTHENTICATED ENCRYPTION!
* Unless you are following expert advice, do not use this feature.
* This DOES NOT provide ciphertext integrity.
* @param string $message Plaintext message
* @param string $nonce Number to be used Once; must be 24 bytes
* @param string $key Encryption key
* @return string Encrypted text which is vulnerable to chosen-
* ciphertext attacks unless you implement some
* other mitigation to the ciphertext (i.e.
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_stream_xor($message, $nonce, $key)
ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2);
ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3);
if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_NONCEBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.');
if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_KEYBYTES) {
throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.');
if (self::useNewSodiumAPI()) {
return sodium_crypto_stream_xor($message, $nonce, $key);
if (self::use_fallback('crypto_stream_xor')) {
return (string) call_user_func('\\Sodium\\crypto_stream_xor', $message, $nonce, $key);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Core32_XSalsa20::xsalsa20_xor($message, $nonce, $key);
return ParagonIE_Sodium_Core_XSalsa20::xsalsa20_xor($message, $nonce, $key);
* Return a secure random key for use with crypto_stream
public static function crypto_stream_keygen()
return random_bytes(self::CRYPTO_STREAM_KEYBYTES);
* Expand a key and nonce into a keystream of pseudorandom bytes.
* @param int $len Number of bytes desired
* @param string $nonce Number to be used Once; must be 24 bytes
* @param string $key XChaCha20 key
* @param bool $dontFallback
* @return string Pseudorandom stream that can be XORed with messages
* to provide encryption (but not authentication; see
* Poly1305 or crypto_auth() for that, which is not
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_stream_xchacha20($len, $nonce, $key, $dontFallback = false)
ParagonIE_Sodium_Core_Util::declareScalarType($len, 'int', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2);
ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3);
if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.');
if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) {
throw new SodiumException('Argument 3 must be CRYPTO_STREAM_XCHACHA20_KEYBYTES long.');
if (self::useNewSodiumAPI() && !$dontFallback) {
return sodium_crypto_stream_xchacha20($len, $nonce, $key);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Core32_XChaCha20::stream($len, $nonce, $key);
return ParagonIE_Sodium_Core_XChaCha20::stream($len, $nonce, $key);
* DANGER! UNAUTHENTICATED ENCRYPTION!
* Unless you are following expert advice, do not use this feature.
* This DOES NOT provide ciphertext integrity.
* @param string $message Plaintext message
* @param string $nonce Number to be used Once; must be 24 bytes
* @param string $key Encryption key
* @return string Encrypted text which is vulnerable to chosen-
* ciphertext attacks unless you implement some
* other mitigation to the ciphertext (i.e.
* @param bool $dontFallback
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_stream_xchacha20_xor($message, $nonce, $key, $dontFallback = false)
ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2);
ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3);
if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.');
if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) {
throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_XCHACHA20_KEYBYTES long.');
if (self::useNewSodiumAPI() && !$dontFallback) {
return sodium_crypto_stream_xchacha20_xor($message, $nonce, $key);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Core32_XChaCha20::streamXorIc($message, $nonce, $key);
return ParagonIE_Sodium_Core_XChaCha20::streamXorIc($message, $nonce, $key);
* DANGER! UNAUTHENTICATED ENCRYPTION!
* Unless you are following expert advice, do not use this feature.
* This DOES NOT provide ciphertext integrity.
* @param string $message Plaintext message
* @param string $nonce Number to be used Once; must be 24 bytes
* @param string $key Encryption key
* @return string Encrypted text which is vulnerable to chosen-
* ciphertext attacks unless you implement some
* other mitigation to the ciphertext (i.e.
* @param bool $dontFallback
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_stream_xchacha20_xor_ic($message, $nonce, $counter, $key, $dontFallback = false)
ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2);
ParagonIE_Sodium_Core_Util::declareScalarType($counter, 'int', 3);
ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4);
if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.');
if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) {
throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_XCHACHA20_KEYBYTES long.');
if (is_callable('sodium_crypto_stream_xchacha20_xor_ic') && !$dontFallback) {
return sodium_crypto_stream_xchacha20_xor_ic($message, $nonce, $counter, $key);
$ic = ParagonIE_Sodium_Core_Util::store64_le($counter);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Core32_XChaCha20::streamXorIc($message, $nonce, $key, $ic);
return ParagonIE_Sodium_Core_XChaCha20::streamXorIc($message, $nonce, $key, $ic);
* Return a secure random key for use with crypto_stream_xchacha20
public static function crypto_stream_xchacha20_keygen()
return random_bytes(self::CRYPTO_STREAM_XCHACHA20_KEYBYTES);
* Cache-timing-safe implementation of hex2bin().
* @param string $string Hexadecimal string
* @param string $ignore List of characters to ignore; useful for whitespace
* @return string Raw binary string
* @throws SodiumException
* @psalm-suppress TooFewArguments
* @psalm-suppress MixedArgument
public static function hex2bin($string, $ignore = '')
ParagonIE_Sodium_Core_Util::declareScalarType($string, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($ignore, 'string', 2);
if (self::useNewSodiumAPI()) {
if (is_callable('sodium_hex2bin')) {
return (string) sodium_hex2bin($string, $ignore);
if (self::use_fallback('hex2bin')) {
return (string) call_user_func('\\Sodium\\hex2bin', $string, $ignore);
return ParagonIE_Sodium_Core_Util::hex2bin($string, $ignore);
* Increase a string (little endian)
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function increment(&$var)
ParagonIE_Sodium_Core_Util::declareScalarType($var, 'string', 1);
if (self::useNewSodiumAPI()) {
if (self::use_fallback('increment')) {
$func = '\\Sodium\\increment';
$len = ParagonIE_Sodium_Core_Util::strlen($var);
for ($i = 0; $i < $len; ++$i) {
$c += ParagonIE_Sodium_Core_Util::chrToInt(
ParagonIE_Sodium_Core_Util::substr($var, $i, 1)
$copy .= ParagonIE_Sodium_Core_Util::intToChr($c);
* @throws SodiumException
public static function is_zero($str)
for ($i = 0; $i < 32; ++$i) {
$d |= ParagonIE_Sodium_Core_Util::chrToInt($str[$i]);
return ((($d - 1) >> 31) & 1) === 1;
* The equivalent to the libsodium minor version we aim to be compatible
* with (sans pwhash and memzero).
public static function library_version_major()
if (self::useNewSodiumAPI() && defined('SODIUM_LIBRARY_MAJOR_VERSION')) {
return SODIUM_LIBRARY_MAJOR_VERSION;
if (self::use_fallback('library_version_major')) {
/** @psalm-suppress UndefinedFunction */
return (int) call_user_func('\\Sodium\\library_version_major');
return self::LIBRARY_VERSION_MAJOR;
* The equivalent to the libsodium minor version we aim to be compatible
* with (sans pwhash and memzero).
public static function library_version_minor()
if (self::useNewSodiumAPI() && defined('SODIUM_LIBRARY_MINOR_VERSION')) {
return SODIUM_LIBRARY_MINOR_VERSION;
if (self::use_fallback('library_version_minor')) {
/** @psalm-suppress UndefinedFunction */
return (int) call_user_func('\\Sodium\\library_version_minor');
return self::LIBRARY_VERSION_MINOR;
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function memcmp($left, $right)
ParagonIE_Sodium_Core_Util::declareScalarType($left, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($right, 'string', 2);
if (self::useNewSodiumAPI()) {
return sodium_memcmp($left, $right);
if (self::use_fallback('memcmp')) {
return (int) call_user_func('\\Sodium\\memcmp', $left, $right);
/** @var string $right */
return ParagonIE_Sodium_Core_Util::memcmp($left, $right);
* It's actually not possible to zero memory buffers in PHP. You need the
* native library for that.
* @param string|null $var
* @param-out string|null $var
* @throws SodiumException (Unless libsodium is installed)
* @psalm-suppress TooFewArguments
public static function memzero(&$var)
ParagonIE_Sodium_Core_Util::declareScalarType($var, 'string', 1);
if (self::useNewSodiumAPI()) {
/** @psalm-suppress MixedArgument */
if (self::use_fallback('memzero')) {
$func = '\\Sodium\\memzero';
// This is the best we can do.
throw new SodiumException(
'This is not implemented in sodium_compat, as it is not possible to securely wipe memory from PHP. ' .
'To fix this error, make sure libsodium is installed and the PHP extension is enabled.'
* @param string $unpadded
* @param bool $dontFallback
* @throws SodiumException
public static function pad($unpadded, $blockSize, $dontFallback = false)
ParagonIE_Sodium_Core_Util::declareScalarType($unpadded, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($blockSize, 'int', 2);
$unpadded = (string) $unpadded;
$blockSize = (int) $blockSize;
if (self::useNewSodiumAPI() && !$dontFallback) {
return (string) sodium_pad($unpadded, $blockSize);
throw new SodiumException(
'block size cannot be less than 1'
$unpadded_len = ParagonIE_Sodium_Core_Util::strlen($unpadded);
$xpadlen = ($blockSize - 1);
if (($blockSize & ($blockSize - 1)) === 0) {
$xpadlen -= $unpadded_len & ($blockSize - 1);
$xpadlen -= $unpadded_len % $blockSize;
$xpadded_len = $unpadded_len + $xpadlen;
$padded = str_repeat("\0", $xpadded_len - 1);
for ($j = 0; $j <= $xpadded_len; ++$j) {
if ($j >= $unpadded_len) {
$padded[$j] = $unpadded[$j];
for ($i = 0; $i < $blockSize; ++$i) {
# barrier_mask = (unsigned char)
# (((i ^ xpadlen) - 1U) >> ((sizeof(size_t) - 1U) * CHAR_BIT));
$barrier_mask = (($i ^ $xpadlen) -1) >> ((PHP_INT_SIZE << 3) - 1);
# tail[-i] = (tail[-i] & mask) | (0x80 & barrier_mask);
$padded[$tail - $i] = ParagonIE_Sodium_Core_Util::intToChr(
(ParagonIE_Sodium_Core_Util::chrToInt($padded[$tail - $i]) & $mask)
* @param bool $dontFallback
* @throws SodiumException
public static function unpad($padded, $blockSize, $dontFallback = false)
ParagonIE_Sodium_Core_Util::declareScalarType($padded, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($blockSize, 'int', 2);
$padded = (string) $padded;
$blockSize = (int) $blockSize;
if (self::useNewSodiumAPI() && !$dontFallback) {