: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
public static function crypto_secretstream_xchacha20poly1305_keygen()
return random_bytes(self::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES);
* @throws SodiumException
public static function crypto_secretstream_xchacha20poly1305_rekey(&$state)
if (PHP_INT_SIZE === 4) {
ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_rekey($state);
ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_rekey($state);
* Calculates a SipHash-2-4 hash of a message for a given key.
* @param string $message Input message
* @param string $key SipHash-2-4 key
* @throws SodiumException
* @psalm-suppress MixedArgument
* @psalm-suppress MixedInferredReturnType
* @psalm-suppress MixedReturnStatement
public static function crypto_shorthash($message, $key)
ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 2);
if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SHORTHASH_KEYBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_SHORTHASH_KEYBYTES long.');
if (self::useNewSodiumAPI()) {
return sodium_crypto_shorthash($message, $key);
if (self::use_fallback('crypto_shorthash')) {
return (string) call_user_func('\\Sodium\\crypto_shorthash', $message, $key);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Core32_SipHash::sipHash24($message, $key);
return ParagonIE_Sodium_Core_SipHash::sipHash24($message, $key);
* Return a secure random key for use with crypto_shorthash
public static function crypto_shorthash_keygen()
return random_bytes(self::CRYPTO_SHORTHASH_KEYBYTES);
* Returns a signed message. You probably want crypto_sign_detached()
* instead, which only returns the signature.
* Algorithm: Ed25519 (EdDSA over Curve25519)
* @param string $message Message to be signed.
* @param string $secretKey Secret signing key.
* @return string Signed message (signature is prefixed).
* @throws SodiumException
* @psalm-suppress MixedArgument
* @psalm-suppress MixedInferredReturnType
* @psalm-suppress MixedReturnStatement
public static function crypto_sign($message, $secretKey)
ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 2);
if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_SIGN_SECRETKEYBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_SIGN_SECRETKEYBYTES long.');
if (self::useNewSodiumAPI()) {
return sodium_crypto_sign($message, $secretKey);
if (self::use_fallback('crypto_sign')) {
return (string) call_user_func('\\Sodium\\crypto_sign', $message, $secretKey);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::sign($message, $secretKey);
return ParagonIE_Sodium_Crypto::sign($message, $secretKey);
* Validates a signed message then returns the message.
* @param string $signedMessage A signed message
* @param string $publicKey A public key
* @return string The original message (if the signature is
* valid for this public key)
* @throws SodiumException
* @psalm-suppress MixedArgument
* @psalm-suppress MixedInferredReturnType
* @psalm-suppress MixedReturnStatement
public static function crypto_sign_open($signedMessage, $publicKey)
ParagonIE_Sodium_Core_Util::declareScalarType($signedMessage, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 2);
if (ParagonIE_Sodium_Core_Util::strlen($signedMessage) < self::CRYPTO_SIGN_BYTES) {
throw new SodiumException('Argument 1 must be at least CRYPTO_SIGN_BYTES long.');
if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_SIGN_PUBLICKEYBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_SIGN_PUBLICKEYBYTES long.');
if (self::useNewSodiumAPI()) {
* @psalm-suppress InvalidReturnStatement
* @psalm-suppress FalsableReturnStatement
return sodium_crypto_sign_open($signedMessage, $publicKey);
if (self::use_fallback('crypto_sign_open')) {
return call_user_func('\\Sodium\\crypto_sign_open', $signedMessage, $publicKey);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::sign_open($signedMessage, $publicKey);
return ParagonIE_Sodium_Crypto::sign_open($signedMessage, $publicKey);
* Generate a new random Ed25519 keypair.
* @throws SodiumException
public static function crypto_sign_keypair()
if (self::useNewSodiumAPI()) {
return sodium_crypto_sign_keypair();
if (self::use_fallback('crypto_sign_keypair')) {
return (string) call_user_func('\\Sodium\\crypto_sign_keypair');
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Core32_Ed25519::keypair();
return ParagonIE_Sodium_Core_Ed25519::keypair();
* @throws SodiumException
public static function crypto_sign_keypair_from_secretkey_and_publickey($sk, $pk)
ParagonIE_Sodium_Core_Util::declareScalarType($sk, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($pk, 'string', 1);
if (ParagonIE_Sodium_Core_Util::strlen($sk) !== self::CRYPTO_SIGN_SECRETKEYBYTES) {
throw new SodiumException('secretkey should be SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes');
if (ParagonIE_Sodium_Core_Util::strlen($pk) !== self::CRYPTO_SIGN_PUBLICKEYBYTES) {
throw new SodiumException('publickey should be SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES bytes');
if (self::useNewSodiumAPI()) {
return sodium_crypto_sign_keypair_from_secretkey_and_publickey($sk, $pk);
* Generate an Ed25519 keypair from a seed.
* @param string $seed Input seed
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_sign_seed_keypair($seed)
ParagonIE_Sodium_Core_Util::declareScalarType($seed, 'string', 1);
if (self::useNewSodiumAPI()) {
return sodium_crypto_sign_seed_keypair($seed);
if (self::use_fallback('crypto_sign_keypair')) {
return (string) call_user_func('\\Sodium\\crypto_sign_seed_keypair', $seed);
if (PHP_INT_SIZE === 4) {
ParagonIE_Sodium_Core32_Ed25519::seed_keypair($publicKey, $secretKey, $seed);
ParagonIE_Sodium_Core_Ed25519::seed_keypair($publicKey, $secretKey, $seed);
return $secretKey . $publicKey;
* Extract an Ed25519 public key from an Ed25519 keypair.
* @param string $keypair Keypair
* @return string Public key
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_sign_publickey($keypair)
ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1);
if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_SIGN_KEYPAIRBYTES) {
throw new SodiumException('Argument 1 must be CRYPTO_SIGN_KEYPAIRBYTES long.');
if (self::useNewSodiumAPI()) {
return sodium_crypto_sign_publickey($keypair);
if (self::use_fallback('crypto_sign_publickey')) {
return (string) call_user_func('\\Sodium\\crypto_sign_publickey', $keypair);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Core32_Ed25519::publickey($keypair);
return ParagonIE_Sodium_Core_Ed25519::publickey($keypair);
* Calculate an Ed25519 public key from an Ed25519 secret key.
* @param string $secretKey Your Ed25519 secret key
* @return string The corresponding Ed25519 public key
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_sign_publickey_from_secretkey($secretKey)
ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1);
if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_SIGN_SECRETKEYBYTES) {
throw new SodiumException('Argument 1 must be CRYPTO_SIGN_SECRETKEYBYTES long.');
if (self::useNewSodiumAPI()) {
return sodium_crypto_sign_publickey_from_secretkey($secretKey);
if (self::use_fallback('crypto_sign_publickey_from_secretkey')) {
return (string) call_user_func('\\Sodium\\crypto_sign_publickey_from_secretkey', $secretKey);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Core32_Ed25519::publickey_from_secretkey($secretKey);
return ParagonIE_Sodium_Core_Ed25519::publickey_from_secretkey($secretKey);
* Extract an Ed25519 secret key from an Ed25519 keypair.
* @param string $keypair Keypair
* @return string Secret key
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_sign_secretkey($keypair)
ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1);
if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_SIGN_KEYPAIRBYTES) {
throw new SodiumException('Argument 1 must be CRYPTO_SIGN_KEYPAIRBYTES long.');
if (self::useNewSodiumAPI()) {
return sodium_crypto_sign_secretkey($keypair);
if (self::use_fallback('crypto_sign_secretkey')) {
return (string) call_user_func('\\Sodium\\crypto_sign_secretkey', $keypair);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Core32_Ed25519::secretkey($keypair);
return ParagonIE_Sodium_Core_Ed25519::secretkey($keypair);
* Calculate the Ed25519 signature of a message and return ONLY the signature.
* Algorithm: Ed25519 (EdDSA over Curve25519)
* @param string $message Message to be signed
* @param string $secretKey Secret signing key
* @return string Digital signature
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_sign_detached($message, $secretKey)
ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 2);
if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_SIGN_SECRETKEYBYTES) {
throw new SodiumException('Argument 2 must be CRYPTO_SIGN_SECRETKEYBYTES long.');
if (self::useNewSodiumAPI()) {
return sodium_crypto_sign_detached($message, $secretKey);
if (self::use_fallback('crypto_sign_detached')) {
return (string) call_user_func('\\Sodium\\crypto_sign_detached', $message, $secretKey);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::sign_detached($message, $secretKey);
return ParagonIE_Sodium_Crypto::sign_detached($message, $secretKey);
* Verify the Ed25519 signature of a message.
* @param string $signature Digital sginature
* @param string $message Message to be verified
* @param string $publicKey Public key
* @return bool TRUE if this signature is good for this public key;
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_sign_verify_detached($signature, $message, $publicKey)
ParagonIE_Sodium_Core_Util::declareScalarType($signature, 'string', 1);
ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 2);
ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 3);
if (ParagonIE_Sodium_Core_Util::strlen($signature) !== self::CRYPTO_SIGN_BYTES) {
throw new SodiumException('Argument 1 must be CRYPTO_SIGN_BYTES long.');
if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_SIGN_PUBLICKEYBYTES) {
throw new SodiumException('Argument 3 must be CRYPTO_SIGN_PUBLICKEYBYTES long.');
if (self::useNewSodiumAPI()) {
return sodium_crypto_sign_verify_detached($signature, $message, $publicKey);
if (self::use_fallback('crypto_sign_verify_detached')) {
return (bool) call_user_func(
'\\Sodium\\crypto_sign_verify_detached',
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Crypto32::sign_verify_detached($signature, $message, $publicKey);
return ParagonIE_Sodium_Crypto::sign_verify_detached($signature, $message, $publicKey);
* Convert an Ed25519 public key to a Curve25519 public key
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_sign_ed25519_pk_to_curve25519($pk)
ParagonIE_Sodium_Core_Util::declareScalarType($pk, 'string', 1);
if (ParagonIE_Sodium_Core_Util::strlen($pk) < self::CRYPTO_SIGN_PUBLICKEYBYTES) {
throw new SodiumException('Argument 1 must be at least CRYPTO_SIGN_PUBLICKEYBYTES long.');
if (self::useNewSodiumAPI()) {
if (is_callable('crypto_sign_ed25519_pk_to_curve25519')) {
return (string) sodium_crypto_sign_ed25519_pk_to_curve25519($pk);
if (self::use_fallback('crypto_sign_ed25519_pk_to_curve25519')) {
return (string) call_user_func('\\Sodium\\crypto_sign_ed25519_pk_to_curve25519', $pk);
if (PHP_INT_SIZE === 4) {
return ParagonIE_Sodium_Core32_Ed25519::pk_to_curve25519($pk);
return ParagonIE_Sodium_Core_Ed25519::pk_to_curve25519($pk);
* Convert an Ed25519 secret key to a Curve25519 secret key
* @throws SodiumException
* @psalm-suppress MixedArgument
public static function crypto_sign_ed25519_sk_to_curve25519($sk)
ParagonIE_Sodium_Core_Util::declareScalarType($sk, 'string', 1);
if (ParagonIE_Sodium_Core_Util::strlen($sk) < self::CRYPTO_SIGN_SEEDBYTES) {
throw new SodiumException('Argument 1 must be at least CRYPTO_SIGN_SEEDBYTES long.');
if (self::useNewSodiumAPI()) {
if (is_callable('crypto_sign_ed25519_sk_to_curve25519')) {
return sodium_crypto_sign_ed25519_sk_to_curve25519($sk);
if (self::use_fallback('crypto_sign_ed25519_sk_to_curve25519')) {
return (string) call_user_func('\\Sodium\\crypto_sign_ed25519_sk_to_curve25519', $sk);
$h = hash('sha512', ParagonIE_Sodium_Core_Util::substr($sk, 0, 32), true);
$h[0] = ParagonIE_Sodium_Core_Util::intToChr(
ParagonIE_Sodium_Core_Util::chrToInt($h[0]) & 248
$h[31] = ParagonIE_Sodium_Core_Util::intToChr(
(ParagonIE_Sodium_Core_Util::chrToInt($h[31]) & 127) | 64
return ParagonIE_Sodium_Core_Util::substr($h, 0, 32);
* 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 XSalsa20 key
* @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($len, $nonce, $key)
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_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_STREAM_KEYBYTES long.');