: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
public static function crypto_auth_keygen()
return random_bytes(self::CRYPTO_AUTH_KEYBYTES);
* Verify the MAC of a message previously authenticated with crypto_auth.
* @param string $mac Message authentication code
* @param string $message Message whose authenticity you are attempting to
* verify (with a given MAC and key)
* @param string $key Symmetric authentication key
* @return bool TRUE if authenticated, FALSE otherwise
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_auth_verify($mac, $message, $key)
ParagonIE_Sodium_Core_Util::declareScalarType($mac, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 2);
ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3);
if (ParagonIE_Sodium_Core_Util::strlen($mac) !== self::CRYPTO_AUTH_BYTES) {
throw new SodiumException('Argument 1 must be CRYPTO_AUTH_BYTES long.');
if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AUTH_KEYBYTES) {
throw new SodiumException('Argument 3 must be CRYPTO_AUTH_KEYBYTES long.');
if (self::useNewSodiumAPI()) {
return (bool) sodium_crypto_auth_verify($mac, $message, $key);
if (self::use_fallback('crypto_auth_verify')) {
return (bool) call_user_func('\\Sodium\\crypto_auth_verify', $mac, $message, $key);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::auth_verify($mac, $message, $key);
return ParagonIE_Sodium_Crypto::auth_verify($mac, $message, $key);
* Authenticated asymmetric-key encryption. Both the sender and recipient
* Algorithm: X25519-XSalsa20-Poly1305.
* X25519: Elliptic-Curve Diffie Hellman over Curve25519.
* XSalsa20: Extended-nonce variant of salsa20.
* Poyl1305: Polynomial MAC for one-time message authentication.
* @param string $plaintext The message to be encrypted
* @param string $nonce A Number to only be used Once; must be 24 bytes
* @param string $keypair Your secret key and your recipient's public key
* @return string Ciphertext with 16-byte Poly1305 MAC
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_box($plaintext, $nonce, $keypair)
ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2);
ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 3);
if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_BOX_NONCEBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_BOX_NONCEBYTES long.');
if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) {
throw new SodiumException('Argument 3 must be CRYPTO_BOX_KEYPAIRBYTES long.');
if (self::useNewSodiumAPI()) {
return (string) sodium_crypto_box($plaintext, $nonce, $keypair);
if (self::use_fallback('crypto_box')) {
return (string) call_user_func('\\Sodium\\crypto_box', $plaintext, $nonce, $keypair);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::box($plaintext, $nonce, $keypair);
return ParagonIE_Sodium_Crypto::box($plaintext, $nonce, $keypair);
* Anonymous public-key encryption. Only the recipient may decrypt messages.
* Algorithm: X25519-XSalsa20-Poly1305, as with crypto_box.
* The sender's X25519 keypair is ephemeral.
* Nonce is generated from the BLAKE2b hash of both public keys.
* This provides ciphertext integrity.
* @param string $plaintext Message to be sealed
* @param string $publicKey Your recipient's public key
* @return string Sealed message that only your recipient can
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_box_seal($plaintext, $publicKey)
ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 2);
if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_BOX_PUBLICKEYBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.');
if (self::useNewSodiumAPI()) {
return (string) sodium_crypto_box_seal($plaintext, $publicKey);
if (self::use_fallback('crypto_box_seal')) {
return (string) call_user_func('\\Sodium\\crypto_box_seal', $plaintext, $publicKey);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::box_seal($plaintext, $publicKey);
return ParagonIE_Sodium_Crypto::box_seal($plaintext, $publicKey);
* Opens a message encrypted with crypto_box_seal(). Requires
* the recipient's keypair (sk || pk) to decrypt successfully.
* This validates ciphertext integrity.
* @param string $ciphertext Sealed message to be opened
* @param string $keypair Your crypto_box keypair
* @return string The original plaintext message
* @throws SodiumException
* @psalm-suppress MixedArgument
* @psalm-suppress MixedInferredReturnType
* @psalm-suppress MixedReturnStatement
public static function crypto_box_seal_open($ciphertext, $keypair)
ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 2);
if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_BOX_KEYPAIRBYTES long.');
if (self::useNewSodiumAPI()) {
* @psalm-suppress InvalidReturnStatement
* @psalm-suppress FalsableReturnStatement
return sodium_crypto_box_seal_open($ciphertext, $keypair);
if (self::use_fallback('crypto_box_seal_open')) {
return call_user_func('\\Sodium\\crypto_box_seal_open', $ciphertext, $keypair);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::box_seal_open($ciphertext, $keypair);
return ParagonIE_Sodium_Crypto::box_seal_open($ciphertext, $keypair);
* Generate a new random X25519 keypair.
* @return string A 64-byte string; the first 32 are your secret key, while
* the last 32 are your public key. crypto_box_secretkey()
* and crypto_box_publickey() exist to separate them so you
* don't accidentally get them mixed up!
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_box_keypair()
if (self::useNewSodiumAPI()) {
return (string) sodium_crypto_box_keypair();
if (self::use_fallback('crypto_box_keypair')) {
return (string) call_user_func('\\Sodium\\crypto_box_keypair');
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::box_keypair();
return ParagonIE_Sodium_Crypto::box_keypair();
* Combine two keys into a keypair for use in library methods that expect
* a keypair. This doesn't necessarily have to be the same person's keys.
* @param string $secretKey Secret key
* @param string $publicKey Public key
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_box_keypair_from_secretkey_and_publickey($secretKey, $publicKey)
ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 2);
if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_BOX_SECRETKEYBYTES) {
throw new SodiumException('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.');
if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_BOX_PUBLICKEYBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.');
if (self::useNewSodiumAPI()) {
return (string) sodium_crypto_box_keypair_from_secretkey_and_publickey($secretKey, $publicKey);
if (self::use_fallback('crypto_box_keypair_from_secretkey_and_publickey')) {
return (string) call_user_func('\\Sodium\\crypto_box_keypair_from_secretkey_and_publickey', $secretKey, $publicKey);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::box_keypair_from_secretkey_and_publickey($secretKey, $publicKey);
return ParagonIE_Sodium_Crypto::box_keypair_from_secretkey_and_publickey($secretKey, $publicKey);
* Decrypt a message previously encrypted with crypto_box().
* @param string $ciphertext Encrypted message
* @param string $nonce Number to only be used Once; must be 24 bytes
* @param string $keypair Your secret key and the sender's public key
* @return string The original plaintext message
* @throws SodiumException
* @psalm-suppress MixedArgument
* @psalm-suppress MixedInferredReturnType
* @psalm-suppress MixedReturnStatement
public static function crypto_box_open($ciphertext, $nonce, $keypair)
ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2);
ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 3);
if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_BOX_MACBYTES) {
throw new SodiumException('Argument 1 must be at least CRYPTO_BOX_MACBYTES long.');
if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_BOX_NONCEBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_BOX_NONCEBYTES long.');
if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) {
throw new SodiumException('Argument 3 must be CRYPTO_BOX_KEYPAIRBYTES long.');
if (self::useNewSodiumAPI()) {
* @psalm-suppress InvalidReturnStatement
* @psalm-suppress FalsableReturnStatement
return sodium_crypto_box_open($ciphertext, $nonce, $keypair);
if (self::use_fallback('crypto_box_open')) {
return call_user_func('\\Sodium\\crypto_box_open', $ciphertext, $nonce, $keypair);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::box_open($ciphertext, $nonce, $keypair);
return ParagonIE_Sodium_Crypto::box_open($ciphertext, $nonce, $keypair);
* Extract the public key from a crypto_box keypair.
* @param string $keypair Keypair containing secret and public key
* @return string Your crypto_box public key
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_box_publickey($keypair)
ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1);
if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) {
throw new SodiumException('Argument 1 must be CRYPTO_BOX_KEYPAIRBYTES long.');
if (self::useNewSodiumAPI()) {
return (string) sodium_crypto_box_publickey($keypair);
if (self::use_fallback('crypto_box_publickey')) {
return (string) call_user_func('\\Sodium\\crypto_box_publickey', $keypair);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::box_publickey($keypair);
return ParagonIE_Sodium_Crypto::box_publickey($keypair);
* Calculate the X25519 public key from a given X25519 secret key.
* @param string $secretKey Any X25519 secret key
* @return string The corresponding X25519 public key
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_box_publickey_from_secretkey($secretKey)
ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1);
if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_BOX_SECRETKEYBYTES) {
throw new SodiumException('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.');
if (self::useNewSodiumAPI()) {
return (string) sodium_crypto_box_publickey_from_secretkey($secretKey);
if (self::use_fallback('crypto_box_publickey_from_secretkey')) {
return (string) call_user_func('\\Sodium\\crypto_box_publickey_from_secretkey', $secretKey);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::box_publickey_from_secretkey($secretKey);
return ParagonIE_Sodium_Crypto::box_publickey_from_secretkey($secretKey);
* Extract the secret key from a crypto_box keypair.
* @return string Your crypto_box secret key
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_box_secretkey($keypair)
ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1);
if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) {
throw new SodiumException('Argument 1 must be CRYPTO_BOX_KEYPAIRBYTES long.');
if (self::useNewSodiumAPI()) {
return (string) sodium_crypto_box_secretkey($keypair);
if (self::use_fallback('crypto_box_secretkey')) {
return (string) call_user_func('\\Sodium\\crypto_box_secretkey', $keypair);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::box_secretkey($keypair);
return ParagonIE_Sodium_Crypto::box_secretkey($keypair);
* Generate an X25519 keypair from a seed.
* @throws SodiumException
* @psalm-suppress MixedArgument
* @psalm-suppress UndefinedFunction
public static function crypto_box_seed_keypair($seed)
ParagonIE_Sodium_Core_Util::declareScalarType($seed, 'string', 1);
if (self::useNewSodiumAPI()) {
return (string) sodium_crypto_box_seed_keypair($seed);
if (self::use_fallback('crypto_box_seed_keypair')) {
return (string) call_user_func('\\Sodium\\crypto_box_seed_keypair', $seed);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::box_seed_keypair($seed);
return ParagonIE_Sodium_Crypto::box_seed_keypair($seed);
* Calculates a BLAKE2b hash, with an optional key.
* @param string $message The message to be hashed
* @param string|null $key If specified, must be a string between 16
* @param int $length Output length in bytes; must be between 16
* @return string Raw binary
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_generichash($message, $key = '', $length = self::CRYPTO_GENERICHASH_BYTES)
ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 2);
ParagonIE_Sodium_Core_Util::declareScalarType($length, 'int', 3);
if (ParagonIE_Sodium_Core_Util::strlen($key) < self::CRYPTO_GENERICHASH_KEYBYTES_MIN) {
throw new SodiumException('Unsupported key size. Must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.');
if (ParagonIE_Sodium_Core_Util::strlen($key) > self::CRYPTO_GENERICHASH_KEYBYTES_MAX) {
throw new SodiumException('Unsupported key size. Must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.');
if (self::useNewSodiumAPI()) {
return (string) sodium_crypto_generichash($message, $key, $length);
if (self::use_fallback('crypto_generichash')) {
return (string) call_user_func('\\Sodium\\crypto_generichash', $message, $key, $length);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::generichash($message, $key, $length);
return ParagonIE_Sodium_Crypto::generichash($message, $key, $length);
* Get the final BLAKE2b hash output for a given context.
* @param string $ctx BLAKE2 hashing context. Generated by crypto_generichash_init().
* @param int $length Hash output size.
* @return string Final BLAKE2b hash.
* @throws SodiumException
* @psalm-suppress MixedArgument
* @psalm-suppress ReferenceConstraintViolation
* @psalm-suppress ConflictingReferenceConstraint
public static function crypto_generichash_final(&$ctx, $length = self::CRYPTO_GENERICHASH_BYTES)
ParagonIE_Sodium_Core_Util::declareScalarType($ctx, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($length, 'int', 2);
if (self::useNewSodiumAPI()) {
return sodium_crypto_generichash_final($ctx, $length);
if (self::use_fallback('crypto_generichash_final')) {
$func = '\\Sodium\\crypto_generichash_final';
return (string) $func($ctx, $length);
} catch (SodiumException $ex) {
if (PHP_INT_SIZE === 4) {
$result = ParagonIE_Sodium_Crypto32::generichash_final($ctx, $length);
$result = ParagonIE_Sodium_Crypto::generichash_final($ctx, $length);
} catch (SodiumException $ex) {
* Initialize a BLAKE2b hashing context, for use in a streaming interface.
* @param string|null $key If specified must be a string between 16 and 64 bytes
* @param int $length The size of the desired hash output
* @return string A BLAKE2 hashing context, encoded as a string
* (To be 100% compatible with ext/libsodium)
* @throws SodiumException