Current Path : /storage/v11800/affypharma/public_html/wp-includes/sodium_compat/src/

Linux v11800 5.3.0-1023-aws #25~18.04.1-Ubuntu SMP Fri Jun 5 15:19:18 UTC 2020 aarch64

Upload File :
Current File : /storage/v11800/affypharma/public_html/wp-includes/sodium_compat/src/Crypto32.php
<?php

if (class_exists('ParagonIE_Sodium_Crypto32', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Crypto
 *
 * ATTENTION!
 *
 * If you are using this library, you should be using
 * ParagonIE_Sodium_Compat in your code, not this class.
 */
abstract class ParagonIE_Sodium_Crypto32
{
    const aead_chacha20poly1305_KEYBYTES = 32;
    const aead_chacha20poly1305_NSECBYTES = 0;
    const aead_chacha20poly1305_NPUBBYTES = 8;
    const aead_chacha20poly1305_ABYTES = 16;

    const aead_chacha20poly1305_IETF_KEYBYTES = 32;
    const aead_chacha20poly1305_IETF_NSECBYTES = 0;
    const aead_chacha20poly1305_IETF_NPUBBYTES = 12;
    const aead_chacha20poly1305_IETF_ABYTES = 16;

    const aead_xchacha20poly1305_IETF_KEYBYTES = 32;
    const aead_xchacha20poly1305_IETF_NSECBYTES = 0;
    const aead_xchacha20poly1305_IETF_NPUBBYTES = 24;
    const aead_xchacha20poly1305_IETF_ABYTES = 16;

    const box_curve25519xsalsa20poly1305_SEEDBYTES = 32;
    const box_curve25519xsalsa20poly1305_PUBLICKEYBYTES = 32;
    const box_curve25519xsalsa20poly1305_SECRETKEYBYTES = 32;
    const box_curve25519xsalsa20poly1305_BEFORENMBYTES = 32;
    const box_curve25519xsalsa20poly1305_NONCEBYTES = 24;
    const box_curve25519xsalsa20poly1305_MACBYTES = 16;
    const box_curve25519xsalsa20poly1305_BOXZEROBYTES = 16;
    const box_curve25519xsalsa20poly1305_ZEROBYTES = 32;

    const onetimeauth_poly1305_BYTES = 16;
    const onetimeauth_poly1305_KEYBYTES = 32;

    const secretbox_xsalsa20poly1305_KEYBYTES = 32;
    const secretbox_xsalsa20poly1305_NONCEBYTES = 24;
    const secretbox_xsalsa20poly1305_MACBYTES = 16;
    const secretbox_xsalsa20poly1305_BOXZEROBYTES = 16;
    const secretbox_xsalsa20poly1305_ZEROBYTES = 32;

    const secretbox_xchacha20poly1305_KEYBYTES = 32;
    const secretbox_xchacha20poly1305_NONCEBYTES = 24;
    const secretbox_xchacha20poly1305_MACBYTES = 16;
    const secretbox_xchacha20poly1305_BOXZEROBYTES = 16;
    const secretbox_xchacha20poly1305_ZEROBYTES = 32;

    const stream_salsa20_KEYBYTES = 32;

    /**
     * AEAD Decryption with ChaCha20-Poly1305
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_chacha20poly1305_decrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        /** @var int $len - Length of message (ciphertext + MAC) */
        $len = ParagonIE_Sodium_Core32_Util::strlen($message);

        /** @var int  $clen - Length of ciphertext */
        $clen = $len - self::aead_chacha20poly1305_ABYTES;

        /** @var int $adlen - Length of associated data */
        $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);

        /** @var string $mac - Message authentication code */
        $mac = ParagonIE_Sodium_Core32_Util::substr(
            $message,
            $clen,
            self::aead_chacha20poly1305_ABYTES
        );

        /** @var string $ciphertext - The encrypted message (sans MAC) */
        $ciphertext = ParagonIE_Sodium_Core32_Util::substr($message, 0, $clen);

        /** @var string The first block of the chacha20 keystream, used as a poly1305 key */
        $block0 = ParagonIE_Sodium_Core32_ChaCha20::stream(
            32,
            $nonce,
            $key
        );

        /* Recalculate the Poly1305 authentication tag (MAC): */
        $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
        } catch (SodiumException $ex) {
            $block0 = null;
        }
        $state->update($ad);
        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
        $state->update($ciphertext);
        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($clen));
        $computed_mac = $state->finish();

        /* Compare the given MAC with the recalculated MAC: */
        if (!ParagonIE_Sodium_Core32_Util::verify_16($computed_mac, $mac)) {
            throw new SodiumException('Invalid MAC');
        }

        // Here, we know that the MAC is valid, so we decrypt and return the plaintext
        return ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
            $ciphertext,
            $nonce,
            $key,
            ParagonIE_Sodium_Core32_Util::store64_le(1)
        );
    }

    /**
     * AEAD Encryption with ChaCha20-Poly1305
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_chacha20poly1305_encrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        /** @var int $len - Length of the plaintext message */
        $len = ParagonIE_Sodium_Core32_Util::strlen($message);

        /** @var int $adlen - Length of the associated data */
        $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);

        /** @var string The first block of the chacha20 keystream, used as a poly1305 key */
        $block0 = ParagonIE_Sodium_Core32_ChaCha20::stream(
            32,
            $nonce,
            $key
        );
        $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
        } catch (SodiumException $ex) {
            $block0 = null;
        }

        /** @var string $ciphertext - Raw encrypted data */
        $ciphertext = ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
            $message,
            $nonce,
            $key,
            ParagonIE_Sodium_Core32_Util::store64_le(1)
        );

        $state->update($ad);
        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
        $state->update($ciphertext);
        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($len));
        return $ciphertext . $state->finish();
    }

    /**
     * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_chacha20poly1305_ietf_decrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        /** @var int $adlen - Length of associated data */
        $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);

        /** @var int $len - Length of message (ciphertext + MAC) */
        $len = ParagonIE_Sodium_Core32_Util::strlen($message);

        /** @var int  $clen - Length of ciphertext */
        $clen = $len - self::aead_chacha20poly1305_IETF_ABYTES;

        /** @var string The first block of the chacha20 keystream, used as a poly1305 key */
        $block0 = ParagonIE_Sodium_Core32_ChaCha20::ietfStream(
            32,
            $nonce,
            $key
        );

        /** @var string $mac - Message authentication code */
        $mac = ParagonIE_Sodium_Core32_Util::substr(
            $message,
            $len - self::aead_chacha20poly1305_IETF_ABYTES,
            self::aead_chacha20poly1305_IETF_ABYTES
        );

        /** @var string $ciphertext - The encrypted message (sans MAC) */
        $ciphertext = ParagonIE_Sodium_Core32_Util::substr(
            $message,
            0,
            $len - self::aead_chacha20poly1305_IETF_ABYTES
        );

        /* Recalculate the Poly1305 authentication tag (MAC): */
        $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
        } catch (SodiumException $ex) {
            $block0 = null;
        }
        $state->update($ad);
        $state->update(str_repeat("\x00", ((0x10 - $adlen) & 0xf)));
        $state->update($ciphertext);
        $state->update(str_repeat("\x00", (0x10 - $clen) & 0xf));
        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($clen));
        $computed_mac = $state->finish();

        /* Compare the given MAC with the recalculated MAC: */
        if (!ParagonIE_Sodium_Core32_Util::verify_16($computed_mac, $mac)) {
            throw new SodiumException('Invalid MAC');
        }

        // Here, we know that the MAC is valid, so we decrypt and return the plaintext
        return ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            $ciphertext,
            $nonce,
            $key,
            ParagonIE_Sodium_Core32_Util::store64_le(1)
        );
    }

    /**
     * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_chacha20poly1305_ietf_encrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        /** @var int $len - Length of the plaintext message */
        $len = ParagonIE_Sodium_Core32_Util::strlen($message);

        /** @var int $adlen - Length of the associated data */
        $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);

        /** @var string The first block of the chacha20 keystream, used as a poly1305 key */
        $block0 = ParagonIE_Sodium_Core32_ChaCha20::ietfStream(
            32,
            $nonce,
            $key
        );
        $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
        } catch (SodiumException $ex) {
            $block0 = null;
        }

        /** @var string $ciphertext - Raw encrypted data */
        $ciphertext = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            $message,
            $nonce,
            $key,
            ParagonIE_Sodium_Core32_Util::store64_le(1)
        );

        $state->update($ad);
        $state->update(str_repeat("\x00", ((0x10 - $adlen) & 0xf)));
        $state->update($ciphertext);
        $state->update(str_repeat("\x00", ((0x10 - $len) & 0xf)));
        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($len));
        return $ciphertext . $state->finish();
    }

    /**
     * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_xchacha20poly1305_ietf_decrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
            ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16),
            $key
        );
        $nonceLast = "\x00\x00\x00\x00" .
            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);

        return self::aead_chacha20poly1305_ietf_decrypt($message, $ad, $nonceLast, $subkey);
    }

    /**
     * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_xchacha20poly1305_ietf_encrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
            ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16),
            $key
        );
        $nonceLast = "\x00\x00\x00\x00" .
            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);

        return self::aead_chacha20poly1305_ietf_encrypt($message, $ad, $nonceLast, $subkey);
    }

    /**
     * HMAC-SHA-512-256 (a.k.a. the leftmost 256 bits of HMAC-SHA-512)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $key
     * @return string
     * @throws TypeError
     */
    public static function auth($message, $key)
    {
        return ParagonIE_Sodium_Core32_Util::substr(
            hash_hmac('sha512', $message, $key, true),
            0,
            32
        );
    }

    /**
     * HMAC-SHA-512-256 validation. Constant-time via hash_equals().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $mac
     * @param string $message
     * @param string $key
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function auth_verify($mac, $message, $key)
    {
        return ParagonIE_Sodium_Core32_Util::hashEquals(
            $mac,
            self::auth($message, $key)
        );
    }

    /**
     * X25519 key exchange followed by XSalsa20Poly1305 symmetric encryption
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $plaintext
     * @param string $nonce
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box($plaintext, $nonce, $keypair)
    {
        return self::secretbox(
            $plaintext,
            $nonce,
            self::box_beforenm(
                self::box_secretkey($keypair),
                self::box_publickey($keypair)
            )
        );
    }

    /**
     * X25519-XSalsa20-Poly1305 with one ephemeral X25519 keypair.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $publicKey
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seal($message, $publicKey)
    {
        /** @var string $ephemeralKeypair */
        $ephemeralKeypair = self::box_keypair();

        /** @var string $ephemeralSK */
        $ephemeralSK = self::box_secretkey($ephemeralKeypair);

        /** @var string $ephemeralPK */
        $ephemeralPK = self::box_publickey($ephemeralKeypair);

        /** @var string $nonce */
        $nonce = self::generichash(
            $ephemeralPK . $publicKey,
            '',
            24
        );

        /** @var string $keypair - The combined keypair used in crypto_box() */
        $keypair = self::box_keypair_from_secretkey_and_publickey($ephemeralSK, $publicKey);

        /** @var string $ciphertext Ciphertext + MAC from crypto_box */
        $ciphertext = self::box($message, $nonce, $keypair);
        try {
            ParagonIE_Sodium_Compat::memzero($ephemeralKeypair);
            ParagonIE_Sodium_Compat::memzero($ephemeralSK);
            ParagonIE_Sodium_Compat::memzero($nonce);
        } catch (SodiumException $ex) {
            $ephemeralKeypair = null;
            $ephemeralSK = null;
            $nonce = null;
        }
        return $ephemeralPK . $ciphertext;
    }

    /**
     * Opens a message encrypted via box_seal().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seal_open($message, $keypair)
    {
        /** @var string $ephemeralPK */
        $ephemeralPK = ParagonIE_Sodium_Core32_Util::substr($message, 0, 32);

        /** @var string $ciphertext (ciphertext + MAC) */
        $ciphertext = ParagonIE_Sodium_Core32_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,
            '',
            24
        );

        /** @var string $keypair */
        $keypair = self::box_keypair_from_secretkey_and_publickey($secretKey, $ephemeralPK);

        /** @var string $m */
        $m = self::box_open($ciphertext, $nonce, $keypair);
        try {
            ParagonIE_Sodium_Compat::memzero($secretKey);
            ParagonIE_Sodium_Compat::memzero($ephemeralPK);
            ParagonIE_Sodium_Compat::memzero($nonce);
        } catch (SodiumException $ex) {
            $secretKey = null;
            $ephemeralPK = null;
            $nonce = null;
        }
        return $m;
    }

    /**
     * Used by crypto_box() to get the crypto_secretbox() key.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $sk
     * @param string $pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_beforenm($sk, $pk)
    {
        return ParagonIE_Sodium_Core32_HSalsa20::hsalsa20(
            str_repeat("\x00", 16),
            self::scalarmult($sk, $pk)
        );
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @return string
     * @throws Exception
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_keypair()
    {
        $sKey = random_bytes(32);
        $pKey = self::scalarmult_base($sKey);
        return $sKey . $pKey;
    }

    /**
     * @param string $seed
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seed_keypair($seed)
    {
        $sKey = ParagonIE_Sodium_Core32_Util::substr(
            hash('sha512', $seed, true),
            0,
            32
        );
        $pKey = self::scalarmult_base($sKey);
        return $sKey . $pKey;
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $sKey
     * @param string $pKey
     * @return string
     * @throws TypeError
     */
    public static function box_keypair_from_secretkey_and_publickey($sKey, $pKey)
    {
        return ParagonIE_Sodium_Core32_Util::substr($sKey, 0, 32) .
            ParagonIE_Sodium_Core32_Util::substr($pKey, 0, 32);
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $keypair
     * @return string
     * @throws RangeException
     * @throws TypeError
     */
    public static function box_secretkey($keypair)
    {
        if (ParagonIE_Sodium_Core32_Util::strlen($keypair) !== 64) {
            throw new RangeException(
                'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.'
            );
        }
        return ParagonIE_Sodium_Core32_Util::substr($keypair, 0, 32);
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $keypair
     * @return string
     * @throws RangeException
     * @throws TypeError
     */
    public static function box_publickey($keypair)
    {
        if (ParagonIE_Sodium_Core32_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_Core32_Util::substr($keypair, 32, 32);
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $sKey
     * @return string
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_publickey_from_secretkey($sKey)
    {
        if (ParagonIE_Sodium_Core32_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
     * @param string $nonce
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_open($ciphertext, $nonce, $keypair)
    {
        return self::secretbox_open(
            $ciphertext,
            $nonce,
            self::box_beforenm(
                self::box_secretkey($keypair),
                self::box_publickey($keypair)
            )
        );
    }

    /**
     * Calculate a BLAKE2b hash.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string|null $key
     * @param int $outlen
     * @return string
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash($message, $key = '', $outlen = 32)
    {
        // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized
        ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();

        $k = null;
        if (!empty($key)) {
            /** @var SplFixedArray $k */
            $k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key);
            if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) {
                throw new RangeException('Invalid key size');
            }
        }

        /** @var SplFixedArray $in */
        $in = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($message);

        /** @var SplFixedArray $ctx */
        $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outlen);
        ParagonIE_Sodium_Core32_BLAKE2b::update($ctx, $in, $in->count());

        /** @var SplFixedArray $out */
        $out = new SplFixedArray($outlen);
        $out = ParagonIE_Sodium_Core32_BLAKE2b::finish($ctx, $out);

        /** @var array<int, int> */
        $outArray = $out->toArray();
        return ParagonIE_Sodium_Core32_Util::intArrayToString($outArray);
    }

    /**
     * Finalize a BLAKE2b hashing context, returning the hash.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ctx
     * @param int $outlen
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash_final($ctx, $outlen = 32)
    {
        if (!is_string($ctx)) {
            throw new TypeError('Context must be a string');
        }
        $out = new SplFixedArray($outlen);

        /** @var SplFixedArray $context */
        $context = ParagonIE_Sodium_Core32_BLAKE2b::stringToContext($ctx);

        /** @var SplFixedArray $out */
        $out = ParagonIE_Sodium_Core32_BLAKE2b::finish($context, $out);

        /** @var array<int, int> */
        $outArray = $out->toArray();
        return ParagonIE_Sodium_Core32_Util::intArrayToString($outArray);
    }

    /**
     * Initialize a hashing context for BLAKE2b.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $key
     * @param int $outputLength
     * @return string
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash_init($key = '', $outputLength = 32)
    {
        // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized
        ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();

        $k = null;
        if (!empty($key)) {
            $k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key);
            if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) {
                throw new RangeException('Invalid key size');
            }
        }

        /** @var SplFixedArray $ctx */
        $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outputLength);

        return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($ctx);
    }

    /**
     * Initialize a hashing context for BLAKE2b.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $key
     * @param int $outputLength
     * @param string $salt
     * @param string $personal
     * @return string
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash_init_salt_personal(
        $key = '',
        $outputLength = 32,
        $salt = '',
        $personal = ''
    ) {
        // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized
        ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();

        $k = null;
        if (!empty($key)) {
            $k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key);
            if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) {
                throw new RangeException('Invalid key size');
            }
        }
        if (!empty($salt)) {
            $s = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($salt);
        } else {
            $s = null;
        }
        if (!empty($salt)) {
            $p = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($personal);
        } else {
            $p = null;
        }

        /** @var SplFixedArray $ctx */
        $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outputLength, $s, $p);

        return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($ctx);
    }

    /**
     * Update a hashing context for BLAKE2b with $message
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ctx
     * @param string $message
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash_update($ctx, $message)
    {
        // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized
        ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();

        /** @var SplFixedArray $context */
        $context = ParagonIE_Sodium_Core32_BLAKE2b::stringToContext($ctx);

        /** @var SplFixedArray $in */
        $in = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($message);

        ParagonIE_Sodium_Core32_BLAKE2b::update($context, $in, $in->count());

        return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($context);
    }

    /**
     * Libsodium's crypto_kx().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $my_sk
     * @param string $their_pk
     * @param string $client_pk
     * @param string $server_pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function keyExchange($my_sk, $their_pk, $client_pk, $server_pk)
    {
        return self::generichash(
            self::scalarmult($my_sk, $their_pk) .
            $client_pk .
            $server_pk
        );
    }

    /**
     * ECDH over Curve25519
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $sKey
     * @param string $pKey
     * @return string
     *
     * @throws SodiumException
     * @throws TypeError
     */
    public static function scalarmult($sKey, $pKey)
    {
        $q = ParagonIE_Sodium_Core32_X25519::crypto_scalarmult_curve25519_ref10($sKey, $pKey);
        self::scalarmult_throw_if_zero($q);
        return $q;
    }

    /**
     * ECDH over Curve25519, using the basepoint.
     * Used to get a secret key from a public key.
     *
     * @param string $secret
     * @return string
     *
     * @throws SodiumException
     * @throws TypeError
     */
    public static function scalarmult_base($secret)
    {
        $q = ParagonIE_Sodium_Core32_X25519::crypto_scalarmult_curve25519_ref10_base($secret);
        self::scalarmult_throw_if_zero($q);
        return $q;
    }

    /**
     * This throws an Error if a zero public key was passed to the function.
     *
     * @param string $q
     * @return void
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function scalarmult_throw_if_zero($q)
    {
        $d = 0;
        for ($i = 0; $i < self::box_curve25519xsalsa20poly1305_SECRETKEYBYTES; ++$i) {
            $d |= ParagonIE_Sodium_Core32_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
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox($plaintext, $nonce, $key)
    {
        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key);

        /** @var string $block0 */
        $block0 = str_repeat("\x00", 32);

        /** @var int $mlen - Length of the plaintext message */
        $mlen = ParagonIE_Sodium_Core32_Util::strlen($plaintext);
        $mlen0 = $mlen;
        if ($mlen0 > 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES) {
            $mlen0 = 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES;
        }
        $block0 .= ParagonIE_Sodium_Core32_Util::substr($plaintext, 0, $mlen0);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20_xor(
            $block0,
            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
            $subkey
        );

        /** @var string $c */
        $c = ParagonIE_Sodium_Core32_Util::substr(
            $block0,
            self::secretbox_xsalsa20poly1305_ZEROBYTES
        );
        if ($mlen > $mlen0) {
            $c .= ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic(
                ParagonIE_Sodium_Core32_Util::substr(
                    $plaintext,
                    self::secretbox_xsalsa20poly1305_ZEROBYTES
                ),
                ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
                1,
                $subkey
            );
        }
        $state = new ParagonIE_Sodium_Core32_Poly1305_State(
            ParagonIE_Sodium_Core32_Util::substr(
                $block0,
                0,
                self::onetimeauth_poly1305_KEYBYTES
            )
        );
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
            ParagonIE_Sodium_Compat::memzero($subkey);
        } catch (SodiumException $ex) {
            $block0 = null;
            $subkey = null;
        }

        $state->update($c);

        /** @var string $c - MAC || ciphertext */
        $c = $state->finish() . $c;
        unset($state);

        return $c;
    }

    /**
     * Decrypt a ciphertext generated via secretbox().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ciphertext
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox_open($ciphertext, $nonce, $key)
    {
        /** @var string $mac */
        $mac = ParagonIE_Sodium_Core32_Util::substr(
            $ciphertext,
            0,
            self::secretbox_xsalsa20poly1305_MACBYTES
        );

        /** @var string $c */
        $c = ParagonIE_Sodium_Core32_Util::substr(
            $ciphertext,
            self::secretbox_xsalsa20poly1305_MACBYTES
        );

        /** @var int $clen */
        $clen = ParagonIE_Sodium_Core32_Util::strlen($c);

        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20(
            64,
            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
            $subkey
        );
        $verified = ParagonIE_Sodium_Core32_Poly1305::onetimeauth_verify(
            $mac,
            $c,
            ParagonIE_Sodium_Core32_Util::substr($block0, 0, 32)
        );
        if (!$verified) {
            try {
                ParagonIE_Sodium_Compat::memzero($subkey);
            } catch (SodiumException $ex) {
                $subkey = null;
            }
            throw new SodiumException('Invalid MAC');
        }

        /** @var string $m - Decrypted message */
        $m = ParagonIE_Sodium_Core32_Util::xorStrings(
            ParagonIE_Sodium_Core32_Util::substr($block0, self::secretbox_xsalsa20poly1305_ZEROBYTES),
            ParagonIE_Sodium_Core32_Util::substr($c, 0, self::secretbox_xsalsa20poly1305_ZEROBYTES)
        );
        if ($clen > self::secretbox_xsalsa20poly1305_ZEROBYTES) {
            // We had more than 1 block, so let's continue to decrypt the rest.
            $m .= ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic(
                ParagonIE_Sodium_Core32_Util::substr(
                    $c,
                    self::secretbox_xsalsa20poly1305_ZEROBYTES
                ),
                ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
                1,
                (string) $subkey
            );
        }
        return $m;
    }

    /**
     * XChaCha20-Poly1305 authenticated symmetric-key encryption.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $plaintext
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox_xchacha20poly1305($plaintext, $nonce, $key)
    {
        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
            ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16),
            $key
        );
        $nonceLast = ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);

        /** @var string $block0 */
        $block0 = str_repeat("\x00", 32);

        /** @var int $mlen - Length of the plaintext message */
        $mlen = ParagonIE_Sodium_Core32_Util::strlen($plaintext);
        $mlen0 = $mlen;
        if ($mlen0 > 64 - self::secretbox_xchacha20poly1305_ZEROBYTES) {
            $mlen0 = 64 - self::secretbox_xchacha20poly1305_ZEROBYTES;
        }
        $block0 .= ParagonIE_Sodium_Core32_Util::substr($plaintext, 0, $mlen0);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
            $block0,
            $nonceLast,
            $subkey
        );

        /** @var string $c */
        $c = ParagonIE_Sodium_Core32_Util::substr(
            $block0,
            self::secretbox_xchacha20poly1305_ZEROBYTES
        );
        if ($mlen > $mlen0) {
            $c .= ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
                ParagonIE_Sodium_Core32_Util::substr(
                    $plaintext,
                    self::secretbox_xchacha20poly1305_ZEROBYTES
                ),
                $nonceLast,
                $subkey,
                ParagonIE_Sodium_Core32_Util::store64_le(1)
            );
        }
        $state = new ParagonIE_Sodium_Core32_Poly1305_State(
            ParagonIE_Sodium_Core32_Util::substr(
                $block0,
                0,
                self::onetimeauth_poly1305_KEYBYTES
            )
        );
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
            ParagonIE_Sodium_Compat::memzero($subkey);
        } catch (SodiumException $ex) {
            $block0 = null;
            $subkey = null;
        }

        $state->update($c);

        /** @var string $c - MAC || ciphertext */
        $c = $state->finish() . $c;
        unset($state);

        return $c;
    }

    /**
     * Decrypt a ciphertext generated via secretbox_xchacha20poly1305().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ciphertext
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key)
    {
        /** @var string $mac */
        $mac = ParagonIE_Sodium_Core32_Util::substr(
            $ciphertext,
            0,
            self::secretbox_xchacha20poly1305_MACBYTES
        );

        /** @var string $c */
        $c = ParagonIE_Sodium_Core32_Util::substr(
            $ciphertext,
            self::secretbox_xchacha20poly1305_MACBYTES
        );

        /** @var int $clen */
        $clen = ParagonIE_Sodium_Core32_Util::strlen($c);

        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hchacha20($nonce, $key);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core32_ChaCha20::stream(
            64,
            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
            $subkey
        );
        $verified = ParagonIE_Sodium_Core32_Poly1305::onetimeauth_verify(
            $mac,
            $c,
            ParagonIE_Sodium_Core32_Util::substr($block0, 0, 32)
        );

        if (!$verified) {
            try {
                ParagonIE_Sodium_Compat::memzero($subkey);
            } catch (SodiumException $ex) {
                $subkey = null;
            }
            throw new SodiumException('Invalid MAC');
        }

        /** @var string $m - Decrypted message */
        $m = ParagonIE_Sodium_Core32_Util::xorStrings(
            ParagonIE_Sodium_Core32_Util::substr($block0, self::secretbox_xchacha20poly1305_ZEROBYTES),
            ParagonIE_Sodium_Core32_Util::substr($c, 0, self::secretbox_xchacha20poly1305_ZEROBYTES)
        );

        if ($clen > self::secretbox_xchacha20poly1305_ZEROBYTES) {
            // We had more than 1 block, so let's continue to decrypt the rest.
            $m .= ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
                ParagonIE_Sodium_Core32_Util::substr(
                    $c,
                    self::secretbox_xchacha20poly1305_ZEROBYTES
                ),
                ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
                (string) $subkey,
                ParagonIE_Sodium_Core32_Util::store64_le(1)
            );
        }
        return $m;
    }

    /**
     * @param string $key
     * @return array<int, string> Returns a state and a header.
     * @throws Exception
     * @throws SodiumException
     */
    public static function secretstream_xchacha20poly1305_init_push($key)
    {
        # randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES);
        $out = random_bytes(24);

        # crypto_core_hchacha20(state->k, out, k, NULL);
        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20($out, $key);
        $state = new ParagonIE_Sodium_Core32_SecretStream_State(
            $subkey,
            ParagonIE_Sodium_Core32_Util::substr($out, 16, 8) . str_repeat("\0", 4)
        );

        # _crypto_secretstream_xchacha20poly1305_counter_reset(state);
        $state->counterReset();

        # memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES,
        #        crypto_secretstream_xchacha20poly1305_INONCEBYTES);
        # memset(state->_pad, 0, sizeof state->_pad);
        return array(
            $state->toString(),
            $out
        );
    }

    /**
     * @param string $key
     * @param string $header
     * @return string Returns a state.
     * @throws Exception
     */
    public static function secretstream_xchacha20poly1305_init_pull($key, $header)
    {
        # crypto_core_hchacha20(state->k, in, k, NULL);
        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
            ParagonIE_Sodium_Core32_Util::substr($header, 0, 16),
            $key
        );
        $state = new ParagonIE_Sodium_Core32_SecretStream_State(
            $subkey,
            ParagonIE_Sodium_Core32_Util::substr($header, 16)
        );
        $state->counterReset();
        # memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES,
        #     crypto_secretstream_xchacha20poly1305_INONCEBYTES);
        # memset(state->_pad, 0, sizeof state->_pad);
        # return 0;
        return $state->toString();
    }

    /**
     * @param string $state
     * @param string $msg
     * @param string $aad
     * @param int $tag
     * @return string
     * @throws SodiumException
     */
    public static function secretstream_xchacha20poly1305_push(&$state, $msg, $aad = '', $tag = 0)
    {
        $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state);
        # crypto_onetimeauth_poly1305_state poly1305_state;
        # unsigned char                     block[64U];
        # unsigned char                     slen[8U];
        # unsigned char                    *c;
        # unsigned char                    *mac;

        $msglen = ParagonIE_Sodium_Core32_Util::strlen($msg);
        $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad);

        if ((($msglen + 63) >> 6) > 0xfffffffe) {
            throw new SodiumException(
                'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes'
            );
        }

        # if (outlen_p != NULL) {
        #     *outlen_p = 0U;
        # }
        # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
        #     sodium_misuse();
        # }

        # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
        # crypto_onetimeauth_poly1305_init(&poly1305_state, block);
        # sodium_memzero(block, sizeof block);
        $auth = new ParagonIE_Sodium_Core32_Poly1305_State(
            ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey())
        );

        # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
        $auth->update($aad);

        # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
        #     (0x10 - adlen) & 0xf);
        $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf)));

        # memset(block, 0, sizeof block);
        # block[0] = tag;
        # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
        #                                    state->nonce, 1U, state->k);
        $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            ParagonIE_Sodium_Core32_Util::intToChr($tag) . str_repeat("\0", 63),
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core32_Util::store64_le(1)
        );

        # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
        $auth->update($block);

        # out[0] = block[0];
        $out = $block[0];
        # c = out + (sizeof tag);
        # crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k);
        $cipher = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            $msg,
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core32_Util::store64_le(2)
        );

        # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
        $auth->update($cipher);

        $out .= $cipher;
        unset($cipher);

        # crypto_onetimeauth_poly1305_update
        # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
        $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf)));

        # STORE64_LE(slen, (uint64_t) adlen);
        $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen);

        # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
        $auth->update($slen);

        # STORE64_LE(slen, (sizeof block) + mlen);
        $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen);

        # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
        $auth->update($slen);

        # mac = c + mlen;
        # crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
        $mac = $auth->finish();
        $out .= $mac;

        # sodium_memzero(&poly1305_state, sizeof poly1305_state);
        unset($auth);


        # XOR_BUF(STATE_INONCE(state), mac,
        #     crypto_secretstream_xchacha20poly1305_INONCEBYTES);
        $st->xorNonce($mac);

        # sodium_increment(STATE_COUNTER(state),
        #     crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
        $st->incrementCounter();
        // Overwrite by reference:
        $state = $st->toString();

        /** @var bool $rekey */
        $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0;
        # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
        #     sodium_is_zero(STATE_COUNTER(state),
        #         crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
        #     crypto_secretstream_xchacha20poly1305_rekey(state);
        # }
        if ($rekey || $st->needsRekey()) {
            // DO REKEY
            self::secretstream_xchacha20poly1305_rekey($state);
        }
        # if (outlen_p != NULL) {
        #     *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen;
        # }
        return $out;
    }

    /**
     * @param string $state
     * @param string $cipher
     * @param string $aad
     * @return bool|array{0: string, 1: int}
     * @throws SodiumException
     */
    public static function secretstream_xchacha20poly1305_pull(&$state, $cipher, $aad = '')
    {
        $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state);

        $cipherlen = ParagonIE_Sodium_Core32_Util::strlen($cipher);
        #     mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES;
        $msglen = $cipherlen - ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES;
        $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad);

        #     if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
        #         sodium_misuse();
        #     }
        if ((($msglen + 63) >> 6) > 0xfffffffe) {
            throw new SodiumException(
                'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes'
            );
        }

        #     crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
        #     crypto_onetimeauth_poly1305_init(&poly1305_state, block);
        #     sodium_memzero(block, sizeof block);
        $auth = new ParagonIE_Sodium_Core32_Poly1305_State(
            ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey())
        );

        #     crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
        $auth->update($aad);

        #     crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
        #         (0x10 - adlen) & 0xf);
        $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf)));


        #     memset(block, 0, sizeof block);
        #     block[0] = in[0];
        #     crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
        #                                        state->nonce, 1U, state->k);
        $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            $cipher[0] . str_repeat("\0", 63),
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core32_Util::store64_le(1)
        );
        #     tag = block[0];
        #     block[0] = in[0];
        #     crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
        $tag = ParagonIE_Sodium_Core32_Util::chrToInt($block[0]);
        $block[0] = $cipher[0];
        $auth->update($block);


        #     c = in + (sizeof tag);
        #     crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
        $auth->update(ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen));

        #     crypto_onetimeauth_poly1305_update
        #     (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
        $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf)));

        #     STORE64_LE(slen, (uint64_t) adlen);
        #     crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
        $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen);
        $auth->update($slen);

        #     STORE64_LE(slen, (sizeof block) + mlen);
        #     crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
        $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen);
        $auth->update($slen);

        #     crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
        #     sodium_memzero(&poly1305_state, sizeof poly1305_state);
        $mac = $auth->finish();

        #     stored_mac = c + mlen;
        #     if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) {
        #     sodium_memzero(mac, sizeof mac);
        #         return -1;
        #     }

        $stored = ParagonIE_Sodium_Core32_Util::substr($cipher, $msglen + 1, 16);
        if (!ParagonIE_Sodium_Core32_Util::hashEquals($mac, $stored)) {
            return false;
        }

        #     crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k);
        $out = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen),
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core32_Util::store64_le(2)
        );

        #     XOR_BUF(STATE_INONCE(state), mac,
        #         crypto_secretstream_xchacha20poly1305_INONCEBYTES);
        $st->xorNonce($mac);

        #     sodium_increment(STATE_COUNTER(state),
        #         crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
        $st->incrementCounter();

        #     if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
        #         sodium_is_zero(STATE_COUNTER(state),
        #             crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
        #         crypto_secretstream_xchacha20poly1305_rekey(state);
        #     }

        // Overwrite by reference:
        $state = $st->toString();

        /** @var bool $rekey */
        $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0;
        if ($rekey || $st->needsRekey()) {
            // DO REKEY
            self::secretstream_xchacha20poly1305_rekey($state);
        }
        return array($out, $tag);
    }

    /**
     * @param string $state
     * @return void
     * @throws SodiumException
     */
    public static function secretstream_xchacha20poly1305_rekey(&$state)
    {
        $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state);
        # unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES +
        # crypto_secretstream_xchacha20poly1305_INONCEBYTES];
        # size_t        i;
        # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
        #     new_key_and_inonce[i] = state->k[i];
        # }
        $new_key_and_inonce = $st->getKey();

        # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
        #     new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] =
        #         STATE_INONCE(state)[i];
        # }
        $new_key_and_inonce .= ParagonIE_Sodium_Core32_Util::substR($st->getNonce(), 0, 8);

        # crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce,
        #                                 sizeof new_key_and_inonce,
        #                                 state->nonce, state->k);

        $st->rekey(ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            $new_key_and_inonce,
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core32_Util::store64_le(0)
        ));

        # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
        #     state->k[i] = new_key_and_inonce[i];
        # }
        # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
        #     STATE_INONCE(state)[i] =
        #          new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i];
        # }
        # _crypto_secretstream_xchacha20poly1305_counter_reset(state);
        $st->counterReset();

        $state = $st->toString();
    }

    /**
     * Detached Ed25519 signature.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_detached($message, $sk)
    {
        return ParagonIE_Sodium_Core32_Ed25519::sign_detached($message, $sk);
    }

    /**
     * Attached Ed25519 signature. (Returns a signed message.)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign($message, $sk)
    {
        return ParagonIE_Sodium_Core32_Ed25519::sign($message, $sk);
    }

    /**
     * Opens a signed message. If valid, returns the message.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $signedMessage
     * @param string $pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_open($signedMessage, $pk)
    {
        return ParagonIE_Sodium_Core32_Ed25519::sign_open($signedMessage, $pk);
    }

    /**
     * Verify a detached signature of a given message and public key.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $signature
     * @param string $message
     * @param string $pk
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_verify_detached($signature, $message, $pk)
    {
        return ParagonIE_Sodium_Core32_Ed25519::verify_detached($signature, $message, $pk);
    }
}

SPERA Medicare – Affy Pharma Pvt Ltd

SPEROXIME

POWDER FOR ORAL SUSPENSION
30ML (HDPE BOTTLE)

Composition

Cefpodoxime 50mg/5ml

Indications & Uses

UTIs, LRTs

SPEROXIME-CV

POWDER FOR ORAL SUSPENSION
30ML (GLASS BOTTLE)

Composition

Cefpodoxime 50mg + Potassium Clavulanate 31.25mg/ 5ml

Indications & Uses

Upper & lower respiratory infections, Uncomplicated skin infections, Urinary Tract Infections

SPERACLAV

POWDER FOR ORAL SUSPENSION
30ML (GLASS +HDPE BOTTLE)

Composition

Amoxycillin 200mg + Potassium clavulanate 28.50 mg/ 5ml

Indications & Uses

Community Acquired Pneumonia, Acute Exacerbations of Chronic Bronchitis, Upper Respiratory Tract Infections, Urinary Tract Infections

SPERIXIME-CV

POWDER FOR ORAL SUSPENSION

30ML (GLASS BOTTLE)

Composition

Cefixime 50mg + Potassium clavulanate 31.25mg/5ml

Indications & Uses

Urinary Tract Inefctions, AECB, Otitis Media, Typhoid

SPERIXIME

POWDER FOR ORAL SUSPENSION
30ML (HDPE BOTTLE)

Composition

Cefixime 50mg/5ml

Indications & Uses

Urinary Tract Inefctions, Gastroenteritis

SPAZIT

ORAL SUSPENSION
15 ml

Composition

Azithromycin 200mg/5ml

Indications & Uses

Community Acquired Pneumonia, Acute Exacerbations of Chronic Bronchitis,

SPENOMOL-DS

ORAL SUSPENSION
60 ml

Composition

Paracetamol 250mg/5ml

Indications & Uses

Fever, Pain

SPENOMOLM

ORAL SUSPENSION
60 ml

Composition

Paracetamol 125mg + Mefenamic Acid 50mg/5ml

Indications & Uses

Pain, Fever

SPEROF

ORAL SUSPENSION
30 ml

Composition

Ofloxacin 50mg/5ml

Indications & Uses

Acute exacerbations of chronic Bronchitis, Diarrhoea

SPENOMOL-CP

SYRUP
60 ml

Composition

Paracetamol 125mg + PPH 5mg + Cetirizine HCI 2mg/5ml

Indications & Uses

Fever, common cold & Flu

PROBILIN

ORAL SUSPENSION
200ml

Composition

Cyproheptadine HCI 2mg + Tricholine citrate 0.275mg/5ml

Indications & Uses

Stimulate Apetite, Induces Weight Gain, Cure Allergies

SPERAZOLE-DSR

CAPSULES ( HARD GELATIN)
10X10 (Alu-Alu)

Composition

Pantoprazole 40mg (EC) + Domperidone 30mg (SR)

Indications & Uses

GERD, Dyspepsia, Acid Peptic Disorders, Gastritis

SPERAB-DSR

CAPSULES ( HARD GELATIN)
11X10 (Alu-Alu)

Composition

Rabeprazole 20mg (EC) + Domperidone SR

Indications & Uses

GERD, Dyspepsia, Acid Peptic Disorders, Gastritis

SPERAZOLE 40

INJECTION

40ml

Composition

Pantoprazole Sodium 40mg + NaCL

Indications & Uses

Acid-peptic disorders in hospitalized patients, Zollinger – Ellison Syndrome, Treatment of GERD Associated with Erasive Esophagitis, GL Bleed

COOLRICH

SUSPENSION
170ml

Composition

Activated Dimethicone 25mg + Magnesium Hydroxide 200mg+ Aluminium Hydroxide Gel 200mg/10ml

Indications & Uses

Heartburn, Acid Indigestion

SPERAZYME

SYRUP
200ml

Composition

Alpha Amylase (1:2000) 50mg, Pepsin(1:3000) 10mg/5ml

Indications & Uses

Dyspepsia, Flatulence, Anorexia, Pancreatic Insufficiency

SPUR-ON

CAPSULES (HARD GELATIN)
10X3X10

Composition

Vitamin C 75mg + Vitamin B12 5mcg + Carbonyl Iron 100mg + Folic Acid 1.5mg + Zinc Sulphate 61.8mg

Indications & Uses

Hyphocromic Anemia in Pregnancy, Chronic and / or Acute Blood Loss, Post-gynaesurgery, Iron Deficiency Anemia

SP-D3 60K

CAPSULES (SOFT GELATIN)
10X1X4

Composition

Cholecalciferol 60000 UI

Indications & Uses

Osteoporosis, Osteoarthritis, Musculoskeletal Pain, Type- 2 Diabetes, Menstrual Irregularities, Pre-eclampsia, IUGR

ERABONA

ORAL SUSPENSION
200ml

Composition

Calcium Carbonate 625mg, Vitamin D3 125 IU/5ml

Indications & Uses

Osteomalacia, Osteoporosis, Fractures, Premenstrual Syndrome

IRO-SPUR

SYRUP (IRON TONIC)
300 ml

Composition

Iron (III) Hydroxide Polymaltose 50mg, Folic Acid 0.5mg/15ml

Indications & Uses

Pregnancy and lactation, Iron Deficiency Anaemia, Anaemia due to Excessive Haemorrhage, Anaemia Associated with Infections and Malignant Disease

CALANTE-Z

CAPSULES (SOFT GELATIN)
5X2X15

Composition

Calcitriol 0.25mcg + Calcium Carbonate 500mg + Zinc Sulphate 7.5mg

Indications & Uses

Osteoporosis, Hypoparathyroidism, Pregnancy & Lactation, Premenstrual Syndrome

SPERA SPAS

TABLETS
20X10

Composition

Mefenamic Acid 250mg + Dicyclomine HCI 10mg

Indications & Uses

Dysmenorrhea, Irritable Bowel Syndrome, Colic and Bladder Spasm, Abdominal Pain

SPERAFEN

TABLETS (BLISTERS)
20X10

Composition

Nimeulide 100mg + Paracetamo; 325mg

Indications & Uses

Arthritis Pain, Soft Tissue Trauma Including Sprains, Musculoskeletal Pain, Pain Following Dental Extraction

PARADOL FORTE

TABLETS

20X10

Composition

Tramadol 37.5mg + Paracetamol 325mg

Indications & Uses

Chronic Back Pain, Osteoarthritis, Postoperative Pain

DIRABEN GEL

GEL
30g

Composition

Diclofenac Diethylamine 1.16% w/w + Oleum Linseed Oil 3 % w/w + Menthol 5% w/w +Methyl Salicylate 10% w/w

Indications & Uses

Sprains & Strains, Lower Back Pain, Joint Pain, Knee Pain

ULTISOFT

CREAM
20g

Composition

Urea 10% +Lactic Acid 10% + Propylene Glycol 10% + Liquid Paraffin 10%

Indications & Uses

Foot Cracks, Keratolytic

PERAZOB

OINTMENT
15g

Composition

Clotrimazole 1% w/w + Beclomethasone Dipropionate 0.025% w/w + Neomycin 0.5% w/w

Indications & Uses

Eczema, Psoriasis, Corticosteroid Responsive Dermatoses

SPARKETO

LOTION
100 ml

Composition

Ketoconazole 2% w/v

Indications & Uses

Pityriasis, Dandruff

SPARKETO-Z

LOTION
100 ml

Composition

Ketoconazole Shampoo 2% w/v + ZPTO 1% w/v

Indications & Uses

Pityriasis, Dandruff

SPARKETO

SOAP
75g

Composition

Ketoconazole 1% w/w

Indications & Uses

Tinea Versicolor, Prophylaxis of Pityriasis Versicolor

SPUKA

TABLETS
20X1X1

Composition

Fluconazole 200mg

Indications & Uses

Vaginal Candidiasis, Brochopulmonary Infections, Candiduria, Tinea Pedis, Corposis, Cruris, Versicolor

VITALAND

SYRUP
200ml

Composition

L-Iysine HCI 25mg + Vitamin B1 2.5mg + Vitamin B2 2.5mg + Vitamin B6 0.75mg + D-panthenol 3mg +Niacinamide 25mg + Mecobalamin 2mcg/10ml

Indications & Uses

Sub-optimal Growth, Poor Weight Gain, Malnutrition, Prolonged Illness

LYCOZIDE PLUS

SYRUP
225ml

Composition

Each 10ml Contains: Lycopene 6% 1000mcg + Vitamin A Palmitate 2500 IU + Vitamin E 10 IU + Ascorbic Acid 50mg + Selenium (as Sodium Selenate) 35mcg + Zinc (As Zinc Gluconate) 3mg + Manganese (as Manganese Gluconate) 2mg + Iodine ( As Potassium Iodine) 100mcg + Copper (As Copper Sulphate0 500mcg + Thiamine HCI 2mg + Riboflavine 3mg + Pyridoxine HCI 1.5mg

Indications & Uses

Tiredness, Stress, Feeling of Weakness, Vitality Deficiency

DENUM

CAPSULES (SOFT GELATIN)
10X1X10

Composition

Antioxidant, Multivitamin & Multiminerals

Indications & Uses

Tiredness, Stress, Feeling of Weakness, Vitality Deficiency

NATOW

CAPSULES (SOFT GELATIN)
10X1X10

Composition

Vitamin E (Natural) 400 IU + Wheat Germ Oil 100mg + Omega 3 Fatty Acids 30mg

Indications & Uses

Ulcerative colitis, Metabolic Syndrome, Rheumatoid Arthritis, Type-2 Diabetes, Cardiovascular Diseases

LYCOZIDE

CAPSULES (SOFT GELATIN)
10X1X10

Composition

Each SG Contains Lycopene 6% 2000 IU + Vitamin A 2500 IU + Vitamin E Acetate 10 IU + Vitamin C 50 mg + Zinc sulphate Monohydrate 27.45mg + Selenium Dioxide 70mcg

Indications & Uses

Idiopathic Male Infertility, Pre-eclampsia, Prostate Cancer, Cardiovascular Diseases, Diabetes Mellitus

DENUM 4G

CAPSULES (SOFT GELATIN)
10X1X10

Composition

Omega 3 Fatty Acid + Ginseng Extract + Ginkgo Bilaba Extract + Grape Seed Extract + Ginseng Extract + Multimineral + Multivitamin + Antioxidants + Trace Elements

Indications & Uses

Tiredness, Stress, Feeling of Weakness, Vitality Deficiency

DENUM G

CAPSULES (SOFT GELATIN)
10X1X11

Composition

Ginseng + Multivitamin + Multimineral

Indications & Uses

Tiredness, Stress, Feeling of Weakness, Vitality Deficiency

SPERIXIME – 200 LB

TABLETS (Alu-Alu)

20X10

Composition

Cefixime 200mg + Lactic Acid Bacilus 2.5 billion spores

Indications & Uses

Otitis Media, Pharyngitis & Tonsillitis, Uncomplicated Urinary Tract Infections, Acute Exacerbations of Chronic Bronchitis, Enteric Fever

SPERIXIME-CV 325

TABLETS (Alu-Alu)
10X1X6

Composition

Cefixime 200mg + Potassium Clavulanate 125mg

Indications & Uses

Respiratory Tract Infections, Urinary Tract Infections, Skin & Skin Structure Infections

SPERACLAV-625

TABLETS (Alu-Alu)
10X1X6

Composition

Amoxycillin 500mg + Potassium Clavulanate 125mg

Indications & Uses

Respiratory Tract Infections, Community Acquired Pneumonia, Gynaecological Infections, Acute Exacerbations of Chronic Bronchitis, Skin and Soft Tissue Infections

SPEROF-O

TABLETS (Blister)
20X10

Composition

Ofloxacin 200mg + Ornidazole 500mg

Indications & Uses

Surgical ions, Diarrheas of Mixed Etiology, Gynaecological Infections, Orofacial and Dental Infections

VEXACIN

TABLETS
10X10

Composition

Levofloxacin 500mg

Indications & Uses

Acute Bacterial Sinusitis, Acute Bacterial Exacerbations of Chronic Bronchitis, Skin & Skin Structure Infections, Chronic Bacterial Prostatitis, Urinary Tract Infections

SPERIXIME-O

TABLETS (Alu-Alu)
10X1X10

Composition

Cefixime 200mg + Ofloxacin 200mg

Indications & Uses

Community Acquired Pneumonia, Multiple Drug Resistant-TB, Typhoid

SPEROXIME-200

TABLETS (Alu-Alu)
10X1X6

Composition

Cefpodoxime Proxetil 200mg

Indications & Uses

Pharyngitis, CAP, Tonsilitis

SPERACLAV-1.2

INJECTIONS
1.2g

Composition

Amoxycillin 1000mg + Potassium Clavulanate 200mg + WFI

Indications & Uses

Community Acquired Pneumonia, Gynaecological Infections, Upper Respiratory Tract Infections, Skin and Soft Tissue Infections, Urinary Tract Infections, Acute Exacerbations of Chronic Bronchitis

SPERBACT-SB 1.5

INJECTIONS
1.5g

Composition

Ceftriaxone 1000mg + Sulbactam 500mg + WFI

Indications & Uses

Gynaecological Infections, Lower Respiratory Tract Infections, Intra-abdominal Infections with Aerobic Organisms, Surgical Prophylaxis

SPERBACT-TZ 1.125

INJECTIONS
1.125gm

Composition

Ceftriaxone 1000mg + Tazobactam 500 mg + WFI

Indications & Uses

Bone & Joint Infections, Intra-abdominal Infections, Bacterial Meningitis, Pre-operative Surgical Prophylaxis

SPERLIV

INJECTIONS
1gm

Composition

Meropenem 1gm + WFI

Indications & Uses

Complicated Intra-abdominal Infection (cIAI), Complicated Skin & Skin Structure Infections (cSSSI), Bacterial Meningitis, Noscocomial Pneumonia

SPIPER-Z 4.5

INJECTIONS
4.5gm

Composition

Piperacillin 4000mg + Tazobactam 500mg + WFI

Indications & Uses

Intra-abdominal Infections, Complicated Urinary Tract Infections, Febrile Neutropenia, Lower Respiratory Tract Infections

SPERBACT-C

INJECTIONS
1.5gm

Composition

Cefaperazone 1000mg + Sulbactam 500mg +WFI

Indications & Uses

Peritonitis, Bacterial Simusitis, Cholecystitis, Meningitis

BROXTAR

SYRUP
100ml

Composition

Ambroxol HCI 15mg + Guaiphensin 50mg + Terbutaline Sulphate 1.5mg + Mentholated Base/5ml

Indications & Uses

Bronchitis, Productive Cough, Emphysema, Bronchial Asthma

BROXTAR-BR

SYRUP

100ml

Composition

Terbutaline Sulphate 1.25mg + Bromhexine HCI 4mg + Guaiphenesin 50mg + Methalated Base/5ml

Indications & Uses

Acute Cough, Abnormal Mucus Secretion, Productive Cough

THROMET

SYRUP
100ml

Composition

Dextromethorphan Hydrobromide 10mg + Phenylpherine 5 mg + Cetrizine 5mg + Mentholated Base/5ml

Indications & Uses

Commom Cold and Flu, Nasal Congestion, Sore Throat

IRIDIE-M

TABLETS (Alu-Alu)
20X10

Composition

Levocetirizine 5mg + Montelukast 10mg

Indications & Uses

Allergic Rhinitis, Nasal Congestion, Asthma

IRIDIE

TABLETS (Alu-Alu)
20X11

Composition

Levocetirizine 5mg

Indications & Uses

Chronic Idiopathic Urticaria (CIU), Seasonal Allergic Rhinitis (SAR), Perennial Allergic Rhinitis (PAR)

Arrange A Callback
[]
1 Step 1
Full Name
Telephone
Departmentyour full name
Postal Address
Message
0 /
Previous
Next
Shopping Basket