: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
$ciphertext = ParagonIE_Sodium_Core_Util::substr($message, 32);
/** @var string $secretKey */
$secretKey = self::box_secretkey($keypair);
/** @var string $publicKey */
$publicKey = self::box_publickey($keypair);
/** @var string $nonce */
$nonce = self::generichash(
$ephemeralPK . $publicKey,
/** @var string $keypair */
$keypair = self::box_keypair_from_secretkey_and_publickey($secretKey, $ephemeralPK);
$m = self::box_open($ciphertext, $nonce, $keypair);
ParagonIE_Sodium_Compat::memzero($secretKey);
ParagonIE_Sodium_Compat::memzero($ephemeralPK);
ParagonIE_Sodium_Compat::memzero($nonce);
} catch (SodiumException $ex) {
* Used by crypto_box() to get the crypto_secretbox() key.
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
* @throws SodiumException
public static function box_beforenm($sk, $pk)
return ParagonIE_Sodium_Core_HSalsa20::hsalsa20(
self::scalarmult($sk, $pk)
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
* @throws SodiumException
public static function box_keypair()
$sKey = random_bytes(32);
$pKey = self::scalarmult_base($sKey);
* @throws SodiumException
public static function box_seed_keypair($seed)
$sKey = ParagonIE_Sodium_Core_Util::substr(
hash('sha512', $seed, true),
$pKey = self::scalarmult_base($sKey);
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
public static function box_keypair_from_secretkey_and_publickey($sKey, $pKey)
return ParagonIE_Sodium_Core_Util::substr($sKey, 0, 32) .
ParagonIE_Sodium_Core_Util::substr($pKey, 0, 32);
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
public static function box_secretkey($keypair)
if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== 64) {
throw new RangeException(
'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.'
return ParagonIE_Sodium_Core_Util::substr($keypair, 0, 32);
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
public static function box_publickey($keypair)
if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
throw new RangeException(
'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.'
return ParagonIE_Sodium_Core_Util::substr($keypair, 32, 32);
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
* @throws SodiumException
public static function box_publickey_from_secretkey($sKey)
if (ParagonIE_Sodium_Core_Util::strlen($sKey) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES) {
throw new RangeException(
'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES bytes long.'
return self::scalarmult_base($sKey);
* Decrypt a message encrypted with box().
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
* @param string $ciphertext
* @throws SodiumException
public static function box_open($ciphertext, $nonce, $keypair)
return self::secretbox_open(
self::box_secretkey($keypair),
self::box_publickey($keypair)
* Calculate a BLAKE2b hash.
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
* @param string|null $key
* @throws SodiumException
public static function generichash($message, $key = '', $outlen = 32)
// This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized
ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();
/** @var SplFixedArray $k */
$k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key);
if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) {
throw new RangeException('Invalid key size');
/** @var SplFixedArray $in */
$in = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($message);
/** @var SplFixedArray $ctx */
$ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outlen);
ParagonIE_Sodium_Core_BLAKE2b::update($ctx, $in, $in->count());
/** @var SplFixedArray $out */
$out = new SplFixedArray($outlen);
$out = ParagonIE_Sodium_Core_BLAKE2b::finish($ctx, $out);
/** @var array<int, int> */
$outArray = $out->toArray();
return ParagonIE_Sodium_Core_Util::intArrayToString($outArray);
* Finalize a BLAKE2b hashing context, returning the hash.
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
* @throws SodiumException
public static function generichash_final($ctx, $outlen = 32)
throw new TypeError('Context must be a string');
$out = new SplFixedArray($outlen);
/** @var SplFixedArray $context */
$context = ParagonIE_Sodium_Core_BLAKE2b::stringToContext($ctx);
/** @var SplFixedArray $out */
$out = ParagonIE_Sodium_Core_BLAKE2b::finish($context, $out);
/** @var array<int, int> */
$outArray = $out->toArray();
return ParagonIE_Sodium_Core_Util::intArrayToString($outArray);
* Initialize a hashing context for BLAKE2b.
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
* @param int $outputLength
* @throws SodiumException
public static function generichash_init($key = '', $outputLength = 32)
// This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized
ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();
$k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key);
if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) {
throw new RangeException('Invalid key size');
/** @var SplFixedArray $ctx */
$ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength);
return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx);
* Initialize a hashing context for BLAKE2b.
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
* @param int $outputLength
* @param string $personal
* @throws SodiumException
public static function generichash_init_salt_personal(
// This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized
ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();
$k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key);
if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) {
throw new RangeException('Invalid key size');
$s = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($salt);
$p = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($personal);
/** @var SplFixedArray $ctx */
$ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength, $s, $p);
return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx);
* Update a hashing context for BLAKE2b with $message
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
* @throws SodiumException
public static function generichash_update($ctx, $message)
// This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized
ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();
/** @var SplFixedArray $context */
$context = ParagonIE_Sodium_Core_BLAKE2b::stringToContext($ctx);
/** @var SplFixedArray $in */
$in = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($message);
ParagonIE_Sodium_Core_BLAKE2b::update($context, $in, $in->count());
return ParagonIE_Sodium_Core_BLAKE2b::contextToString($context);
* Libsodium's crypto_kx().
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
* @param string $their_pk
* @param string $client_pk
* @param string $server_pk
* @throws SodiumException
public static function keyExchange($my_sk, $their_pk, $client_pk, $server_pk)
return ParagonIE_Sodium_Compat::crypto_generichash(
ParagonIE_Sodium_Compat::crypto_scalarmult($my_sk, $their_pk) .
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
* @throws SodiumException
public static function scalarmult($sKey, $pKey)
$q = ParagonIE_Sodium_Core_X25519::crypto_scalarmult_curve25519_ref10($sKey, $pKey);
self::scalarmult_throw_if_zero($q);
* ECDH over Curve25519, using the basepoint.
* Used to get a secret key from a public key.
* @throws SodiumException
public static function scalarmult_base($secret)
$q = ParagonIE_Sodium_Core_X25519::crypto_scalarmult_curve25519_ref10_base($secret);
self::scalarmult_throw_if_zero($q);
* This throws an Error if a zero public key was passed to the function.
* @throws SodiumException
protected static function scalarmult_throw_if_zero($q)
for ($i = 0; $i < self::box_curve25519xsalsa20poly1305_SECRETKEYBYTES; ++$i) {
$d |= ParagonIE_Sodium_Core_Util::chrToInt($q[$i]);
/* branch-free variant of === 0 */
if (-(1 & (($d - 1) >> 8))) {
throw new SodiumException('Zero public key is not allowed');
* XSalsa20-Poly1305 authenticated symmetric-key encryption.
* @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
* @param string $plaintext
* @throws SodiumException
public static function secretbox($plaintext, $nonce, $key)
/** @var string $subkey */
$subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);
/** @var string $block0 */
$block0 = str_repeat("\x00", 32);
/** @var int $mlen - Length of the plaintext message */
$mlen = ParagonIE_Sodium_Core_Util::strlen($plaintext);
if ($mlen0 > 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES) {
$mlen0 = 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES;
$block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0, $mlen0);
/** @var string $block0 */
$block0 = ParagonIE_Sodium_Core_Salsa20::salsa20_xor(
ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
$c = ParagonIE_Sodium_Core_Util::substr(
self::secretbox_xsalsa20poly1305_ZEROBYTES
$c .= ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
ParagonIE_Sodium_Core_Util::substr(
self::secretbox_xsalsa20poly1305_ZEROBYTES
ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
$state = new ParagonIE_Sodium_Core_Poly1305_State(
ParagonIE_Sodium_Core_Util::substr(
self::onetimeauth_poly1305_KEYBYTES
ParagonIE_Sodium_Compat::memzero($block0);
ParagonIE_Sodium_Compat::memzero($subkey);
} catch (SodiumException $ex) {