| Server IP : 170.10.162.208 / Your IP : 216.73.216.181 Web Server : LiteSpeed System : Linux altar19.supremepanel19.com 4.18.0-553.69.1.lve.el8.x86_64 #1 SMP Wed Aug 13 19:53:59 UTC 2025 x86_64 User : deltahospital ( 1806) PHP Version : 7.4.33 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /var/tmp/ |
Upload File : |
Crypto32.php 0000644 00000153517 15051413217 0006715 0 ustar 00 <?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);
}
}
Core32/SipHash.php 0000644 00000014725 15051413224 0007657 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core32_SipHash', false)) {
return;
}
/**
* Class ParagonIE_SodiumCompat_Core32_SipHash
*
* Only uses 32-bit arithmetic, while the original SipHash used 64-bit integers
*/
class ParagonIE_Sodium_Core32_SipHash extends ParagonIE_Sodium_Core32_Util
{
/**
* @internal You should not use this directly from another application
*
* @param array<int, ParagonIE_Sodium_Core32_Int64> $v
* @return array<int, ParagonIE_Sodium_Core32_Int64>
*/
public static function sipRound(array $v)
{
# v0 += v1;
$v[0] = $v[0]->addInt64($v[1]);
# v1 = ROTL(v1, 13);
$v[1] = $v[1]->rotateLeft(13);
# v1 ^= v0;
$v[1] = $v[1]->xorInt64($v[0]);
# v0=ROTL(v0,32);
$v[0] = $v[0]->rotateLeft(32);
# v2 += v3;
$v[2] = $v[2]->addInt64($v[3]);
# v3=ROTL(v3,16);
$v[3] = $v[3]->rotateLeft(16);
# v3 ^= v2;
$v[3] = $v[3]->xorInt64($v[2]);
# v0 += v3;
$v[0] = $v[0]->addInt64($v[3]);
# v3=ROTL(v3,21);
$v[3] = $v[3]->rotateLeft(21);
# v3 ^= v0;
$v[3] = $v[3]->xorInt64($v[0]);
# v2 += v1;
$v[2] = $v[2]->addInt64($v[1]);
# v1=ROTL(v1,17);
$v[1] = $v[1]->rotateLeft(17);
# v1 ^= v2;
$v[1] = $v[1]->xorInt64($v[2]);
# v2=ROTL(v2,32)
$v[2] = $v[2]->rotateLeft(32);
return $v;
}
/**
* @internal You should not use this directly from another application
*
* @param string $in
* @param string $key
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function sipHash24($in, $key)
{
$inlen = self::strlen($in);
# /* "somepseudorandomlygeneratedbytes" */
# u64 v0 = 0x736f6d6570736575ULL;
# u64 v1 = 0x646f72616e646f6dULL;
# u64 v2 = 0x6c7967656e657261ULL;
# u64 v3 = 0x7465646279746573ULL;
$v = array(
new ParagonIE_Sodium_Core32_Int64(
array(0x736f, 0x6d65, 0x7073, 0x6575)
),
new ParagonIE_Sodium_Core32_Int64(
array(0x646f, 0x7261, 0x6e64, 0x6f6d)
),
new ParagonIE_Sodium_Core32_Int64(
array(0x6c79, 0x6765, 0x6e65, 0x7261)
),
new ParagonIE_Sodium_Core32_Int64(
array(0x7465, 0x6462, 0x7974, 0x6573)
)
);
# u64 k0 = LOAD64_LE( k );
# u64 k1 = LOAD64_LE( k + 8 );
$k = array(
ParagonIE_Sodium_Core32_Int64::fromReverseString(
self::substr($key, 0, 8)
),
ParagonIE_Sodium_Core32_Int64::fromReverseString(
self::substr($key, 8, 8)
)
);
# b = ( ( u64 )inlen ) << 56;
$b = new ParagonIE_Sodium_Core32_Int64(
array(($inlen << 8) & 0xffff, 0, 0, 0)
);
# v3 ^= k1;
$v[3] = $v[3]->xorInt64($k[1]);
# v2 ^= k0;
$v[2] = $v[2]->xorInt64($k[0]);
# v1 ^= k1;
$v[1] = $v[1]->xorInt64($k[1]);
# v0 ^= k0;
$v[0] = $v[0]->xorInt64($k[0]);
$left = $inlen;
# for ( ; in != end; in += 8 )
while ($left >= 8) {
# m = LOAD64_LE( in );
$m = ParagonIE_Sodium_Core32_Int64::fromReverseString(
self::substr($in, 0, 8)
);
# v3 ^= m;
$v[3] = $v[3]->xorInt64($m);
# SIPROUND;
# SIPROUND;
$v = self::sipRound($v);
$v = self::sipRound($v);
# v0 ^= m;
$v[0] = $v[0]->xorInt64($m);
$in = self::substr($in, 8);
$left -= 8;
}
# switch( left )
# {
# case 7: b |= ( ( u64 )in[ 6] ) << 48;
# case 6: b |= ( ( u64 )in[ 5] ) << 40;
# case 5: b |= ( ( u64 )in[ 4] ) << 32;
# case 4: b |= ( ( u64 )in[ 3] ) << 24;
# case 3: b |= ( ( u64 )in[ 2] ) << 16;
# case 2: b |= ( ( u64 )in[ 1] ) << 8;
# case 1: b |= ( ( u64 )in[ 0] ); break;
# case 0: break;
# }
switch ($left) {
case 7:
$b = $b->orInt64(
ParagonIE_Sodium_Core32_Int64::fromInts(
0, self::chrToInt($in[6]) << 16
)
);
case 6:
$b = $b->orInt64(
ParagonIE_Sodium_Core32_Int64::fromInts(
0, self::chrToInt($in[5]) << 8
)
);
case 5:
$b = $b->orInt64(
ParagonIE_Sodium_Core32_Int64::fromInts(
0, self::chrToInt($in[4])
)
);
case 4:
$b = $b->orInt64(
ParagonIE_Sodium_Core32_Int64::fromInts(
self::chrToInt($in[3]) << 24, 0
)
);
case 3:
$b = $b->orInt64(
ParagonIE_Sodium_Core32_Int64::fromInts(
self::chrToInt($in[2]) << 16, 0
)
);
case 2:
$b = $b->orInt64(
ParagonIE_Sodium_Core32_Int64::fromInts(
self::chrToInt($in[1]) << 8, 0
)
);
case 1:
$b = $b->orInt64(
ParagonIE_Sodium_Core32_Int64::fromInts(
self::chrToInt($in[0]), 0
)
);
case 0:
break;
}
# v3 ^= b;
$v[3] = $v[3]->xorInt64($b);
# SIPROUND;
# SIPROUND;
$v = self::sipRound($v);
$v = self::sipRound($v);
# v0 ^= b;
$v[0] = $v[0]->xorInt64($b);
// Flip the lower 8 bits of v2 which is ($v[4], $v[5]) in our implementation
# v2 ^= 0xff;
$v[2]->limbs[3] ^= 0xff;
# SIPROUND;
# SIPROUND;
# SIPROUND;
# SIPROUND;
$v = self::sipRound($v);
$v = self::sipRound($v);
$v = self::sipRound($v);
$v = self::sipRound($v);
# b = v0 ^ v1 ^ v2 ^ v3;
# STORE64_LE( out, b );
return $v[0]
->xorInt64($v[1])
->xorInt64($v[2])
->xorInt64($v[3])
->toReverseString();
}
}
Core32/HSalsa20.php 0000644 00000015435 15051413226 0007636 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core32_HSalsa20', false)) {
return;
}
/**
* Class ParagonIE_Sodium_Core32_HSalsa20
*/
abstract class ParagonIE_Sodium_Core32_HSalsa20 extends ParagonIE_Sodium_Core32_Salsa20
{
/**
* Calculate an hsalsa20 hash of a single block
*
* HSalsa20 doesn't have a counter and will never be used for more than
* one block (used to derive a subkey for xsalsa20).
*
* @internal You should not use this directly from another application
*
* @param string $in
* @param string $k
* @param string|null $c
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function hsalsa20($in, $k, $c = null)
{
/**
* @var ParagonIE_Sodium_Core32_Int32 $x0
* @var ParagonIE_Sodium_Core32_Int32 $x1
* @var ParagonIE_Sodium_Core32_Int32 $x2
* @var ParagonIE_Sodium_Core32_Int32 $x3
* @var ParagonIE_Sodium_Core32_Int32 $x4
* @var ParagonIE_Sodium_Core32_Int32 $x5
* @var ParagonIE_Sodium_Core32_Int32 $x6
* @var ParagonIE_Sodium_Core32_Int32 $x7
* @var ParagonIE_Sodium_Core32_Int32 $x8
* @var ParagonIE_Sodium_Core32_Int32 $x9
* @var ParagonIE_Sodium_Core32_Int32 $x10
* @var ParagonIE_Sodium_Core32_Int32 $x11
* @var ParagonIE_Sodium_Core32_Int32 $x12
* @var ParagonIE_Sodium_Core32_Int32 $x13
* @var ParagonIE_Sodium_Core32_Int32 $x14
* @var ParagonIE_Sodium_Core32_Int32 $x15
* @var ParagonIE_Sodium_Core32_Int32 $j0
* @var ParagonIE_Sodium_Core32_Int32 $j1
* @var ParagonIE_Sodium_Core32_Int32 $j2
* @var ParagonIE_Sodium_Core32_Int32 $j3
* @var ParagonIE_Sodium_Core32_Int32 $j4
* @var ParagonIE_Sodium_Core32_Int32 $j5
* @var ParagonIE_Sodium_Core32_Int32 $j6
* @var ParagonIE_Sodium_Core32_Int32 $j7
* @var ParagonIE_Sodium_Core32_Int32 $j8
* @var ParagonIE_Sodium_Core32_Int32 $j9
* @var ParagonIE_Sodium_Core32_Int32 $j10
* @var ParagonIE_Sodium_Core32_Int32 $j11
* @var ParagonIE_Sodium_Core32_Int32 $j12
* @var ParagonIE_Sodium_Core32_Int32 $j13
* @var ParagonIE_Sodium_Core32_Int32 $j14
* @var ParagonIE_Sodium_Core32_Int32 $j15
*/
if (self::strlen($k) < 32) {
throw new RangeException('Key must be 32 bytes long');
}
if ($c === null) {
$x0 = new ParagonIE_Sodium_Core32_Int32(array(0x6170, 0x7865));
$x5 = new ParagonIE_Sodium_Core32_Int32(array(0x3320, 0x646e));
$x10 = new ParagonIE_Sodium_Core32_Int32(array(0x7962, 0x2d32));
$x15 = new ParagonIE_Sodium_Core32_Int32(array(0x6b20, 0x6574));
} else {
$x0 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 0, 4));
$x5 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 4, 4));
$x10 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 8, 4));
$x15 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 12, 4));
}
$x1 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 0, 4));
$x2 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 4, 4));
$x3 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 8, 4));
$x4 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 12, 4));
$x6 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 0, 4));
$x7 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 4, 4));
$x8 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 8, 4));
$x9 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 12, 4));
$x11 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 16, 4));
$x12 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 20, 4));
$x13 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 24, 4));
$x14 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 28, 4));
for ($i = self::ROUNDS; $i > 0; $i -= 2) {
$x4 = $x4->xorInt32($x0->addInt32($x12)->rotateLeft(7));
$x8 = $x8->xorInt32($x4->addInt32($x0)->rotateLeft(9));
$x12 = $x12->xorInt32($x8->addInt32($x4)->rotateLeft(13));
$x0 = $x0->xorInt32($x12->addInt32($x8)->rotateLeft(18));
$x9 = $x9->xorInt32($x5->addInt32($x1)->rotateLeft(7));
$x13 = $x13->xorInt32($x9->addInt32($x5)->rotateLeft(9));
$x1 = $x1->xorInt32($x13->addInt32($x9)->rotateLeft(13));
$x5 = $x5->xorInt32($x1->addInt32($x13)->rotateLeft(18));
$x14 = $x14->xorInt32($x10->addInt32($x6)->rotateLeft(7));
$x2 = $x2->xorInt32($x14->addInt32($x10)->rotateLeft(9));
$x6 = $x6->xorInt32($x2->addInt32($x14)->rotateLeft(13));
$x10 = $x10->xorInt32($x6->addInt32($x2)->rotateLeft(18));
$x3 = $x3->xorInt32($x15->addInt32($x11)->rotateLeft(7));
$x7 = $x7->xorInt32($x3->addInt32($x15)->rotateLeft(9));
$x11 = $x11->xorInt32($x7->addInt32($x3)->rotateLeft(13));
$x15 = $x15->xorInt32($x11->addInt32($x7)->rotateLeft(18));
$x1 = $x1->xorInt32($x0->addInt32($x3)->rotateLeft(7));
$x2 = $x2->xorInt32($x1->addInt32($x0)->rotateLeft(9));
$x3 = $x3->xorInt32($x2->addInt32($x1)->rotateLeft(13));
$x0 = $x0->xorInt32($x3->addInt32($x2)->rotateLeft(18));
$x6 = $x6->xorInt32($x5->addInt32($x4)->rotateLeft(7));
$x7 = $x7->xorInt32($x6->addInt32($x5)->rotateLeft(9));
$x4 = $x4->xorInt32($x7->addInt32($x6)->rotateLeft(13));
$x5 = $x5->xorInt32($x4->addInt32($x7)->rotateLeft(18));
$x11 = $x11->xorInt32($x10->addInt32($x9)->rotateLeft(7));
$x8 = $x8->xorInt32($x11->addInt32($x10)->rotateLeft(9));
$x9 = $x9->xorInt32($x8->addInt32($x11)->rotateLeft(13));
$x10 = $x10->xorInt32($x9->addInt32($x8)->rotateLeft(18));
$x12 = $x12->xorInt32($x15->addInt32($x14)->rotateLeft(7));
$x13 = $x13->xorInt32($x12->addInt32($x15)->rotateLeft(9));
$x14 = $x14->xorInt32($x13->addInt32($x12)->rotateLeft(13));
$x15 = $x15->xorInt32($x14->addInt32($x13)->rotateLeft(18));
}
return $x0->toReverseString() .
$x5->toReverseString() .
$x10->toReverseString() .
$x15->toReverseString() .
$x6->toReverseString() .
$x7->toReverseString() .
$x8->toReverseString() .
$x9->toReverseString();
}
}
Core32/Curve25519.php 0000644 00000403556 15051413227 0010021 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core32_Curve25519', false)) {
return;
}
/**
* Class ParagonIE_Sodium_Core32_Curve25519
*
* Implements Curve25519 core functions
*
* Based on the ref10 curve25519 code provided by libsodium
*
* @ref https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c
*/
abstract class ParagonIE_Sodium_Core32_Curve25519 extends ParagonIE_Sodium_Core32_Curve25519_H
{
/**
* Get a field element of size 10 with a value of 0
*
* @internal You should not use this directly from another application
*
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
* @throws SodiumException
* @throws TypeError
*/
public static function fe_0()
{
return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32()
)
);
}
/**
* Get a field element of size 10 with a value of 1
*
* @internal You should not use this directly from another application
*
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
* @throws SodiumException
* @throws TypeError
*/
public static function fe_1()
{
return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
ParagonIE_Sodium_Core32_Int32::fromInt(1),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32(),
new ParagonIE_Sodium_Core32_Int32()
)
);
}
/**
* Add two field elements.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedMethodCall
*/
public static function fe_add(
ParagonIE_Sodium_Core32_Curve25519_Fe $f,
ParagonIE_Sodium_Core32_Curve25519_Fe $g
) {
$arr = array();
for ($i = 0; $i < 10; ++$i) {
$arr[$i] = $f[$i]->addInt32($g[$i]);
}
/** @var array<int, ParagonIE_Sodium_Core32_Int32> $arr */
return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($arr);
}
/**
* Constant-time conditional move.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
* @param int $b
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedMethodCall
*/
public static function fe_cmov(
ParagonIE_Sodium_Core32_Curve25519_Fe $f,
ParagonIE_Sodium_Core32_Curve25519_Fe $g,
$b = 0
) {
/** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
$h = array();
for ($i = 0; $i < 10; ++$i) {
if (!($f[$i] instanceof ParagonIE_Sodium_Core32_Int32)) {
throw new TypeError('Expected Int32');
}
if (!($g[$i] instanceof ParagonIE_Sodium_Core32_Int32)) {
throw new TypeError('Expected Int32');
}
$h[$i] = $f[$i]->xorInt32(
$f[$i]->xorInt32($g[$i])->mask($b)
);
}
/** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h);
}
/**
* Create a copy of a field element.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
*/
public static function fe_copy(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
{
$h = clone $f;
return $h;
}
/**
* Give: 32-byte string.
* Receive: A field element object to use for internal calculations.
*
* @internal You should not use this directly from another application
*
* @param string $s
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
* @throws RangeException
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedMethodCall
*/
public static function fe_frombytes($s)
{
if (self::strlen($s) !== 32) {
throw new RangeException('Expected a 32-byte string.');
}
/** @var ParagonIE_Sodium_Core32_Int32 $h0 */
$h0 = ParagonIE_Sodium_Core32_Int32::fromInt(
self::load_4($s)
);
/** @var ParagonIE_Sodium_Core32_Int32 $h1 */
$h1 = ParagonIE_Sodium_Core32_Int32::fromInt(
self::load_3(self::substr($s, 4, 3)) << 6
);
/** @var ParagonIE_Sodium_Core32_Int32 $h2 */
$h2 = ParagonIE_Sodium_Core32_Int32::fromInt(
self::load_3(self::substr($s, 7, 3)) << 5
);
/** @var ParagonIE_Sodium_Core32_Int32 $h3 */
$h3 = ParagonIE_Sodium_Core32_Int32::fromInt(
self::load_3(self::substr($s, 10, 3)) << 3
);
/** @var ParagonIE_Sodium_Core32_Int32 $h4 */
$h4 = ParagonIE_Sodium_Core32_Int32::fromInt(
self::load_3(self::substr($s, 13, 3)) << 2
);
/** @var ParagonIE_Sodium_Core32_Int32 $h5 */
$h5 = ParagonIE_Sodium_Core32_Int32::fromInt(
self::load_4(self::substr($s, 16, 4))
);
/** @var ParagonIE_Sodium_Core32_Int32 $h6 */
$h6 = ParagonIE_Sodium_Core32_Int32::fromInt(
self::load_3(self::substr($s, 20, 3)) << 7
);
/** @var ParagonIE_Sodium_Core32_Int32 $h7 */
$h7 = ParagonIE_Sodium_Core32_Int32::fromInt(
self::load_3(self::substr($s, 23, 3)) << 5
);
/** @var ParagonIE_Sodium_Core32_Int32 $h8 */
$h8 = ParagonIE_Sodium_Core32_Int32::fromInt(
self::load_3(self::substr($s, 26, 3)) << 4
);
/** @var ParagonIE_Sodium_Core32_Int32 $h9 */
$h9 = ParagonIE_Sodium_Core32_Int32::fromInt(
(self::load_3(self::substr($s, 29, 3)) & 8388607) << 2
);
$carry9 = $h9->addInt(1 << 24)->shiftRight(25);
$h0 = $h0->addInt32($carry9->mulInt(19, 5));
$h9 = $h9->subInt32($carry9->shiftLeft(25));
$carry1 = $h1->addInt(1 << 24)->shiftRight(25);
$h2 = $h2->addInt32($carry1);
$h1 = $h1->subInt32($carry1->shiftLeft(25));
$carry3 = $h3->addInt(1 << 24)->shiftRight(25);
$h4 = $h4->addInt32($carry3);
$h3 = $h3->subInt32($carry3->shiftLeft(25));
$carry5 = $h5->addInt(1 << 24)->shiftRight(25);
$h6 = $h6->addInt32($carry5);
$h5 = $h5->subInt32($carry5->shiftLeft(25));
$carry7 = $h7->addInt(1 << 24)->shiftRight(25);
$h8 = $h8->addInt32($carry7);
$h7 = $h7->subInt32($carry7->shiftLeft(25));
$carry0 = $h0->addInt(1 << 25)->shiftRight(26);
$h1 = $h1->addInt32($carry0);
$h0 = $h0->subInt32($carry0->shiftLeft(26));
$carry2 = $h2->addInt(1 << 25)->shiftRight(26);
$h3 = $h3->addInt32($carry2);
$h2 = $h2->subInt32($carry2->shiftLeft(26));
$carry4 = $h4->addInt(1 << 25)->shiftRight(26);
$h5 = $h5->addInt32($carry4);
$h4 = $h4->subInt32($carry4->shiftLeft(26));
$carry6 = $h6->addInt(1 << 25)->shiftRight(26);
$h7 = $h7->addInt32($carry6);
$h6 = $h6->subInt32($carry6->shiftLeft(26));
$carry8 = $h8->addInt(1 << 25)->shiftRight(26);
$h9 = $h9->addInt32($carry8);
$h8 = $h8->subInt32($carry8->shiftLeft(26));
return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array($h0, $h1, $h2,$h3, $h4, $h5, $h6, $h7, $h8, $h9)
);
}
/**
* Convert a field element to a byte string.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $h
* @return string
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedMethodCall
*/
public static function fe_tobytes(ParagonIE_Sodium_Core32_Curve25519_Fe $h)
{
/**
* @var ParagonIE_Sodium_Core32_Int64[] $f
* @var ParagonIE_Sodium_Core32_Int64 $q
*/
$f = array();
for ($i = 0; $i < 10; ++$i) {
$f[$i] = $h[$i]->toInt64();
}
$q = $f[9]->mulInt(19, 5)->addInt(1 << 14)->shiftRight(25)
->addInt64($f[0])->shiftRight(26)
->addInt64($f[1])->shiftRight(25)
->addInt64($f[2])->shiftRight(26)
->addInt64($f[3])->shiftRight(25)
->addInt64($f[4])->shiftRight(26)
->addInt64($f[5])->shiftRight(25)
->addInt64($f[6])->shiftRight(26)
->addInt64($f[7])->shiftRight(25)
->addInt64($f[8])->shiftRight(26)
->addInt64($f[9])->shiftRight(25);
$f[0] = $f[0]->addInt64($q->mulInt(19, 5));
$carry0 = $f[0]->shiftRight(26);
$f[1] = $f[1]->addInt64($carry0);
$f[0] = $f[0]->subInt64($carry0->shiftLeft(26));
$carry1 = $f[1]->shiftRight(25);
$f[2] = $f[2]->addInt64($carry1);
$f[1] = $f[1]->subInt64($carry1->shiftLeft(25));
$carry2 = $f[2]->shiftRight(26);
$f[3] = $f[3]->addInt64($carry2);
$f[2] = $f[2]->subInt64($carry2->shiftLeft(26));
$carry3 = $f[3]->shiftRight(25);
$f[4] = $f[4]->addInt64($carry3);
$f[3] = $f[3]->subInt64($carry3->shiftLeft(25));
$carry4 = $f[4]->shiftRight(26);
$f[5] = $f[5]->addInt64($carry4);
$f[4] = $f[4]->subInt64($carry4->shiftLeft(26));
$carry5 = $f[5]->shiftRight(25);
$f[6] = $f[6]->addInt64($carry5);
$f[5] = $f[5]->subInt64($carry5->shiftLeft(25));
$carry6 = $f[6]->shiftRight(26);
$f[7] = $f[7]->addInt64($carry6);
$f[6] = $f[6]->subInt64($carry6->shiftLeft(26));
$carry7 = $f[7]->shiftRight(25);
$f[8] = $f[8]->addInt64($carry7);
$f[7] = $f[7]->subInt64($carry7->shiftLeft(25));
$carry8 = $f[8]->shiftRight(26);
$f[9] = $f[9]->addInt64($carry8);
$f[8] = $f[8]->subInt64($carry8->shiftLeft(26));
$carry9 = $f[9]->shiftRight(25);
$f[9] = $f[9]->subInt64($carry9->shiftLeft(25));
$h0 = $f[0]->toInt32()->toInt();
$h1 = $f[1]->toInt32()->toInt();
$h2 = $f[2]->toInt32()->toInt();
$h3 = $f[3]->toInt32()->toInt();
$h4 = $f[4]->toInt32()->toInt();
$h5 = $f[5]->toInt32()->toInt();
$h6 = $f[6]->toInt32()->toInt();
$h7 = $f[7]->toInt32()->toInt();
$h8 = $f[8]->toInt32()->toInt();
$h9 = $f[9]->toInt32()->toInt();
/**
* @var array<int, int>
*/
$s = array(
(int) (($h0 >> 0) & 0xff),
(int) (($h0 >> 8) & 0xff),
(int) (($h0 >> 16) & 0xff),
(int) ((($h0 >> 24) | ($h1 << 2)) & 0xff),
(int) (($h1 >> 6) & 0xff),
(int) (($h1 >> 14) & 0xff),
(int) ((($h1 >> 22) | ($h2 << 3)) & 0xff),
(int) (($h2 >> 5) & 0xff),
(int) (($h2 >> 13) & 0xff),
(int) ((($h2 >> 21) | ($h3 << 5)) & 0xff),
(int) (($h3 >> 3) & 0xff),
(int) (($h3 >> 11) & 0xff),
(int) ((($h3 >> 19) | ($h4 << 6)) & 0xff),
(int) (($h4 >> 2) & 0xff),
(int) (($h4 >> 10) & 0xff),
(int) (($h4 >> 18) & 0xff),
(int) (($h5 >> 0) & 0xff),
(int) (($h5 >> 8) & 0xff),
(int) (($h5 >> 16) & 0xff),
(int) ((($h5 >> 24) | ($h6 << 1)) & 0xff),
(int) (($h6 >> 7) & 0xff),
(int) (($h6 >> 15) & 0xff),
(int) ((($h6 >> 23) | ($h7 << 3)) & 0xff),
(int) (($h7 >> 5) & 0xff),
(int) (($h7 >> 13) & 0xff),
(int) ((($h7 >> 21) | ($h8 << 4)) & 0xff),
(int) (($h8 >> 4) & 0xff),
(int) (($h8 >> 12) & 0xff),
(int) ((($h8 >> 20) | ($h9 << 6)) & 0xff),
(int) (($h9 >> 2) & 0xff),
(int) (($h9 >> 10) & 0xff),
(int) (($h9 >> 18) & 0xff)
);
return self::intArrayToString($s);
}
/**
* Is a field element negative? (1 = yes, 0 = no. Used in calculations.)
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
* @return int
* @throws SodiumException
* @throws TypeError
*/
public static function fe_isnegative(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
{
$str = self::fe_tobytes($f);
return (int) (self::chrToInt($str[0]) & 1);
}
/**
* Returns 0 if this field element results in all NUL bytes.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
* @return bool
* @throws SodiumException
* @throws TypeError
*/
public static function fe_isnonzero(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
{
static $zero;
if ($zero === null) {
$zero = str_repeat("\x00", 32);
}
$str = self::fe_tobytes($f);
/** @var string $zero */
return !self::verify_32($str, $zero);
}
/**
* Multiply two field elements
*
* h = f * g
*
* @internal You should not use this directly from another application
*
* @security Is multiplication a source of timing leaks? If so, can we do
* anything to prevent that from happening?
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
* @throws SodiumException
* @throws TypeError
*/
public static function fe_mul(
ParagonIE_Sodium_Core32_Curve25519_Fe $f,
ParagonIE_Sodium_Core32_Curve25519_Fe $g
) {
/**
* @var ParagonIE_Sodium_Core32_Int32[] $f
* @var ParagonIE_Sodium_Core32_Int32[] $g
* @var ParagonIE_Sodium_Core32_Int64 $f0
* @var ParagonIE_Sodium_Core32_Int64 $f1
* @var ParagonIE_Sodium_Core32_Int64 $f2
* @var ParagonIE_Sodium_Core32_Int64 $f3
* @var ParagonIE_Sodium_Core32_Int64 $f4
* @var ParagonIE_Sodium_Core32_Int64 $f5
* @var ParagonIE_Sodium_Core32_Int64 $f6
* @var ParagonIE_Sodium_Core32_Int64 $f7
* @var ParagonIE_Sodium_Core32_Int64 $f8
* @var ParagonIE_Sodium_Core32_Int64 $f9
* @var ParagonIE_Sodium_Core32_Int64 $g0
* @var ParagonIE_Sodium_Core32_Int64 $g1
* @var ParagonIE_Sodium_Core32_Int64 $g2
* @var ParagonIE_Sodium_Core32_Int64 $g3
* @var ParagonIE_Sodium_Core32_Int64 $g4
* @var ParagonIE_Sodium_Core32_Int64 $g5
* @var ParagonIE_Sodium_Core32_Int64 $g6
* @var ParagonIE_Sodium_Core32_Int64 $g7
* @var ParagonIE_Sodium_Core32_Int64 $g8
* @var ParagonIE_Sodium_Core32_Int64 $g9
*/
$f0 = $f[0]->toInt64();
$f1 = $f[1]->toInt64();
$f2 = $f[2]->toInt64();
$f3 = $f[3]->toInt64();
$f4 = $f[4]->toInt64();
$f5 = $f[5]->toInt64();
$f6 = $f[6]->toInt64();
$f7 = $f[7]->toInt64();
$f8 = $f[8]->toInt64();
$f9 = $f[9]->toInt64();
$g0 = $g[0]->toInt64();
$g1 = $g[1]->toInt64();
$g2 = $g[2]->toInt64();
$g3 = $g[3]->toInt64();
$g4 = $g[4]->toInt64();
$g5 = $g[5]->toInt64();
$g6 = $g[6]->toInt64();
$g7 = $g[7]->toInt64();
$g8 = $g[8]->toInt64();
$g9 = $g[9]->toInt64();
$g1_19 = $g1->mulInt(19, 5); /* 2^4 <= 19 <= 2^5, but we only want 5 bits */
$g2_19 = $g2->mulInt(19, 5);
$g3_19 = $g3->mulInt(19, 5);
$g4_19 = $g4->mulInt(19, 5);
$g5_19 = $g5->mulInt(19, 5);
$g6_19 = $g6->mulInt(19, 5);
$g7_19 = $g7->mulInt(19, 5);
$g8_19 = $g8->mulInt(19, 5);
$g9_19 = $g9->mulInt(19, 5);
$f1_2 = $f1->shiftLeft(1);
$f3_2 = $f3->shiftLeft(1);
$f5_2 = $f5->shiftLeft(1);
$f7_2 = $f7->shiftLeft(1);
$f9_2 = $f9->shiftLeft(1);
$f0g0 = $f0->mulInt64($g0, 27);
$f0g1 = $f0->mulInt64($g1, 27);
$f0g2 = $f0->mulInt64($g2, 27);
$f0g3 = $f0->mulInt64($g3, 27);
$f0g4 = $f0->mulInt64($g4, 27);
$f0g5 = $f0->mulInt64($g5, 27);
$f0g6 = $f0->mulInt64($g6, 27);
$f0g7 = $f0->mulInt64($g7, 27);
$f0g8 = $f0->mulInt64($g8, 27);
$f0g9 = $f0->mulInt64($g9, 27);
$f1g0 = $f1->mulInt64($g0, 27);
$f1g1_2 = $f1_2->mulInt64($g1, 27);
$f1g2 = $f1->mulInt64($g2, 27);
$f1g3_2 = $f1_2->mulInt64($g3, 27);
$f1g4 = $f1->mulInt64($g4, 30);
$f1g5_2 = $f1_2->mulInt64($g5, 30);
$f1g6 = $f1->mulInt64($g6, 30);
$f1g7_2 = $f1_2->mulInt64($g7, 30);
$f1g8 = $f1->mulInt64($g8, 30);
$f1g9_38 = $g9_19->mulInt64($f1_2, 30);
$f2g0 = $f2->mulInt64($g0, 30);
$f2g1 = $f2->mulInt64($g1, 29);
$f2g2 = $f2->mulInt64($g2, 30);
$f2g3 = $f2->mulInt64($g3, 29);
$f2g4 = $f2->mulInt64($g4, 30);
$f2g5 = $f2->mulInt64($g5, 29);
$f2g6 = $f2->mulInt64($g6, 30);
$f2g7 = $f2->mulInt64($g7, 29);
$f2g8_19 = $g8_19->mulInt64($f2, 30);
$f2g9_19 = $g9_19->mulInt64($f2, 30);
$f3g0 = $f3->mulInt64($g0, 30);
$f3g1_2 = $f3_2->mulInt64($g1, 30);
$f3g2 = $f3->mulInt64($g2, 30);
$f3g3_2 = $f3_2->mulInt64($g3, 30);
$f3g4 = $f3->mulInt64($g4, 30);
$f3g5_2 = $f3_2->mulInt64($g5, 30);
$f3g6 = $f3->mulInt64($g6, 30);
$f3g7_38 = $g7_19->mulInt64($f3_2, 30);
$f3g8_19 = $g8_19->mulInt64($f3, 30);
$f3g9_38 = $g9_19->mulInt64($f3_2, 30);
$f4g0 = $f4->mulInt64($g0, 30);
$f4g1 = $f4->mulInt64($g1, 30);
$f4g2 = $f4->mulInt64($g2, 30);
$f4g3 = $f4->mulInt64($g3, 30);
$f4g4 = $f4->mulInt64($g4, 30);
$f4g5 = $f4->mulInt64($g5, 30);
$f4g6_19 = $g6_19->mulInt64($f4, 30);
$f4g7_19 = $g7_19->mulInt64($f4, 30);
$f4g8_19 = $g8_19->mulInt64($f4, 30);
$f4g9_19 = $g9_19->mulInt64($f4, 30);
$f5g0 = $f5->mulInt64($g0, 30);
$f5g1_2 = $f5_2->mulInt64($g1, 30);
$f5g2 = $f5->mulInt64($g2, 30);
$f5g3_2 = $f5_2->mulInt64($g3, 30);
$f5g4 = $f5->mulInt64($g4, 30);
$f5g5_38 = $g5_19->mulInt64($f5_2, 30);
$f5g6_19 = $g6_19->mulInt64($f5, 30);
$f5g7_38 = $g7_19->mulInt64($f5_2, 30);
$f5g8_19 = $g8_19->mulInt64($f5, 30);
$f5g9_38 = $g9_19->mulInt64($f5_2, 30);
$f6g0 = $f6->mulInt64($g0, 30);
$f6g1 = $f6->mulInt64($g1, 30);
$f6g2 = $f6->mulInt64($g2, 30);
$f6g3 = $f6->mulInt64($g3, 30);
$f6g4_19 = $g4_19->mulInt64($f6, 30);
$f6g5_19 = $g5_19->mulInt64($f6, 30);
$f6g6_19 = $g6_19->mulInt64($f6, 30);
$f6g7_19 = $g7_19->mulInt64($f6, 30);
$f6g8_19 = $g8_19->mulInt64($f6, 30);
$f6g9_19 = $g9_19->mulInt64($f6, 30);
$f7g0 = $f7->mulInt64($g0, 30);
$f7g1_2 = $g1->mulInt64($f7_2, 30);
$f7g2 = $f7->mulInt64($g2, 30);
$f7g3_38 = $g3_19->mulInt64($f7_2, 30);
$f7g4_19 = $g4_19->mulInt64($f7, 30);
$f7g5_38 = $g5_19->mulInt64($f7_2, 30);
$f7g6_19 = $g6_19->mulInt64($f7, 30);
$f7g7_38 = $g7_19->mulInt64($f7_2, 30);
$f7g8_19 = $g8_19->mulInt64($f7, 30);
$f7g9_38 = $g9_19->mulInt64($f7_2, 30);
$f8g0 = $f8->mulInt64($g0, 30);
$f8g1 = $f8->mulInt64($g1, 29);
$f8g2_19 = $g2_19->mulInt64($f8, 30);
$f8g3_19 = $g3_19->mulInt64($f8, 30);
$f8g4_19 = $g4_19->mulInt64($f8, 30);
$f8g5_19 = $g5_19->mulInt64($f8, 30);
$f8g6_19 = $g6_19->mulInt64($f8, 30);
$f8g7_19 = $g7_19->mulInt64($f8, 30);
$f8g8_19 = $g8_19->mulInt64($f8, 30);
$f8g9_19 = $g9_19->mulInt64($f8, 30);
$f9g0 = $f9->mulInt64($g0, 30);
$f9g1_38 = $g1_19->mulInt64($f9_2, 30);
$f9g2_19 = $g2_19->mulInt64($f9, 30);
$f9g3_38 = $g3_19->mulInt64($f9_2, 30);
$f9g4_19 = $g4_19->mulInt64($f9, 30);
$f9g5_38 = $g5_19->mulInt64($f9_2, 30);
$f9g6_19 = $g6_19->mulInt64($f9, 30);
$f9g7_38 = $g7_19->mulInt64($f9_2, 30);
$f9g8_19 = $g8_19->mulInt64($f9, 30);
$f9g9_38 = $g9_19->mulInt64($f9_2, 30);
// $h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 + $f5g5_38 + $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38;
$h0 = $f0g0->addInt64($f1g9_38)->addInt64($f2g8_19)->addInt64($f3g7_38)
->addInt64($f4g6_19)->addInt64($f5g5_38)->addInt64($f6g4_19)
->addInt64($f7g3_38)->addInt64($f8g2_19)->addInt64($f9g1_38);
// $h1 = $f0g1 + $f1g0 + $f2g9_19 + $f3g8_19 + $f4g7_19 + $f5g6_19 + $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19;
$h1 = $f0g1->addInt64($f1g0)->addInt64($f2g9_19)->addInt64($f3g8_19)
->addInt64($f4g7_19)->addInt64($f5g6_19)->addInt64($f6g5_19)
->addInt64($f7g4_19)->addInt64($f8g3_19)->addInt64($f9g2_19);
// $h2 = $f0g2 + $f1g1_2 + $f2g0 + $f3g9_38 + $f4g8_19 + $f5g7_38 + $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38;
$h2 = $f0g2->addInt64($f1g1_2)->addInt64($f2g0)->addInt64($f3g9_38)
->addInt64($f4g8_19)->addInt64($f5g7_38)->addInt64($f6g6_19)
->addInt64($f7g5_38)->addInt64($f8g4_19)->addInt64($f9g3_38);
// $h3 = $f0g3 + $f1g2 + $f2g1 + $f3g0 + $f4g9_19 + $f5g8_19 + $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19;
$h3 = $f0g3->addInt64($f1g2)->addInt64($f2g1)->addInt64($f3g0)
->addInt64($f4g9_19)->addInt64($f5g8_19)->addInt64($f6g7_19)
->addInt64($f7g6_19)->addInt64($f8g5_19)->addInt64($f9g4_19);
// $h4 = $f0g4 + $f1g3_2 + $f2g2 + $f3g1_2 + $f4g0 + $f5g9_38 + $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38;
$h4 = $f0g4->addInt64($f1g3_2)->addInt64($f2g2)->addInt64($f3g1_2)
->addInt64($f4g0)->addInt64($f5g9_38)->addInt64($f6g8_19)
->addInt64($f7g7_38)->addInt64($f8g6_19)->addInt64($f9g5_38);
// $h5 = $f0g5 + $f1g4 + $f2g3 + $f3g2 + $f4g1 + $f5g0 + $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19;
$h5 = $f0g5->addInt64($f1g4)->addInt64($f2g3)->addInt64($f3g2)
->addInt64($f4g1)->addInt64($f5g0)->addInt64($f6g9_19)
->addInt64($f7g8_19)->addInt64($f8g7_19)->addInt64($f9g6_19);
// $h6 = $f0g6 + $f1g5_2 + $f2g4 + $f3g3_2 + $f4g2 + $f5g1_2 + $f6g0 + $f7g9_38 + $f8g8_19 + $f9g7_38;
$h6 = $f0g6->addInt64($f1g5_2)->addInt64($f2g4)->addInt64($f3g3_2)
->addInt64($f4g2)->addInt64($f5g1_2)->addInt64($f6g0)
->addInt64($f7g9_38)->addInt64($f8g8_19)->addInt64($f9g7_38);
// $h7 = $f0g7 + $f1g6 + $f2g5 + $f3g4 + $f4g3 + $f5g2 + $f6g1 + $f7g0 + $f8g9_19 + $f9g8_19;
$h7 = $f0g7->addInt64($f1g6)->addInt64($f2g5)->addInt64($f3g4)
->addInt64($f4g3)->addInt64($f5g2)->addInt64($f6g1)
->addInt64($f7g0)->addInt64($f8g9_19)->addInt64($f9g8_19);
// $h8 = $f0g8 + $f1g7_2 + $f2g6 + $f3g5_2 + $f4g4 + $f5g3_2 + $f6g2 + $f7g1_2 + $f8g0 + $f9g9_38;
$h8 = $f0g8->addInt64($f1g7_2)->addInt64($f2g6)->addInt64($f3g5_2)
->addInt64($f4g4)->addInt64($f5g3_2)->addInt64($f6g2)
->addInt64($f7g1_2)->addInt64($f8g0)->addInt64($f9g9_38);
// $h9 = $f0g9 + $f1g8 + $f2g7 + $f3g6 + $f4g5 + $f5g4 + $f6g3 + $f7g2 + $f8g1 + $f9g0 ;
$h9 = $f0g9->addInt64($f1g8)->addInt64($f2g7)->addInt64($f3g6)
->addInt64($f4g5)->addInt64($f5g4)->addInt64($f6g3)
->addInt64($f7g2)->addInt64($f8g1)->addInt64($f9g0);
/**
* @var ParagonIE_Sodium_Core32_Int64 $h0
* @var ParagonIE_Sodium_Core32_Int64 $h1
* @var ParagonIE_Sodium_Core32_Int64 $h2
* @var ParagonIE_Sodium_Core32_Int64 $h3
* @var ParagonIE_Sodium_Core32_Int64 $h4
* @var ParagonIE_Sodium_Core32_Int64 $h5
* @var ParagonIE_Sodium_Core32_Int64 $h6
* @var ParagonIE_Sodium_Core32_Int64 $h7
* @var ParagonIE_Sodium_Core32_Int64 $h8
* @var ParagonIE_Sodium_Core32_Int64 $h9
* @var ParagonIE_Sodium_Core32_Int64 $carry0
* @var ParagonIE_Sodium_Core32_Int64 $carry1
* @var ParagonIE_Sodium_Core32_Int64 $carry2
* @var ParagonIE_Sodium_Core32_Int64 $carry3
* @var ParagonIE_Sodium_Core32_Int64 $carry4
* @var ParagonIE_Sodium_Core32_Int64 $carry5
* @var ParagonIE_Sodium_Core32_Int64 $carry6
* @var ParagonIE_Sodium_Core32_Int64 $carry7
* @var ParagonIE_Sodium_Core32_Int64 $carry8
* @var ParagonIE_Sodium_Core32_Int64 $carry9
*/
$carry0 = $h0->addInt(1 << 25)->shiftRight(26);
$h1 = $h1->addInt64($carry0);
$h0 = $h0->subInt64($carry0->shiftLeft(26));
$carry4 = $h4->addInt(1 << 25)->shiftRight(26);
$h5 = $h5->addInt64($carry4);
$h4 = $h4->subInt64($carry4->shiftLeft(26));
$carry1 = $h1->addInt(1 << 24)->shiftRight(25);
$h2 = $h2->addInt64($carry1);
$h1 = $h1->subInt64($carry1->shiftLeft(25));
$carry5 = $h5->addInt(1 << 24)->shiftRight(25);
$h6 = $h6->addInt64($carry5);
$h5 = $h5->subInt64($carry5->shiftLeft(25));
$carry2 = $h2->addInt(1 << 25)->shiftRight(26);
$h3 = $h3->addInt64($carry2);
$h2 = $h2->subInt64($carry2->shiftLeft(26));
$carry6 = $h6->addInt(1 << 25)->shiftRight(26);
$h7 = $h7->addInt64($carry6);
$h6 = $h6->subInt64($carry6->shiftLeft(26));
$carry3 = $h3->addInt(1 << 24)->shiftRight(25);
$h4 = $h4->addInt64($carry3);
$h3 = $h3->subInt64($carry3->shiftLeft(25));
$carry7 = $h7->addInt(1 << 24)->shiftRight(25);
$h8 = $h8->addInt64($carry7);
$h7 = $h7->subInt64($carry7->shiftLeft(25));
$carry4 = $h4->addInt(1 << 25)->shiftRight(26);
$h5 = $h5->addInt64($carry4);
$h4 = $h4->subInt64($carry4->shiftLeft(26));
$carry8 = $h8->addInt(1 << 25)->shiftRight(26);
$h9 = $h9->addInt64($carry8);
$h8 = $h8->subInt64($carry8->shiftLeft(26));
$carry9 = $h9->addInt(1 << 24)->shiftRight(25);
$h0 = $h0->addInt64($carry9->mulInt(19, 5));
$h9 = $h9->subInt64($carry9->shiftLeft(25));
$carry0 = $h0->addInt(1 << 25)->shiftRight(26);
$h1 = $h1->addInt64($carry0);
$h0 = $h0->subInt64($carry0->shiftLeft(26));
return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
$h0->toInt32(),
$h1->toInt32(),
$h2->toInt32(),
$h3->toInt32(),
$h4->toInt32(),
$h5->toInt32(),
$h6->toInt32(),
$h7->toInt32(),
$h8->toInt32(),
$h9->toInt32()
)
);
}
/**
* Get the negative values for each piece of the field element.
*
* h = -f
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedMethodCall
*/
public static function fe_neg(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
{
$h = new ParagonIE_Sodium_Core32_Curve25519_Fe();
for ($i = 0; $i < 10; ++$i) {
$h[$i] = $h[$i]->subInt32($f[$i]);
}
return $h;
}
/**
* Square a field element
*
* h = f * f
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedMethodCall
*/
public static function fe_sq(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
{
$f0 = $f[0]->toInt64();
$f1 = $f[1]->toInt64();
$f2 = $f[2]->toInt64();
$f3 = $f[3]->toInt64();
$f4 = $f[4]->toInt64();
$f5 = $f[5]->toInt64();
$f6 = $f[6]->toInt64();
$f7 = $f[7]->toInt64();
$f8 = $f[8]->toInt64();
$f9 = $f[9]->toInt64();
$f0_2 = $f0->shiftLeft(1);
$f1_2 = $f1->shiftLeft(1);
$f2_2 = $f2->shiftLeft(1);
$f3_2 = $f3->shiftLeft(1);
$f4_2 = $f4->shiftLeft(1);
$f5_2 = $f5->shiftLeft(1);
$f6_2 = $f6->shiftLeft(1);
$f7_2 = $f7->shiftLeft(1);
$f5_38 = $f5->mulInt(38, 6);
$f6_19 = $f6->mulInt(19, 5);
$f7_38 = $f7->mulInt(38, 6);
$f8_19 = $f8->mulInt(19, 5);
$f9_38 = $f9->mulInt(38, 6);
$f0f0 = $f0->mulInt64($f0, 28);
$f0f1_2 = $f0_2->mulInt64($f1, 28);
$f0f2_2 = $f0_2->mulInt64($f2, 28);
$f0f3_2 = $f0_2->mulInt64($f3, 28);
$f0f4_2 = $f0_2->mulInt64($f4, 28);
$f0f5_2 = $f0_2->mulInt64($f5, 28);
$f0f6_2 = $f0_2->mulInt64($f6, 28);
$f0f7_2 = $f0_2->mulInt64($f7, 28);
$f0f8_2 = $f0_2->mulInt64($f8, 28);
$f0f9_2 = $f0_2->mulInt64($f9, 28);
$f1f1_2 = $f1_2->mulInt64($f1, 28);
$f1f2_2 = $f1_2->mulInt64($f2, 28);
$f1f3_4 = $f1_2->mulInt64($f3_2, 28);
$f1f4_2 = $f1_2->mulInt64($f4, 28);
$f1f5_4 = $f1_2->mulInt64($f5_2, 30);
$f1f6_2 = $f1_2->mulInt64($f6, 28);
$f1f7_4 = $f1_2->mulInt64($f7_2, 28);
$f1f8_2 = $f1_2->mulInt64($f8, 28);
$f1f9_76 = $f9_38->mulInt64($f1_2, 30);
$f2f2 = $f2->mulInt64($f2, 28);
$f2f3_2 = $f2_2->mulInt64($f3, 28);
$f2f4_2 = $f2_2->mulInt64($f4, 28);
$f2f5_2 = $f2_2->mulInt64($f5, 28);
$f2f6_2 = $f2_2->mulInt64($f6, 28);
$f2f7_2 = $f2_2->mulInt64($f7, 28);
$f2f8_38 = $f8_19->mulInt64($f2_2, 30);
$f2f9_38 = $f9_38->mulInt64($f2, 30);
$f3f3_2 = $f3_2->mulInt64($f3, 28);
$f3f4_2 = $f3_2->mulInt64($f4, 28);
$f3f5_4 = $f3_2->mulInt64($f5_2, 30);
$f3f6_2 = $f3_2->mulInt64($f6, 28);
$f3f7_76 = $f7_38->mulInt64($f3_2, 30);
$f3f8_38 = $f8_19->mulInt64($f3_2, 30);
$f3f9_76 = $f9_38->mulInt64($f3_2, 30);
$f4f4 = $f4->mulInt64($f4, 28);
$f4f5_2 = $f4_2->mulInt64($f5, 28);
$f4f6_38 = $f6_19->mulInt64($f4_2, 30);
$f4f7_38 = $f7_38->mulInt64($f4, 30);
$f4f8_38 = $f8_19->mulInt64($f4_2, 30);
$f4f9_38 = $f9_38->mulInt64($f4, 30);
$f5f5_38 = $f5_38->mulInt64($f5, 30);
$f5f6_38 = $f6_19->mulInt64($f5_2, 30);
$f5f7_76 = $f7_38->mulInt64($f5_2, 30);
$f5f8_38 = $f8_19->mulInt64($f5_2, 30);
$f5f9_76 = $f9_38->mulInt64($f5_2, 30);
$f6f6_19 = $f6_19->mulInt64($f6, 30);
$f6f7_38 = $f7_38->mulInt64($f6, 30);
$f6f8_38 = $f8_19->mulInt64($f6_2, 30);
$f6f9_38 = $f9_38->mulInt64($f6, 30);
$f7f7_38 = $f7_38->mulInt64($f7, 28);
$f7f8_38 = $f8_19->mulInt64($f7_2, 30);
$f7f9_76 = $f9_38->mulInt64($f7_2, 30);
$f8f8_19 = $f8_19->mulInt64($f8, 30);
$f8f9_38 = $f9_38->mulInt64($f8, 30);
$f9f9_38 = $f9_38->mulInt64($f9, 28);
$h0 = $f0f0->addInt64($f1f9_76)->addInt64($f2f8_38)->addInt64($f3f7_76)->addInt64($f4f6_38)->addInt64($f5f5_38);
$h1 = $f0f1_2->addInt64($f2f9_38)->addInt64($f3f8_38)->addInt64($f4f7_38)->addInt64($f5f6_38);
$h2 = $f0f2_2->addInt64($f1f1_2)->addInt64($f3f9_76)->addInt64($f4f8_38)->addInt64($f5f7_76)->addInt64($f6f6_19);
$h3 = $f0f3_2->addInt64($f1f2_2)->addInt64($f4f9_38)->addInt64($f5f8_38)->addInt64($f6f7_38);
$h4 = $f0f4_2->addInt64($f1f3_4)->addInt64($f2f2)->addInt64($f5f9_76)->addInt64($f6f8_38)->addInt64($f7f7_38);
$h5 = $f0f5_2->addInt64($f1f4_2)->addInt64($f2f3_2)->addInt64($f6f9_38)->addInt64($f7f8_38);
$h6 = $f0f6_2->addInt64($f1f5_4)->addInt64($f2f4_2)->addInt64($f3f3_2)->addInt64($f7f9_76)->addInt64($f8f8_19);
$h7 = $f0f7_2->addInt64($f1f6_2)->addInt64($f2f5_2)->addInt64($f3f4_2)->addInt64($f8f9_38);
$h8 = $f0f8_2->addInt64($f1f7_4)->addInt64($f2f6_2)->addInt64($f3f5_4)->addInt64($f4f4)->addInt64($f9f9_38);
$h9 = $f0f9_2->addInt64($f1f8_2)->addInt64($f2f7_2)->addInt64($f3f6_2)->addInt64($f4f5_2);
/**
* @var ParagonIE_Sodium_Core32_Int64 $h0
* @var ParagonIE_Sodium_Core32_Int64 $h1
* @var ParagonIE_Sodium_Core32_Int64 $h2
* @var ParagonIE_Sodium_Core32_Int64 $h3
* @var ParagonIE_Sodium_Core32_Int64 $h4
* @var ParagonIE_Sodium_Core32_Int64 $h5
* @var ParagonIE_Sodium_Core32_Int64 $h6
* @var ParagonIE_Sodium_Core32_Int64 $h7
* @var ParagonIE_Sodium_Core32_Int64 $h8
* @var ParagonIE_Sodium_Core32_Int64 $h9
*/
$carry0 = $h0->addInt(1 << 25)->shiftRight(26);
$h1 = $h1->addInt64($carry0);
$h0 = $h0->subInt64($carry0->shiftLeft(26));
$carry4 = $h4->addInt(1 << 25)->shiftRight(26);
$h5 = $h5->addInt64($carry4);
$h4 = $h4->subInt64($carry4->shiftLeft(26));
$carry1 = $h1->addInt(1 << 24)->shiftRight(25);
$h2 = $h2->addInt64($carry1);
$h1 = $h1->subInt64($carry1->shiftLeft(25));
$carry5 = $h5->addInt(1 << 24)->shiftRight(25);
$h6 = $h6->addInt64($carry5);
$h5 = $h5->subInt64($carry5->shiftLeft(25));
$carry2 = $h2->addInt(1 << 25)->shiftRight(26);
$h3 = $h3->addInt64($carry2);
$h2 = $h2->subInt64($carry2->shiftLeft(26));
$carry6 = $h6->addInt(1 << 25)->shiftRight(26);
$h7 = $h7->addInt64($carry6);
$h6 = $h6->subInt64($carry6->shiftLeft(26));
$carry3 = $h3->addInt(1 << 24)->shiftRight(25);
$h4 = $h4->addInt64($carry3);
$h3 = $h3->subInt64($carry3->shiftLeft(25));
$carry7 = $h7->addInt(1 << 24)->shiftRight(25);
$h8 = $h8->addInt64($carry7);
$h7 = $h7->subInt64($carry7->shiftLeft(25));
$carry4 = $h4->addInt(1 << 25)->shiftRight(26);
$h5 = $h5->addInt64($carry4);
$h4 = $h4->subInt64($carry4->shiftLeft(26));
$carry8 = $h8->addInt(1 << 25)->shiftRight(26);
$h9 = $h9->addInt64($carry8);
$h8 = $h8->subInt64($carry8->shiftLeft(26));
$carry9 = $h9->addInt(1 << 24)->shiftRight(25);
$h0 = $h0->addInt64($carry9->mulInt(19, 5));
$h9 = $h9->subInt64($carry9->shiftLeft(25));
$carry0 = $h0->addInt(1 << 25)->shiftRight(26);
$h1 = $h1->addInt64($carry0);
$h0 = $h0->subInt64($carry0->shiftLeft(26));
return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
$h0->toInt32(),
$h1->toInt32(),
$h2->toInt32(),
$h3->toInt32(),
$h4->toInt32(),
$h5->toInt32(),
$h6->toInt32(),
$h7->toInt32(),
$h8->toInt32(),
$h9->toInt32()
)
);
}
/**
* Square and double a field element
*
* h = 2 * f * f
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedMethodCall
*/
public static function fe_sq2(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
{
$f0 = $f[0]->toInt64();
$f1 = $f[1]->toInt64();
$f2 = $f[2]->toInt64();
$f3 = $f[3]->toInt64();
$f4 = $f[4]->toInt64();
$f5 = $f[5]->toInt64();
$f6 = $f[6]->toInt64();
$f7 = $f[7]->toInt64();
$f8 = $f[8]->toInt64();
$f9 = $f[9]->toInt64();
$f0_2 = $f0->shiftLeft(1);
$f1_2 = $f1->shiftLeft(1);
$f2_2 = $f2->shiftLeft(1);
$f3_2 = $f3->shiftLeft(1);
$f4_2 = $f4->shiftLeft(1);
$f5_2 = $f5->shiftLeft(1);
$f6_2 = $f6->shiftLeft(1);
$f7_2 = $f7->shiftLeft(1);
$f5_38 = $f5->mulInt(38, 6); /* 1.959375*2^30 */
$f6_19 = $f6->mulInt(19, 5); /* 1.959375*2^30 */
$f7_38 = $f7->mulInt(38, 6); /* 1.959375*2^30 */
$f8_19 = $f8->mulInt(19, 5); /* 1.959375*2^30 */
$f9_38 = $f9->mulInt(38, 6); /* 1.959375*2^30 */
$f0f0 = $f0->mulInt64($f0, 28);
$f0f1_2 = $f0_2->mulInt64($f1, 28);
$f0f2_2 = $f0_2->mulInt64($f2, 28);
$f0f3_2 = $f0_2->mulInt64($f3, 28);
$f0f4_2 = $f0_2->mulInt64($f4, 28);
$f0f5_2 = $f0_2->mulInt64($f5, 28);
$f0f6_2 = $f0_2->mulInt64($f6, 28);
$f0f7_2 = $f0_2->mulInt64($f7, 28);
$f0f8_2 = $f0_2->mulInt64($f8, 28);
$f0f9_2 = $f0_2->mulInt64($f9, 28);
$f1f1_2 = $f1_2->mulInt64($f1, 28);
$f1f2_2 = $f1_2->mulInt64($f2, 28);
$f1f3_4 = $f1_2->mulInt64($f3_2, 29);
$f1f4_2 = $f1_2->mulInt64($f4, 28);
$f1f5_4 = $f1_2->mulInt64($f5_2, 29);
$f1f6_2 = $f1_2->mulInt64($f6, 28);
$f1f7_4 = $f1_2->mulInt64($f7_2, 29);
$f1f8_2 = $f1_2->mulInt64($f8, 28);
$f1f9_76 = $f9_38->mulInt64($f1_2, 29);
$f2f2 = $f2->mulInt64($f2, 28);
$f2f3_2 = $f2_2->mulInt64($f3, 28);
$f2f4_2 = $f2_2->mulInt64($f4, 28);
$f2f5_2 = $f2_2->mulInt64($f5, 28);
$f2f6_2 = $f2_2->mulInt64($f6, 28);
$f2f7_2 = $f2_2->mulInt64($f7, 28);
$f2f8_38 = $f8_19->mulInt64($f2_2, 29);
$f2f9_38 = $f9_38->mulInt64($f2, 29);
$f3f3_2 = $f3_2->mulInt64($f3, 28);
$f3f4_2 = $f3_2->mulInt64($f4, 28);
$f3f5_4 = $f3_2->mulInt64($f5_2, 28);
$f3f6_2 = $f3_2->mulInt64($f6, 28);
$f3f7_76 = $f7_38->mulInt64($f3_2, 29);
$f3f8_38 = $f8_19->mulInt64($f3_2, 29);
$f3f9_76 = $f9_38->mulInt64($f3_2, 29);
$f4f4 = $f4->mulInt64($f4, 28);
$f4f5_2 = $f4_2->mulInt64($f5, 28);
$f4f6_38 = $f6_19->mulInt64($f4_2, 29);
$f4f7_38 = $f7_38->mulInt64($f4, 29);
$f4f8_38 = $f8_19->mulInt64($f4_2, 29);
$f4f9_38 = $f9_38->mulInt64($f4, 29);
$f5f5_38 = $f5_38->mulInt64($f5, 29);
$f5f6_38 = $f6_19->mulInt64($f5_2, 29);
$f5f7_76 = $f7_38->mulInt64($f5_2, 29);
$f5f8_38 = $f8_19->mulInt64($f5_2, 29);
$f5f9_76 = $f9_38->mulInt64($f5_2, 29);
$f6f6_19 = $f6_19->mulInt64($f6, 29);
$f6f7_38 = $f7_38->mulInt64($f6, 29);
$f6f8_38 = $f8_19->mulInt64($f6_2, 29);
$f6f9_38 = $f9_38->mulInt64($f6, 29);
$f7f7_38 = $f7_38->mulInt64($f7, 29);
$f7f8_38 = $f8_19->mulInt64($f7_2, 29);
$f7f9_76 = $f9_38->mulInt64($f7_2, 29);
$f8f8_19 = $f8_19->mulInt64($f8, 29);
$f8f9_38 = $f9_38->mulInt64($f8, 29);
$f9f9_38 = $f9_38->mulInt64($f9, 29);
$h0 = $f0f0->addInt64($f1f9_76)->addInt64($f2f8_38)->addInt64($f3f7_76)->addInt64($f4f6_38)->addInt64($f5f5_38);
$h1 = $f0f1_2->addInt64($f2f9_38)->addInt64($f3f8_38)->addInt64($f4f7_38)->addInt64($f5f6_38);
$h2 = $f0f2_2->addInt64($f1f1_2)->addInt64($f3f9_76)->addInt64($f4f8_38)->addInt64($f5f7_76)->addInt64($f6f6_19);
$h3 = $f0f3_2->addInt64($f1f2_2)->addInt64($f4f9_38)->addInt64($f5f8_38)->addInt64($f6f7_38);
$h4 = $f0f4_2->addInt64($f1f3_4)->addInt64($f2f2)->addInt64($f5f9_76)->addInt64($f6f8_38)->addInt64($f7f7_38);
$h5 = $f0f5_2->addInt64($f1f4_2)->addInt64($f2f3_2)->addInt64($f6f9_38)->addInt64($f7f8_38);
$h6 = $f0f6_2->addInt64($f1f5_4)->addInt64($f2f4_2)->addInt64($f3f3_2)->addInt64($f7f9_76)->addInt64($f8f8_19);
$h7 = $f0f7_2->addInt64($f1f6_2)->addInt64($f2f5_2)->addInt64($f3f4_2)->addInt64($f8f9_38);
$h8 = $f0f8_2->addInt64($f1f7_4)->addInt64($f2f6_2)->addInt64($f3f5_4)->addInt64($f4f4)->addInt64($f9f9_38);
$h9 = $f0f9_2->addInt64($f1f8_2)->addInt64($f2f7_2)->addInt64($f3f6_2)->addInt64($f4f5_2);
/**
* @var ParagonIE_Sodium_Core32_Int64 $h0
* @var ParagonIE_Sodium_Core32_Int64 $h1
* @var ParagonIE_Sodium_Core32_Int64 $h2
* @var ParagonIE_Sodium_Core32_Int64 $h3
* @var ParagonIE_Sodium_Core32_Int64 $h4
* @var ParagonIE_Sodium_Core32_Int64 $h5
* @var ParagonIE_Sodium_Core32_Int64 $h6
* @var ParagonIE_Sodium_Core32_Int64 $h7
* @var ParagonIE_Sodium_Core32_Int64 $h8
* @var ParagonIE_Sodium_Core32_Int64 $h9
*/
$h0 = $h0->shiftLeft(1);
$h1 = $h1->shiftLeft(1);
$h2 = $h2->shiftLeft(1);
$h3 = $h3->shiftLeft(1);
$h4 = $h4->shiftLeft(1);
$h5 = $h5->shiftLeft(1);
$h6 = $h6->shiftLeft(1);
$h7 = $h7->shiftLeft(1);
$h8 = $h8->shiftLeft(1);
$h9 = $h9->shiftLeft(1);
$carry0 = $h0->addInt(1 << 25)->shiftRight(26);
$h1 = $h1->addInt64($carry0);
$h0 = $h0->subInt64($carry0->shiftLeft(26));
$carry4 = $h4->addInt(1 << 25)->shiftRight(26);
$h5 = $h5->addInt64($carry4);
$h4 = $h4->subInt64($carry4->shiftLeft(26));
$carry1 = $h1->addInt(1 << 24)->shiftRight(25);
$h2 = $h2->addInt64($carry1);
$h1 = $h1->subInt64($carry1->shiftLeft(25));
$carry5 = $h5->addInt(1 << 24)->shiftRight(25);
$h6 = $h6->addInt64($carry5);
$h5 = $h5->subInt64($carry5->shiftLeft(25));
$carry2 = $h2->addInt(1 << 25)->shiftRight(26);
$h3 = $h3->addInt64($carry2);
$h2 = $h2->subInt64($carry2->shiftLeft(26));
$carry6 = $h6->addInt(1 << 25)->shiftRight(26);
$h7 = $h7->addInt64($carry6);
$h6 = $h6->subInt64($carry6->shiftLeft(26));
$carry3 = $h3->addInt(1 << 24)->shiftRight(25);
$h4 = $h4->addInt64($carry3);
$h3 = $h3->subInt64($carry3->shiftLeft(25));
$carry7 = $h7->addInt(1 << 24)->shiftRight(25);
$h8 = $h8->addInt64($carry7);
$h7 = $h7->subInt64($carry7->shiftLeft(25));
$carry4 = $h4->addInt(1 << 25)->shiftRight(26);
$h5 = $h5->addInt64($carry4);
$h4 = $h4->subInt64($carry4->shiftLeft(26));
$carry8 = $h8->addInt(1 << 25)->shiftRight(26);
$h9 = $h9->addInt64($carry8);
$h8 = $h8->subInt64($carry8->shiftLeft(26));
$carry9 = $h9->addInt(1 << 24)->shiftRight(25);
$h0 = $h0->addInt64($carry9->mulInt(19, 5));
$h9 = $h9->subInt64($carry9->shiftLeft(25));
$carry0 = $h0->addInt(1 << 25)->shiftRight(26);
$h1 = $h1->addInt64($carry0);
$h0 = $h0->subInt64($carry0->shiftLeft(26));
return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
$h0->toInt32(),
$h1->toInt32(),
$h2->toInt32(),
$h3->toInt32(),
$h4->toInt32(),
$h5->toInt32(),
$h6->toInt32(),
$h7->toInt32(),
$h8->toInt32(),
$h9->toInt32()
)
);
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $Z
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
* @throws SodiumException
* @throws TypeError
*/
public static function fe_invert(ParagonIE_Sodium_Core32_Curve25519_Fe $Z)
{
$z = clone $Z;
$t0 = self::fe_sq($z);
$t1 = self::fe_sq($t0);
$t1 = self::fe_sq($t1);
$t1 = self::fe_mul($z, $t1);
$t0 = self::fe_mul($t0, $t1);
$t2 = self::fe_sq($t0);
$t1 = self::fe_mul($t1, $t2);
$t2 = self::fe_sq($t1);
for ($i = 1; $i < 5; ++$i) {
$t2 = self::fe_sq($t2);
}
$t1 = self::fe_mul($t2, $t1);
$t2 = self::fe_sq($t1);
for ($i = 1; $i < 10; ++$i) {
$t2 = self::fe_sq($t2);
}
$t2 = self::fe_mul($t2, $t1);
$t3 = self::fe_sq($t2);
for ($i = 1; $i < 20; ++$i) {
$t3 = self::fe_sq($t3);
}
$t2 = self::fe_mul($t3, $t2);
$t2 = self::fe_sq($t2);
for ($i = 1; $i < 10; ++$i) {
$t2 = self::fe_sq($t2);
}
$t1 = self::fe_mul($t2, $t1);
$t2 = self::fe_sq($t1);
for ($i = 1; $i < 50; ++$i) {
$t2 = self::fe_sq($t2);
}
$t2 = self::fe_mul($t2, $t1);
$t3 = self::fe_sq($t2);
for ($i = 1; $i < 100; ++$i) {
$t3 = self::fe_sq($t3);
}
$t2 = self::fe_mul($t3, $t2);
$t2 = self::fe_sq($t2);
for ($i = 1; $i < 50; ++$i) {
$t2 = self::fe_sq($t2);
}
$t1 = self::fe_mul($t2, $t1);
$t1 = self::fe_sq($t1);
for ($i = 1; $i < 5; ++$i) {
$t1 = self::fe_sq($t1);
}
return self::fe_mul($t1, $t0);
}
/**
* @internal You should not use this directly from another application
*
* @ref https://github.com/jedisct1/libsodium/blob/68564326e1e9dc57ef03746f85734232d20ca6fb/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1054-L1106
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $z
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
* @throws SodiumException
* @throws TypeError
*/
public static function fe_pow22523(ParagonIE_Sodium_Core32_Curve25519_Fe $z)
{
# fe_sq(t0, z);
# fe_sq(t1, t0);
# fe_sq(t1, t1);
# fe_mul(t1, z, t1);
# fe_mul(t0, t0, t1);
# fe_sq(t0, t0);
# fe_mul(t0, t1, t0);
# fe_sq(t1, t0);
$t0 = self::fe_sq($z);
$t1 = self::fe_sq($t0);
$t1 = self::fe_sq($t1);
$t1 = self::fe_mul($z, $t1);
$t0 = self::fe_mul($t0, $t1);
$t0 = self::fe_sq($t0);
$t0 = self::fe_mul($t1, $t0);
$t1 = self::fe_sq($t0);
# for (i = 1; i < 5; ++i) {
# fe_sq(t1, t1);
# }
for ($i = 1; $i < 5; ++$i) {
$t1 = self::fe_sq($t1);
}
# fe_mul(t0, t1, t0);
# fe_sq(t1, t0);
$t0 = self::fe_mul($t1, $t0);
$t1 = self::fe_sq($t0);
# for (i = 1; i < 10; ++i) {
# fe_sq(t1, t1);
# }
for ($i = 1; $i < 10; ++$i) {
$t1 = self::fe_sq($t1);
}
# fe_mul(t1, t1, t0);
# fe_sq(t2, t1);
$t1 = self::fe_mul($t1, $t0);
$t2 = self::fe_sq($t1);
# for (i = 1; i < 20; ++i) {
# fe_sq(t2, t2);
# }
for ($i = 1; $i < 20; ++$i) {
$t2 = self::fe_sq($t2);
}
# fe_mul(t1, t2, t1);
# fe_sq(t1, t1);
$t1 = self::fe_mul($t2, $t1);
$t1 = self::fe_sq($t1);
# for (i = 1; i < 10; ++i) {
# fe_sq(t1, t1);
# }
for ($i = 1; $i < 10; ++$i) {
$t1 = self::fe_sq($t1);
}
# fe_mul(t0, t1, t0);
# fe_sq(t1, t0);
$t0 = self::fe_mul($t1, $t0);
$t1 = self::fe_sq($t0);
# for (i = 1; i < 50; ++i) {
# fe_sq(t1, t1);
# }
for ($i = 1; $i < 50; ++$i) {
$t1 = self::fe_sq($t1);
}
# fe_mul(t1, t1, t0);
# fe_sq(t2, t1);
$t1 = self::fe_mul($t1, $t0);
$t2 = self::fe_sq($t1);
# for (i = 1; i < 100; ++i) {
# fe_sq(t2, t2);
# }
for ($i = 1; $i < 100; ++$i) {
$t2 = self::fe_sq($t2);
}
# fe_mul(t1, t2, t1);
# fe_sq(t1, t1);
$t1 = self::fe_mul($t2, $t1);
$t1 = self::fe_sq($t1);
# for (i = 1; i < 50; ++i) {
# fe_sq(t1, t1);
# }
for ($i = 1; $i < 50; ++$i) {
$t1 = self::fe_sq($t1);
}
# fe_mul(t0, t1, t0);
# fe_sq(t0, t0);
# fe_sq(t0, t0);
# fe_mul(out, t0, z);
$t0 = self::fe_mul($t1, $t0);
$t0 = self::fe_sq($t0);
$t0 = self::fe_sq($t0);
return self::fe_mul($t0, $z);
}
/**
* Subtract two field elements.
*
* h = f - g
*
* Preconditions:
* |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
* |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
*
* Postconditions:
* |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
* @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
* @return ParagonIE_Sodium_Core32_Curve25519_Fe
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedMethodCall
* @psalm-suppress MixedTypeCoercion
*/
public static function fe_sub(ParagonIE_Sodium_Core32_Curve25519_Fe $f, ParagonIE_Sodium_Core32_Curve25519_Fe $g)
{
return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
$f[0]->subInt32($g[0]),
$f[1]->subInt32($g[1]),
$f[2]->subInt32($g[2]),
$f[3]->subInt32($g[3]),
$f[4]->subInt32($g[4]),
$f[5]->subInt32($g[5]),
$f[6]->subInt32($g[6]),
$f[7]->subInt32($g[7]),
$f[8]->subInt32($g[8]),
$f[9]->subInt32($g[9])
)
);
}
/**
* Add two group elements.
*
* r = p + q
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
* @throws SodiumException
* @throws TypeError
*/
public static function ge_add(
ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
) {
$r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
$r->X = self::fe_add($p->Y, $p->X);
$r->Y = self::fe_sub($p->Y, $p->X);
$r->Z = self::fe_mul($r->X, $q->YplusX);
$r->Y = self::fe_mul($r->Y, $q->YminusX);
$r->T = self::fe_mul($q->T2d, $p->T);
$r->X = self::fe_mul($p->Z, $q->Z);
$t0 = self::fe_add($r->X, $r->X);
$r->X = self::fe_sub($r->Z, $r->Y);
$r->Y = self::fe_add($r->Z, $r->Y);
$r->Z = self::fe_add($t0, $r->T);
$r->T = self::fe_sub($t0, $r->T);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @ref https://github.com/jedisct1/libsodium/blob/157c4a80c13b117608aeae12178b2d38825f9f8f/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1185-L1215
* @param string $a
* @return array<int, mixed>
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArrayOffset
*/
public static function slide($a)
{
if (self::strlen($a) < 256) {
if (self::strlen($a) < 16) {
$a = str_pad($a, 256, '0', STR_PAD_RIGHT);
}
}
/** @var array<int, int> $r */
$r = array();
for ($i = 0; $i < 256; ++$i) {
$r[$i] = (int) (1 &
(
self::chrToInt($a[$i >> 3])
>>
($i & 7)
)
);
}
for ($i = 0;$i < 256;++$i) {
if ($r[$i]) {
for ($b = 1;$b <= 6 && $i + $b < 256;++$b) {
if ($r[$i + $b]) {
if ($r[$i] + ($r[$i + $b] << $b) <= 15) {
$r[$i] += $r[$i + $b] << $b;
$r[$i + $b] = 0;
} elseif ($r[$i] - ($r[$i + $b] << $b) >= -15) {
$r[$i] -= $r[$i + $b] << $b;
for ($k = $i + $b; $k < 256; ++$k) {
if (!$r[$k]) {
$r[$k] = 1;
break;
}
$r[$k] = 0;
}
} else {
break;
}
}
}
}
}
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @param string $s
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
* @throws SodiumException
* @throws TypeError
*/
public static function ge_frombytes_negate_vartime($s)
{
static $d = null;
if (!$d) {
$d = ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[0]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[1]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[2]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[3]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[4]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[5]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[6]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[7]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[8]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[9])
)
);
}
/** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d */
# fe_frombytes(h->Y,s);
# fe_1(h->Z);
$h = new ParagonIE_Sodium_Core32_Curve25519_Ge_P3(
self::fe_0(),
self::fe_frombytes($s),
self::fe_1()
);
# fe_sq(u,h->Y);
# fe_mul(v,u,d);
# fe_sub(u,u,h->Z); /* u = y^2-1 */
# fe_add(v,v,h->Z); /* v = dy^2+1 */
$u = self::fe_sq($h->Y);
/** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d */
$v = self::fe_mul($u, $d);
$u = self::fe_sub($u, $h->Z); /* u = y^2 - 1 */
$v = self::fe_add($v, $h->Z); /* v = dy^2 + 1 */
# fe_sq(v3,v);
# fe_mul(v3,v3,v); /* v3 = v^3 */
# fe_sq(h->X,v3);
# fe_mul(h->X,h->X,v);
# fe_mul(h->X,h->X,u); /* x = uv^7 */
$v3 = self::fe_sq($v);
$v3 = self::fe_mul($v3, $v); /* v3 = v^3 */
$h->X = self::fe_sq($v3);
$h->X = self::fe_mul($h->X, $v);
$h->X = self::fe_mul($h->X, $u); /* x = uv^7 */
# fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */
# fe_mul(h->X,h->X,v3);
# fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */
$h->X = self::fe_pow22523($h->X); /* x = (uv^7)^((q-5)/8) */
$h->X = self::fe_mul($h->X, $v3);
$h->X = self::fe_mul($h->X, $u); /* x = uv^3(uv^7)^((q-5)/8) */
# fe_sq(vxx,h->X);
# fe_mul(vxx,vxx,v);
# fe_sub(check,vxx,u); /* vx^2-u */
$vxx = self::fe_sq($h->X);
$vxx = self::fe_mul($vxx, $v);
$check = self::fe_sub($vxx, $u); /* vx^2 - u */
# if (fe_isnonzero(check)) {
# fe_add(check,vxx,u); /* vx^2+u */
# if (fe_isnonzero(check)) {
# return -1;
# }
# fe_mul(h->X,h->X,sqrtm1);
# }
if (self::fe_isnonzero($check)) {
$check = self::fe_add($vxx, $u); /* vx^2 + u */
if (self::fe_isnonzero($check)) {
throw new RangeException('Internal check failed.');
}
$h->X = self::fe_mul(
$h->X,
ParagonIE_Sodium_Core32_Curve25519_Fe::fromIntArray(self::$sqrtm1)
);
}
# if (fe_isnegative(h->X) == (s[31] >> 7)) {
# fe_neg(h->X,h->X);
# }
$i = self::chrToInt($s[31]);
if (self::fe_isnegative($h->X) === ($i >> 7)) {
$h->X = self::fe_neg($h->X);
}
# fe_mul(h->T,h->X,h->Y);
$h->T = self::fe_mul($h->X, $h->Y);
return $h;
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
* @throws SodiumException
* @throws TypeError
*/
public static function ge_madd(
ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R,
ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
) {
$r = clone $R;
$r->X = self::fe_add($p->Y, $p->X);
$r->Y = self::fe_sub($p->Y, $p->X);
$r->Z = self::fe_mul($r->X, $q->yplusx);
$r->Y = self::fe_mul($r->Y, $q->yminusx);
$r->T = self::fe_mul($q->xy2d, $p->T);
$t0 = self::fe_add(clone $p->Z, clone $p->Z);
$r->X = self::fe_sub($r->Z, $r->Y);
$r->Y = self::fe_add($r->Z, $r->Y);
$r->Z = self::fe_add($t0, $r->T);
$r->T = self::fe_sub($t0, $r->T);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
* @throws SodiumException
* @throws TypeError
*/
public static function ge_msub(
ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R,
ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
) {
$r = clone $R;
$r->X = self::fe_add($p->Y, $p->X);
$r->Y = self::fe_sub($p->Y, $p->X);
$r->Z = self::fe_mul($r->X, $q->yminusx);
$r->Y = self::fe_mul($r->Y, $q->yplusx);
$r->T = self::fe_mul($q->xy2d, $p->T);
$t0 = self::fe_add($p->Z, $p->Z);
$r->X = self::fe_sub($r->Z, $r->Y);
$r->Y = self::fe_add($r->Z, $r->Y);
$r->Z = self::fe_sub($t0, $r->T);
$r->T = self::fe_add($t0, $r->T);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
* @throws SodiumException
* @throws TypeError
*/
public static function ge_p1p1_to_p2(ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p)
{
$r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P2();
$r->X = self::fe_mul($p->X, $p->T);
$r->Y = self::fe_mul($p->Y, $p->Z);
$r->Z = self::fe_mul($p->Z, $p->T);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
* @throws SodiumException
* @throws TypeError
*/
public static function ge_p1p1_to_p3(ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p)
{
$r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P3();
$r->X = self::fe_mul($p->X, $p->T);
$r->Y = self::fe_mul($p->Y, $p->Z);
$r->Z = self::fe_mul($p->Z, $p->T);
$r->T = self::fe_mul($p->X, $p->Y);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
* @throws SodiumException
* @throws TypeError
*/
public static function ge_p2_0()
{
return new ParagonIE_Sodium_Core32_Curve25519_Ge_P2(
self::fe_0(),
self::fe_1(),
self::fe_1()
);
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $p
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
* @throws SodiumException
* @throws TypeError
*/
public static function ge_p2_dbl(ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $p)
{
$r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
$r->X = self::fe_sq($p->X);
$r->Z = self::fe_sq($p->Y);
$r->T = self::fe_sq2($p->Z);
$r->Y = self::fe_add($p->X, $p->Y);
$t0 = self::fe_sq($r->Y);
$r->Y = self::fe_add($r->Z, $r->X);
$r->Z = self::fe_sub($r->Z, $r->X);
$r->X = self::fe_sub($t0, $r->Y);
$r->T = self::fe_sub($r->T, $r->Z);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
* @throws SodiumException
* @throws TypeError
*/
public static function ge_p3_0()
{
return new ParagonIE_Sodium_Core32_Curve25519_Ge_P3(
self::fe_0(),
self::fe_1(),
self::fe_1(),
self::fe_0()
);
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_Cached
* @throws SodiumException
* @throws TypeError
*/
public static function ge_p3_to_cached(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p)
{
static $d2 = null;
if ($d2 === null) {
$d2 = ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[0]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[1]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[2]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[3]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[4]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[5]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[6]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[7]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[8]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[9])
)
);
}
/** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d2 */
$r = new ParagonIE_Sodium_Core32_Curve25519_Ge_Cached();
$r->YplusX = self::fe_add($p->Y, $p->X);
$r->YminusX = self::fe_sub($p->Y, $p->X);
$r->Z = self::fe_copy($p->Z);
$r->T2d = self::fe_mul($p->T, $d2);
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
*/
public static function ge_p3_to_p2(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p)
{
return new ParagonIE_Sodium_Core32_Curve25519_Ge_P2(
$p->X,
$p->Y,
$p->Z
);
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $h
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function ge_p3_tobytes(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $h)
{
$recip = self::fe_invert($h->Z);
$x = self::fe_mul($h->X, $recip);
$y = self::fe_mul($h->Y, $recip);
$s = self::fe_tobytes($y);
$s[31] = self::intToChr(
self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
);
return $s;
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
* @throws SodiumException
* @throws TypeError
*/
public static function ge_p3_dbl(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p)
{
$q = self::ge_p3_to_p2($p);
return self::ge_p2_dbl($q);
}
/**
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
* @throws SodiumException
* @throws TypeError
*/
public static function ge_precomp_0()
{
return new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
self::fe_1(),
self::fe_1(),
self::fe_0()
);
}
/**
* @internal You should not use this directly from another application
*
* @param int $b
* @param int $c
* @return int
* @psalm-suppress MixedReturnStatement
*/
public static function equal($b, $c)
{
$b0 = $b & 0xffff;
$b1 = ($b >> 16) & 0xffff;
$c0 = $c & 0xffff;
$c1 = ($c >> 16) & 0xffff;
$d0 = (($b0 ^ $c0) - 1) >> 31;
$d1 = (($b1 ^ $c1) - 1) >> 31;
return ($d0 & $d1) & 1;
}
/**
* @internal You should not use this directly from another application
*
* @param string|int $char
* @return int (1 = yes, 0 = no)
* @throws SodiumException
* @throws TypeError
*/
public static function negative($char)
{
if (is_int($char)) {
return $char < 0 ? 1 : 0;
}
/** @var string $char */
$x = self::chrToInt(self::substr($char, 0, 1));
return (int) ($x >> 31);
}
/**
* Conditional move
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $t
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $u
* @param int $b
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
* @throws SodiumException
* @throws TypeError
*/
public static function cmov(
ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $t,
ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $u,
$b
) {
if (!is_int($b)) {
throw new InvalidArgumentException('Expected an integer.');
}
return new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
self::fe_cmov($t->yplusx, $u->yplusx, $b),
self::fe_cmov($t->yminusx, $u->yminusx, $b),
self::fe_cmov($t->xy2d, $u->xy2d, $b)
);
}
/**
* @internal You should not use this directly from another application
*
* @param int $pos
* @param int $b
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArrayAccess
* @psalm-suppress MixedArrayOffset
* @psalm-suppress MixedArgument
*/
public static function ge_select($pos = 0, $b = 0)
{
static $base = null;
if ($base === null) {
$base = array();
foreach (self::$base as $i => $bas) {
for ($j = 0; $j < 8; ++$j) {
$base[$i][$j] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][0]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][1]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][2]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][3]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][4]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][5]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][6]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][7]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][8]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][9])
)
),
ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][0]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][1]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][2]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][3]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][4]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][5]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][6]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][7]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][8]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][9])
)
),
ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][0]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][1]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][2]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][3]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][4]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][5]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][6]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][7]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][8]),
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][9])
)
)
);
}
}
}
if (!is_int($pos)) {
throw new InvalidArgumentException('Position must be an integer');
}
if ($pos < 0 || $pos > 31) {
throw new RangeException('Position is out of range [0, 31]');
}
$bnegative = self::negative($b);
$babs = $b - (((-$bnegative) & $b) << 1);
$t = self::ge_precomp_0();
for ($i = 0; $i < 8; ++$i) {
$t = self::cmov(
$t,
$base[$pos][$i],
-self::equal($babs, $i + 1)
);
}
$minusT = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
self::fe_copy($t->yminusx),
self::fe_copy($t->yplusx),
self::fe_neg($t->xy2d)
);
return self::cmov($t, $minusT, -$bnegative);
}
/**
* Subtract two group elements.
*
* r = p - q
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
* @throws SodiumException
* @throws TypeError
*/
public static function ge_sub(
ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
) {
$r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
$r->X = self::fe_add($p->Y, $p->X);
$r->Y = self::fe_sub($p->Y, $p->X);
$r->Z = self::fe_mul($r->X, $q->YminusX);
$r->Y = self::fe_mul($r->Y, $q->YplusX);
$r->T = self::fe_mul($q->T2d, $p->T);
$r->X = self::fe_mul($p->Z, $q->Z);
$t0 = self::fe_add($r->X, $r->X);
$r->X = self::fe_sub($r->Z, $r->Y);
$r->Y = self::fe_add($r->Z, $r->Y);
$r->Z = self::fe_sub($t0, $r->T);
$r->T = self::fe_add($t0, $r->T);
return $r;
}
/**
* Convert a group element to a byte string.
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $h
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function ge_tobytes(ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $h)
{
$recip = self::fe_invert($h->Z);
$x = self::fe_mul($h->X, $recip);
$y = self::fe_mul($h->Y, $recip);
$s = self::fe_tobytes($y);
$s[31] = self::intToChr(
self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
);
return $s;
}
/**
* @internal You should not use this directly from another application
*
* @param string $a
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A
* @param string $b
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArrayAccess
*/
public static function ge_double_scalarmult_vartime(
$a,
ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A,
$b
) {
/** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai */
$Ai = array();
static $Bi = array();
/** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp> $Bi */
if (!$Bi) {
for ($i = 0; $i < 8; ++$i) {
$Bi[$i] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][0]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][1]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][2]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][3]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][4]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][5]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][6]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][7]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][8]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][9])
)
),
ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][0]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][1]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][2]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][3]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][4]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][5]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][6]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][7]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][8]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][9])
)
),
ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
array(
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][0]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][1]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][2]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][3]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][4]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][5]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][6]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][7]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][8]),
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][9])
)
)
);
}
}
for ($i = 0; $i < 8; ++$i) {
$Ai[$i] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Cached(
self::fe_0(),
self::fe_0(),
self::fe_0(),
self::fe_0()
);
}
/** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai */
# slide(aslide,a);
# slide(bslide,b);
/** @var array<int, int> $aslide */
$aslide = self::slide($a);
/** @var array<int, int> $bslide */
$bslide = self::slide($b);
# ge_p3_to_cached(&Ai[0],A);
# ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t);
$Ai[0] = self::ge_p3_to_cached($A);
$t = self::ge_p3_dbl($A);
$A2 = self::ge_p1p1_to_p3($t);
# ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u);
# ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u);
# ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u);
# ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u);
# ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u);
# ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u);
# ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u);
for ($i = 0; $i < 7; ++$i) {
$t = self::ge_add($A2, $Ai[$i]);
$u = self::ge_p1p1_to_p3($t);
$Ai[$i + 1] = self::ge_p3_to_cached($u);
}
# ge_p2_0(r);
$r = self::ge_p2_0();
# for (i = 255;i >= 0;--i) {
# if (aslide[i] || bslide[i]) break;
# }
$i = 255;
for (; $i >= 0; --$i) {
if ($aslide[$i] || $bslide[$i]) {
break;
}
}
# for (;i >= 0;--i) {
for (; $i >= 0; --$i) {
# ge_p2_dbl(&t,r);
$t = self::ge_p2_dbl($r);
# if (aslide[i] > 0) {
if ($aslide[$i] > 0) {
# ge_p1p1_to_p3(&u,&t);
# ge_add(&t,&u,&Ai[aslide[i]/2]);
$u = self::ge_p1p1_to_p3($t);
$t = self::ge_add(
$u,
$Ai[(int) floor($aslide[$i] / 2)]
);
# } else if (aslide[i] < 0) {
} elseif ($aslide[$i] < 0) {
# ge_p1p1_to_p3(&u,&t);
# ge_sub(&t,&u,&Ai[(-aslide[i])/2]);
$u = self::ge_p1p1_to_p3($t);
$t = self::ge_sub(
$u,
$Ai[(int) floor(-$aslide[$i] / 2)]
);
}
/** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp> $Bi */
# if (bslide[i] > 0) {
if ($bslide[$i] > 0) {
# ge_p1p1_to_p3(&u,&t);
# ge_madd(&t,&u,&Bi[bslide[i]/2]);
$u = self::ge_p1p1_to_p3($t);
/** @var int $index */
$index = (int) floor($bslide[$i] / 2);
/** @var ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $thisB */
$thisB = $Bi[$index];
$t = self::ge_madd($t, $u, $thisB);
# } else if (bslide[i] < 0) {
} elseif ($bslide[$i] < 0) {
# ge_p1p1_to_p3(&u,&t);
# ge_msub(&t,&u,&Bi[(-bslide[i])/2]);
$u = self::ge_p1p1_to_p3($t);
/** @var int $index */
$index = (int) floor(-$bslide[$i] / 2);
/** @var ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $thisB */
$thisB = $Bi[$index];
$t = self::ge_msub($t, $u, $thisB);
}
# ge_p1p1_to_p2(r,&t);
$r = self::ge_p1p1_to_p2($t);
}
return $r;
}
/**
* @internal You should not use this directly from another application
*
* @param string $a
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedOperand
* @throws SodiumException
* @throws TypeError
*/
public static function ge_scalarmult_base($a)
{
/** @var array<int, int> $e */
$e = array();
$r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
for ($i = 0; $i < 32; ++$i) {
/** @var int $dbl */
$dbl = (int) $i << 1;
$e[$dbl] = (int) self::chrToInt($a[$i]) & 15;
$e[$dbl + 1] = (int) (self::chrToInt($a[$i]) >> 4) & 15;
}
/** @var int $carry */
$carry = 0;
for ($i = 0; $i < 63; ++$i) {
$e[$i] += $carry;
$carry = $e[$i] + 8;
$carry >>= 4;
$e[$i] -= $carry << 4;
}
/** @var array<int, int> $e */
$e[63] += (int) $carry;
$h = self::ge_p3_0();
for ($i = 1; $i < 64; $i += 2) {
$t = self::ge_select((int) floor($i / 2), (int) $e[$i]);
$r = self::ge_madd($r, $h, $t);
$h = self::ge_p1p1_to_p3($r);
}
$r = self::ge_p3_dbl($h);
$s = self::ge_p1p1_to_p2($r);
$r = self::ge_p2_dbl($s);
$s = self::ge_p1p1_to_p2($r);
$r = self::ge_p2_dbl($s);
$s = self::ge_p1p1_to_p2($r);
$r = self::ge_p2_dbl($s);
$h = self::ge_p1p1_to_p3($r);
for ($i = 0; $i < 64; $i += 2) {
$t = self::ge_select($i >> 1, (int) $e[$i]);
$r = self::ge_madd($r, $h, $t);
$h = self::ge_p1p1_to_p3($r);
}
return $h;
}
/**
* Calculates (ab + c) mod l
* where l = 2^252 + 27742317777372353535851937790883648493
*
* @internal You should not use this directly from another application
*
* @param string $a
* @param string $b
* @param string $c
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function sc_muladd($a, $b, $c)
{
$a0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($a, 0, 3)));
$a1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5));
$a2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2));
$a3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7));
$a4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4));
$a5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1));
$a6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6));
$a7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3));
$a8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($a, 21, 3)));
$a9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5));
$a10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2));
$a11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($a, 28, 4)) >> 7));
$b0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($b, 0, 3)));
$b1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5));
$b2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2));
$b3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7));
$b4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4));
$b5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1));
$b6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6));
$b7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3));
$b8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($b, 21, 3)));
$b9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5));
$b10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2));
$b11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($b, 28, 4)) >> 7));
$c0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($c, 0, 3)));
$c1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 2, 4)) >> 5));
$c2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 5, 3)) >> 2));
$c3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 7, 4)) >> 7));
$c4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 10, 4)) >> 4));
$c5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 13, 3)) >> 1));
$c6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 15, 4)) >> 6));
$c7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 18, 3)) >> 3));
$c8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($c, 21, 3)));
$c9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 23, 4)) >> 5));
$c10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 26, 3)) >> 2));
$c11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($c, 28, 4)) >> 7));
/* Can't really avoid the pyramid here: */
/**
* @var ParagonIE_Sodium_Core32_Int64 $s0
* @var ParagonIE_Sodium_Core32_Int64 $s1
* @var ParagonIE_Sodium_Core32_Int64 $s2
* @var ParagonIE_Sodium_Core32_Int64 $s3
* @var ParagonIE_Sodium_Core32_Int64 $s4
* @var ParagonIE_Sodium_Core32_Int64 $s5
* @var ParagonIE_Sodium_Core32_Int64 $s6
* @var ParagonIE_Sodium_Core32_Int64 $s7
* @var ParagonIE_Sodium_Core32_Int64 $s8
* @var ParagonIE_Sodium_Core32_Int64 $s9
* @var ParagonIE_Sodium_Core32_Int64 $s10
* @var ParagonIE_Sodium_Core32_Int64 $s11
* @var ParagonIE_Sodium_Core32_Int64 $s12
* @var ParagonIE_Sodium_Core32_Int64 $s13
* @var ParagonIE_Sodium_Core32_Int64 $s14
* @var ParagonIE_Sodium_Core32_Int64 $s15
* @var ParagonIE_Sodium_Core32_Int64 $s16
* @var ParagonIE_Sodium_Core32_Int64 $s17
* @var ParagonIE_Sodium_Core32_Int64 $s18
* @var ParagonIE_Sodium_Core32_Int64 $s19
* @var ParagonIE_Sodium_Core32_Int64 $s20
* @var ParagonIE_Sodium_Core32_Int64 $s21
* @var ParagonIE_Sodium_Core32_Int64 $s22
* @var ParagonIE_Sodium_Core32_Int64 $s23
*/
$s0 = $c0->addInt64($a0->mulInt64($b0, 24));
$s1 = $c1->addInt64($a0->mulInt64($b1, 24))->addInt64($a1->mulInt64($b0, 24));
$s2 = $c2->addInt64($a0->mulInt64($b2, 24))->addInt64($a1->mulInt64($b1, 24))->addInt64($a2->mulInt64($b0, 24));
$s3 = $c3->addInt64($a0->mulInt64($b3, 24))->addInt64($a1->mulInt64($b2, 24))->addInt64($a2->mulInt64($b1, 24))
->addInt64($a3->mulInt64($b0, 24));
$s4 = $c4->addInt64($a0->mulInt64($b4, 24))->addInt64($a1->mulInt64($b3, 24))->addInt64($a2->mulInt64($b2, 24))
->addInt64($a3->mulInt64($b1, 24))->addInt64($a4->mulInt64($b0, 24));
$s5 = $c5->addInt64($a0->mulInt64($b5, 24))->addInt64($a1->mulInt64($b4, 24))->addInt64($a2->mulInt64($b3, 24))
->addInt64($a3->mulInt64($b2, 24))->addInt64($a4->mulInt64($b1, 24))->addInt64($a5->mulInt64($b0, 24));
$s6 = $c6->addInt64($a0->mulInt64($b6, 24))->addInt64($a1->mulInt64($b5, 24))->addInt64($a2->mulInt64($b4, 24))
->addInt64($a3->mulInt64($b3, 24))->addInt64($a4->mulInt64($b2, 24))->addInt64($a5->mulInt64($b1, 24))
->addInt64($a6->mulInt64($b0, 24));
$s7 = $c7->addInt64($a0->mulInt64($b7, 24))->addInt64($a1->mulInt64($b6, 24))->addInt64($a2->mulInt64($b5, 24))
->addInt64($a3->mulInt64($b4, 24))->addInt64($a4->mulInt64($b3, 24))->addInt64($a5->mulInt64($b2, 24))
->addInt64($a6->mulInt64($b1, 24))->addInt64($a7->mulInt64($b0, 24));
$s8 = $c8->addInt64($a0->mulInt64($b8, 24))->addInt64($a1->mulInt64($b7, 24))->addInt64($a2->mulInt64($b6, 24))
->addInt64($a3->mulInt64($b5, 24))->addInt64($a4->mulInt64($b4, 24))->addInt64($a5->mulInt64($b3, 24))
->addInt64($a6->mulInt64($b2, 24))->addInt64($a7->mulInt64($b1, 24))->addInt64($a8->mulInt64($b0, 24));
$s9 = $c9->addInt64($a0->mulInt64($b9, 24))->addInt64($a1->mulInt64($b8, 24))->addInt64($a2->mulInt64($b7, 24))
->addInt64($a3->mulInt64($b6, 24))->addInt64($a4->mulInt64($b5, 24))->addInt64($a5->mulInt64($b4, 24))
->addInt64($a6->mulInt64($b3, 24))->addInt64($a7->mulInt64($b2, 24))->addInt64($a8->mulInt64($b1, 24))
->addInt64($a9->mulInt64($b0, 24));
$s10 = $c10->addInt64($a0->mulInt64($b10, 24))->addInt64($a1->mulInt64($b9, 24))->addInt64($a2->mulInt64($b8, 24))
->addInt64($a3->mulInt64($b7, 24))->addInt64($a4->mulInt64($b6, 24))->addInt64($a5->mulInt64($b5, 24))
->addInt64($a6->mulInt64($b4, 24))->addInt64($a7->mulInt64($b3, 24))->addInt64($a8->mulInt64($b2, 24))
->addInt64($a9->mulInt64($b1, 24))->addInt64($a10->mulInt64($b0, 24));
$s11 = $c11->addInt64($a0->mulInt64($b11, 24))->addInt64($a1->mulInt64($b10, 24))->addInt64($a2->mulInt64($b9, 24))
->addInt64($a3->mulInt64($b8, 24))->addInt64($a4->mulInt64($b7, 24))->addInt64($a5->mulInt64($b6, 24))
->addInt64($a6->mulInt64($b5, 24))->addInt64($a7->mulInt64($b4, 24))->addInt64($a8->mulInt64($b3, 24))
->addInt64($a9->mulInt64($b2, 24))->addInt64($a10->mulInt64($b1, 24))->addInt64($a11->mulInt64($b0, 24));
$s12 = $a1->mulInt64($b11, 24)->addInt64($a2->mulInt64($b10, 24))->addInt64($a3->mulInt64($b9, 24))
->addInt64($a4->mulInt64($b8, 24))->addInt64($a5->mulInt64($b7, 24))->addInt64($a6->mulInt64($b6, 24))
->addInt64($a7->mulInt64($b5, 24))->addInt64($a8->mulInt64($b4, 24))->addInt64($a9->mulInt64($b3, 24))
->addInt64($a10->mulInt64($b2, 24))->addInt64($a11->mulInt64($b1, 24));
$s13 = $a2->mulInt64($b11, 24)->addInt64($a3->mulInt64($b10, 24))->addInt64($a4->mulInt64($b9, 24))
->addInt64($a5->mulInt64($b8, 24))->addInt64($a6->mulInt64($b7, 24))->addInt64($a7->mulInt64($b6, 24))
->addInt64($a8->mulInt64($b5, 24))->addInt64($a9->mulInt64($b4, 24))->addInt64($a10->mulInt64($b3, 24))
->addInt64($a11->mulInt64($b2, 24));
$s14 = $a3->mulInt64($b11, 24)->addInt64($a4->mulInt64($b10, 24))->addInt64($a5->mulInt64($b9, 24))
->addInt64($a6->mulInt64($b8, 24))->addInt64($a7->mulInt64($b7, 24))->addInt64($a8->mulInt64($b6, 24))
->addInt64($a9->mulInt64($b5, 24))->addInt64($a10->mulInt64($b4, 24))->addInt64($a11->mulInt64($b3, 24));
$s15 = $a4->mulInt64($b11, 24)->addInt64($a5->mulInt64($b10, 24))->addInt64($a6->mulInt64($b9, 24))
->addInt64($a7->mulInt64($b8, 24))->addInt64($a8->mulInt64($b7, 24))->addInt64($a9->mulInt64($b6, 24))
->addInt64($a10->mulInt64($b5, 24))->addInt64($a11->mulInt64($b4, 24));
$s16 = $a5->mulInt64($b11, 24)->addInt64($a6->mulInt64($b10, 24))->addInt64($a7->mulInt64($b9, 24))
->addInt64($a8->mulInt64($b8, 24))->addInt64($a9->mulInt64($b7, 24))->addInt64($a10->mulInt64($b6, 24))
->addInt64($a11->mulInt64($b5, 24));
$s17 = $a6->mulInt64($b11, 24)->addInt64($a7->mulInt64($b10, 24))->addInt64($a8->mulInt64($b9, 24))
->addInt64($a9->mulInt64($b8, 24))->addInt64($a10->mulInt64($b7, 24))->addInt64($a11->mulInt64($b6, 24));
$s18 = $a7->mulInt64($b11, 24)->addInt64($a8->mulInt64($b10, 24))->addInt64($a9->mulInt64($b9, 24))
->addInt64($a10->mulInt64($b8, 24))->addInt64($a11->mulInt64($b7, 24));
$s19 = $a8->mulInt64($b11, 24)->addInt64($a9->mulInt64($b10, 24))->addInt64($a10->mulInt64($b9, 24))
->addInt64($a11->mulInt64($b8, 24));
$s20 = $a9->mulInt64($b11, 24)->addInt64($a10->mulInt64($b10, 24))->addInt64($a11->mulInt64($b9, 24));
$s21 = $a10->mulInt64($b11, 24)->addInt64($a11->mulInt64($b10, 24));
$s22 = $a11->mulInt64($b11, 24);
$s23 = new ParagonIE_Sodium_Core32_Int64();
$carry0 = $s0->addInt(1 << 20)->shiftRight(21);
$s1 = $s1->addInt64($carry0);
$s0 = $s0->subInt64($carry0->shiftLeft(21));
$carry2 = $s2->addInt(1 << 20)->shiftRight(21);
$s3 = $s3->addInt64($carry2);
$s2 = $s2->subInt64($carry2->shiftLeft(21));
$carry4 = $s4->addInt(1 << 20)->shiftRight(21);
$s5 = $s5->addInt64($carry4);
$s4 = $s4->subInt64($carry4->shiftLeft(21));
$carry6 = $s6->addInt(1 << 20)->shiftRight(21);
$s7 = $s7->addInt64($carry6);
$s6 = $s6->subInt64($carry6->shiftLeft(21));
$carry8 = $s8->addInt(1 << 20)->shiftRight(21);
$s9 = $s9->addInt64($carry8);
$s8 = $s8->subInt64($carry8->shiftLeft(21));
$carry10 = $s10->addInt(1 << 20)->shiftRight(21);
$s11 = $s11->addInt64($carry10);
$s10 = $s10->subInt64($carry10->shiftLeft(21));
$carry12 = $s12->addInt(1 << 20)->shiftRight(21);
$s13 = $s13->addInt64($carry12);
$s12 = $s12->subInt64($carry12->shiftLeft(21));
$carry14 = $s14->addInt(1 << 20)->shiftRight(21);
$s15 = $s15->addInt64($carry14);
$s14 = $s14->subInt64($carry14->shiftLeft(21));
$carry16 = $s16->addInt(1 << 20)->shiftRight(21);
$s17 = $s17->addInt64($carry16);
$s16 = $s16->subInt64($carry16->shiftLeft(21));
$carry18 = $s18->addInt(1 << 20)->shiftRight(21);
$s19 = $s19->addInt64($carry18);
$s18 = $s18->subInt64($carry18->shiftLeft(21));
$carry20 = $s20->addInt(1 << 20)->shiftRight(21);
$s21 = $s21->addInt64($carry20);
$s20 = $s20->subInt64($carry20->shiftLeft(21));
$carry22 = $s22->addInt(1 << 20)->shiftRight(21);
$s23 = $s23->addInt64($carry22);
$s22 = $s22->subInt64($carry22->shiftLeft(21));
$carry1 = $s1->addInt(1 << 20)->shiftRight(21);
$s2 = $s2->addInt64($carry1);
$s1 = $s1->subInt64($carry1->shiftLeft(21));
$carry3 = $s3->addInt(1 << 20)->shiftRight(21);
$s4 = $s4->addInt64($carry3);
$s3 = $s3->subInt64($carry3->shiftLeft(21));
$carry5 = $s5->addInt(1 << 20)->shiftRight(21);
$s6 = $s6->addInt64($carry5);
$s5 = $s5->subInt64($carry5->shiftLeft(21));
$carry7 = $s7->addInt(1 << 20)->shiftRight(21);
$s8 = $s8->addInt64($carry7);
$s7 = $s7->subInt64($carry7->shiftLeft(21));
$carry9 = $s9->addInt(1 << 20)->shiftRight(21);
$s10 = $s10->addInt64($carry9);
$s9 = $s9->subInt64($carry9->shiftLeft(21));
$carry11 = $s11->addInt(1 << 20)->shiftRight(21);
$s12 = $s12->addInt64($carry11);
$s11 = $s11->subInt64($carry11->shiftLeft(21));
$carry13 = $s13->addInt(1 << 20)->shiftRight(21);
$s14 = $s14->addInt64($carry13);
$s13 = $s13->subInt64($carry13->shiftLeft(21));
$carry15 = $s15->addInt(1 << 20)->shiftRight(21);
$s16 = $s16->addInt64($carry15);
$s15 = $s15->subInt64($carry15->shiftLeft(21));
$carry17 = $s17->addInt(1 << 20)->shiftRight(21);
$s18 = $s18->addInt64($carry17);
$s17 = $s17->subInt64($carry17->shiftLeft(21));
$carry19 = $s19->addInt(1 << 20)->shiftRight(21);
$s20 = $s20->addInt64($carry19);
$s19 = $s19->subInt64($carry19->shiftLeft(21));
$carry21 = $s21->addInt(1 << 20)->shiftRight(21);
$s22 = $s22->addInt64($carry21);
$s21 = $s21->subInt64($carry21->shiftLeft(21));
$s11 = $s11->addInt64($s23->mulInt(666643, 20));
$s12 = $s12->addInt64($s23->mulInt(470296, 19));
$s13 = $s13->addInt64($s23->mulInt(654183, 20));
$s14 = $s14->subInt64($s23->mulInt(997805, 20));
$s15 = $s15->addInt64($s23->mulInt(136657, 18));
$s16 = $s16->subInt64($s23->mulInt(683901, 20));
$s10 = $s10->addInt64($s22->mulInt(666643, 20));
$s11 = $s11->addInt64($s22->mulInt(470296, 19));
$s12 = $s12->addInt64($s22->mulInt(654183, 20));
$s13 = $s13->subInt64($s22->mulInt(997805, 20));
$s14 = $s14->addInt64($s22->mulInt(136657, 18));
$s15 = $s15->subInt64($s22->mulInt(683901, 20));
$s9 = $s9->addInt64($s21->mulInt(666643, 20));
$s10 = $s10->addInt64($s21->mulInt(470296, 19));
$s11 = $s11->addInt64($s21->mulInt(654183, 20));
$s12 = $s12->subInt64($s21->mulInt(997805, 20));
$s13 = $s13->addInt64($s21->mulInt(136657, 18));
$s14 = $s14->subInt64($s21->mulInt(683901, 20));
$s8 = $s8->addInt64($s20->mulInt(666643, 20));
$s9 = $s9->addInt64($s20->mulInt(470296, 19));
$s10 = $s10->addInt64($s20->mulInt(654183, 20));
$s11 = $s11->subInt64($s20->mulInt(997805, 20));
$s12 = $s12->addInt64($s20->mulInt(136657, 18));
$s13 = $s13->subInt64($s20->mulInt(683901, 20));
$s7 = $s7->addInt64($s19->mulInt(666643, 20));
$s8 = $s8->addInt64($s19->mulInt(470296, 19));
$s9 = $s9->addInt64($s19->mulInt(654183, 20));
$s10 = $s10->subInt64($s19->mulInt(997805, 20));
$s11 = $s11->addInt64($s19->mulInt(136657, 18));
$s12 = $s12->subInt64($s19->mulInt(683901, 20));
$s6 = $s6->addInt64($s18->mulInt(666643, 20));
$s7 = $s7->addInt64($s18->mulInt(470296, 19));
$s8 = $s8->addInt64($s18->mulInt(654183, 20));
$s9 = $s9->subInt64($s18->mulInt(997805, 20));
$s10 = $s10->addInt64($s18->mulInt(136657, 18));
$s11 = $s11->subInt64($s18->mulInt(683901, 20));
$carry6 = $s6->addInt(1 << 20)->shiftRight(21);
$s7 = $s7->addInt64($carry6);
$s6 = $s6->subInt64($carry6->shiftLeft(21));
$carry8 = $s8->addInt(1 << 20)->shiftRight(21);
$s9 = $s9->addInt64($carry8);
$s8 = $s8->subInt64($carry8->shiftLeft(21));
$carry10 = $s10->addInt(1 << 20)->shiftRight(21);
$s11 = $s11->addInt64($carry10);
$s10 = $s10->subInt64($carry10->shiftLeft(21));
$carry12 = $s12->addInt(1 << 20)->shiftRight(21);
$s13 = $s13->addInt64($carry12);
$s12 = $s12->subInt64($carry12->shiftLeft(21));
$carry14 = $s14->addInt(1 << 20)->shiftRight(21);
$s15 = $s15->addInt64($carry14);
$s14 = $s14->subInt64($carry14->shiftLeft(21));
$carry16 = $s16->addInt(1 << 20)->shiftRight(21);
$s17 = $s17->addInt64($carry16);
$s16 = $s16->subInt64($carry16->shiftLeft(21));
$carry7 = $s7->addInt(1 << 20)->shiftRight(21);
$s8 = $s8->addInt64($carry7);
$s7 = $s7->subInt64($carry7->shiftLeft(21));
$carry9 = $s9->addInt(1 << 20)->shiftRight(21);
$s10 = $s10->addInt64($carry9);
$s9 = $s9->subInt64($carry9->shiftLeft(21));
$carry11 = $s11->addInt(1 << 20)->shiftRight(21);
$s12 = $s12->addInt64($carry11);
$s11 = $s11->subInt64($carry11->shiftLeft(21));
$carry13 = $s13->addInt(1 << 20)->shiftRight(21);
$s14 = $s14->addInt64($carry13);
$s13 = $s13->subInt64($carry13->shiftLeft(21));
$carry15 = $s15->addInt(1 << 20)->shiftRight(21);
$s16 = $s16->addInt64($carry15);
$s15 = $s15->subInt64($carry15->shiftLeft(21));
$s5 = $s5->addInt64($s17->mulInt(666643, 20));
$s6 = $s6->addInt64($s17->mulInt(470296, 19));
$s7 = $s7->addInt64($s17->mulInt(654183, 20));
$s8 = $s8->subInt64($s17->mulInt(997805, 20));
$s9 = $s9->addInt64($s17->mulInt(136657, 18));
$s10 = $s10->subInt64($s17->mulInt(683901, 20));
$s4 = $s4->addInt64($s16->mulInt(666643, 20));
$s5 = $s5->addInt64($s16->mulInt(470296, 19));
$s6 = $s6->addInt64($s16->mulInt(654183, 20));
$s7 = $s7->subInt64($s16->mulInt(997805, 20));
$s8 = $s8->addInt64($s16->mulInt(136657, 18));
$s9 = $s9->subInt64($s16->mulInt(683901, 20));
$s3 = $s3->addInt64($s15->mulInt(666643, 20));
$s4 = $s4->addInt64($s15->mulInt(470296, 19));
$s5 = $s5->addInt64($s15->mulInt(654183, 20));
$s6 = $s6->subInt64($s15->mulInt(997805, 20));
$s7 = $s7->addInt64($s15->mulInt(136657, 18));
$s8 = $s8->subInt64($s15->mulInt(683901, 20));
$s2 = $s2->addInt64($s14->mulInt(666643, 20));
$s3 = $s3->addInt64($s14->mulInt(470296, 19));
$s4 = $s4->addInt64($s14->mulInt(654183, 20));
$s5 = $s5->subInt64($s14->mulInt(997805, 20));
$s6 = $s6->addInt64($s14->mulInt(136657, 18));
$s7 = $s7->subInt64($s14->mulInt(683901, 20));
$s1 = $s1->addInt64($s13->mulInt(666643, 20));
$s2 = $s2->addInt64($s13->mulInt(470296, 19));
$s3 = $s3->addInt64($s13->mulInt(654183, 20));
$s4 = $s4->subInt64($s13->mulInt(997805, 20));
$s5 = $s5->addInt64($s13->mulInt(136657, 18));
$s6 = $s6->subInt64($s13->mulInt(683901, 20));
$s0 = $s0->addInt64($s12->mulInt(666643, 20));
$s1 = $s1->addInt64($s12->mulInt(470296, 19));
$s2 = $s2->addInt64($s12->mulInt(654183, 20));
$s3 = $s3->subInt64($s12->mulInt(997805, 20));
$s4 = $s4->addInt64($s12->mulInt(136657, 18));
$s5 = $s5->subInt64($s12->mulInt(683901, 20));
$s12 = new ParagonIE_Sodium_Core32_Int64();
$carry0 = $s0->addInt(1 << 20)->shiftRight(21);
$s1 = $s1->addInt64($carry0);
$s0 = $s0->subInt64($carry0->shiftLeft(21));
$carry2 = $s2->addInt(1 << 20)->shiftRight(21);
$s3 = $s3->addInt64($carry2);
$s2 = $s2->subInt64($carry2->shiftLeft(21));
$carry4 = $s4->addInt(1 << 20)->shiftRight(21);
$s5 = $s5->addInt64($carry4);
$s4 = $s4->subInt64($carry4->shiftLeft(21));
$carry6 = $s6->addInt(1 << 20)->shiftRight(21);
$s7 = $s7->addInt64($carry6);
$s6 = $s6->subInt64($carry6->shiftLeft(21));
$carry8 = $s8->addInt(1 << 20)->shiftRight(21);
$s9 = $s9->addInt64($carry8);
$s8 = $s8->subInt64($carry8->shiftLeft(21));
$carry10 = $s10->addInt(1 << 20)->shiftRight(21);
$s11 = $s11->addInt64($carry10);
$s10 = $s10->subInt64($carry10->shiftLeft(21));
$carry1 = $s1->addInt(1 << 20)->shiftRight(21);
$s2 = $s2->addInt64($carry1);
$s1 = $s1->subInt64($carry1->shiftLeft(21));
$carry3 = $s3->addInt(1 << 20)->shiftRight(21);
$s4 = $s4->addInt64($carry3);
$s3 = $s3->subInt64($carry3->shiftLeft(21));
$carry5 = $s5->addInt(1 << 20)->shiftRight(21);
$s6 = $s6->addInt64($carry5);
$s5 = $s5->subInt64($carry5->shiftLeft(21));
$carry7 = $s7->addInt(1 << 20)->shiftRight(21);
$s8 = $s8->addInt64($carry7);
$s7 = $s7->subInt64($carry7->shiftLeft(21));
$carry9 = $s9->addInt(1 << 20)->shiftRight(21);
$s10 = $s10->addInt64($carry9);
$s9 = $s9->subInt64($carry9->shiftLeft(21));
$carry11 = $s11->addInt(1 << 20)->shiftRight(21);
$s12 = $s12->addInt64($carry11);
$s11 = $s11->subInt64($carry11->shiftLeft(21));
$s0 = $s0->addInt64($s12->mulInt(666643, 20));
$s1 = $s1->addInt64($s12->mulInt(470296, 19));
$s2 = $s2->addInt64($s12->mulInt(654183, 20));
$s3 = $s3->subInt64($s12->mulInt(997805, 20));
$s4 = $s4->addInt64($s12->mulInt(136657, 18));
$s5 = $s5->subInt64($s12->mulInt(683901, 20));
$s12 = new ParagonIE_Sodium_Core32_Int64();
$carry0 = $s0->shiftRight(21);
$s1 = $s1->addInt64($carry0);
$s0 = $s0->subInt64($carry0->shiftLeft(21));
$carry1 = $s1->shiftRight(21);
$s2 = $s2->addInt64($carry1);
$s1 = $s1->subInt64($carry1->shiftLeft(21));
$carry2 = $s2->shiftRight(21);
$s3 = $s3->addInt64($carry2);
$s2 = $s2->subInt64($carry2->shiftLeft(21));
$carry3 = $s3->shiftRight(21);
$s4 = $s4->addInt64($carry3);
$s3 = $s3->subInt64($carry3->shiftLeft(21));
$carry4 = $s4->shiftRight(21);
$s5 = $s5->addInt64($carry4);
$s4 = $s4->subInt64($carry4->shiftLeft(21));
$carry5 = $s5->shiftRight(21);
$s6 = $s6->addInt64($carry5);
$s5 = $s5->subInt64($carry5->shiftLeft(21));
$carry6 = $s6->shiftRight(21);
$s7 = $s7->addInt64($carry6);
$s6 = $s6->subInt64($carry6->shiftLeft(21));
$carry7 = $s7->shiftRight(21);
$s8 = $s8->addInt64($carry7);
$s7 = $s7->subInt64($carry7->shiftLeft(21));
$carry8 = $s8->shiftRight(21);
$s9 = $s9->addInt64($carry8);
$s8 = $s8->subInt64($carry8->shiftLeft(21));
$carry9 = $s9->shiftRight(21);
$s10 = $s10->addInt64($carry9);
$s9 = $s9->subInt64($carry9->shiftLeft(21));
$carry10 = $s10->shiftRight(21);
$s11 = $s11->addInt64($carry10);
$s10 = $s10->subInt64($carry10->shiftLeft(21));
$carry11 = $s11->shiftRight(21);
$s12 = $s12->addInt64($carry11);
$s11 = $s11->subInt64($carry11->shiftLeft(21));
$s0 = $s0->addInt64($s12->mulInt(666643, 20));
$s1 = $s1->addInt64($s12->mulInt(470296, 19));
$s2 = $s2->addInt64($s12->mulInt(654183, 20));
$s3 = $s3->subInt64($s12->mulInt(997805, 20));
$s4 = $s4->addInt64($s12->mulInt(136657, 18));
$s5 = $s5->subInt64($s12->mulInt(683901, 20));
$carry0 = $s0->shiftRight(21);
$s1 = $s1->addInt64($carry0);
$s0 = $s0->subInt64($carry0->shiftLeft(21));
$carry1 = $s1->shiftRight(21);
$s2 = $s2->addInt64($carry1);
$s1 = $s1->subInt64($carry1->shiftLeft(21));
$carry2 = $s2->shiftRight(21);
$s3 = $s3->addInt64($carry2);
$s2 = $s2->subInt64($carry2->shiftLeft(21));
$carry3 = $s3->shiftRight(21);
$s4 = $s4->addInt64($carry3);
$s3 = $s3->subInt64($carry3->shiftLeft(21));
$carry4 = $s4->shiftRight(21);
$s5 = $s5->addInt64($carry4);
$s4 = $s4->subInt64($carry4->shiftLeft(21));
$carry5 = $s5->shiftRight(21);
$s6 = $s6->addInt64($carry5);
$s5 = $s5->subInt64($carry5->shiftLeft(21));
$carry6 = $s6->shiftRight(21);
$s7 = $s7->addInt64($carry6);
$s6 = $s6->subInt64($carry6->shiftLeft(21));
$carry7 = $s7->shiftRight(21);
$s8 = $s8->addInt64($carry7);
$s7 = $s7->subInt64($carry7->shiftLeft(21));
$carry8 = $s10->shiftRight(21);
$s9 = $s9->addInt64($carry8);
$s8 = $s8->subInt64($carry8->shiftLeft(21));
$carry9 = $s9->shiftRight(21);
$s10 = $s10->addInt64($carry9);
$s9 = $s9->subInt64($carry9->shiftLeft(21));
$carry10 = $s10->shiftRight(21);
$s11 = $s11->addInt64($carry10);
$s10 = $s10->subInt64($carry10->shiftLeft(21));
$S0 = $s0->toInt();
$S1 = $s1->toInt();
$S2 = $s2->toInt();
$S3 = $s3->toInt();
$S4 = $s4->toInt();
$S5 = $s5->toInt();
$S6 = $s6->toInt();
$S7 = $s7->toInt();
$S8 = $s8->toInt();
$S9 = $s9->toInt();
$S10 = $s10->toInt();
$S11 = $s11->toInt();
/**
* @var array<int, int>
*/
$arr = array(
(int) (0xff & ($S0 >> 0)),
(int) (0xff & ($S0 >> 8)),
(int) (0xff & (($S0 >> 16) | ($S1 << 5))),
(int) (0xff & ($S1 >> 3)),
(int) (0xff & ($S1 >> 11)),
(int) (0xff & (($S1 >> 19) | ($S2 << 2))),
(int) (0xff & ($S2 >> 6)),
(int) (0xff & (($S2 >> 14) | ($S3 << 7))),
(int) (0xff & ($S3 >> 1)),
(int) (0xff & ($S3 >> 9)),
(int) (0xff & (($S3 >> 17) | ($S4 << 4))),
(int) (0xff & ($S4 >> 4)),
(int) (0xff & ($S4 >> 12)),
(int) (0xff & (($S4 >> 20) | ($S5 << 1))),
(int) (0xff & ($S5 >> 7)),
(int) (0xff & (($S5 >> 15) | ($S6 << 6))),
(int) (0xff & ($S6 >> 2)),
(int) (0xff & ($S6 >> 10)),
(int) (0xff & (($S6 >> 18) | ($S7 << 3))),
(int) (0xff & ($S7 >> 5)),
(int) (0xff & ($S7 >> 13)),
(int) (0xff & ($S8 >> 0)),
(int) (0xff & ($S8 >> 8)),
(int) (0xff & (($S8 >> 16) | ($S9 << 5))),
(int) (0xff & ($S9 >> 3)),
(int) (0xff & ($S9 >> 11)),
(int) (0xff & (($S9 >> 19) | ($S10 << 2))),
(int) (0xff & ($S10 >> 6)),
(int) (0xff & (($S10 >> 14) | ($S11 << 7))),
(int) (0xff & ($S11 >> 1)),
(int) (0xff & ($S11 >> 9)),
(int) (0xff & ($S11 >> 17))
);
return self::intArrayToString($arr);
}
/**
* @internal You should not use this directly from another application
*
* @param string $s
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function sc_reduce($s)
{
/**
* @var ParagonIE_Sodium_Core32_Int64 $s0
* @var ParagonIE_Sodium_Core32_Int64 $s1
* @var ParagonIE_Sodium_Core32_Int64 $s2
* @var ParagonIE_Sodium_Core32_Int64 $s3
* @var ParagonIE_Sodium_Core32_Int64 $s4
* @var ParagonIE_Sodium_Core32_Int64 $s5
* @var ParagonIE_Sodium_Core32_Int64 $s6
* @var ParagonIE_Sodium_Core32_Int64 $s7
* @var ParagonIE_Sodium_Core32_Int64 $s8
* @var ParagonIE_Sodium_Core32_Int64 $s9
* @var ParagonIE_Sodium_Core32_Int64 $s10
* @var ParagonIE_Sodium_Core32_Int64 $s11
* @var ParagonIE_Sodium_Core32_Int64 $s12
* @var ParagonIE_Sodium_Core32_Int64 $s13
* @var ParagonIE_Sodium_Core32_Int64 $s14
* @var ParagonIE_Sodium_Core32_Int64 $s15
* @var ParagonIE_Sodium_Core32_Int64 $s16
* @var ParagonIE_Sodium_Core32_Int64 $s17
* @var ParagonIE_Sodium_Core32_Int64 $s18
* @var ParagonIE_Sodium_Core32_Int64 $s19
* @var ParagonIE_Sodium_Core32_Int64 $s20
* @var ParagonIE_Sodium_Core32_Int64 $s21
* @var ParagonIE_Sodium_Core32_Int64 $s22
* @var ParagonIE_Sodium_Core32_Int64 $s23
*/
$s0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($s, 0, 3)));
$s1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 2, 4)) >> 5));
$s2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 5, 3)) >> 2));
$s3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 7, 4)) >> 7));
$s4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 10, 4)) >> 4));
$s5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 13, 3)) >> 1));
$s6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 15, 4)) >> 6));
$s7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 18, 4)) >> 3));
$s8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($s, 21, 3)));
$s9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 23, 4)) >> 5));
$s10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 26, 3)) >> 2));
$s11 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 28, 4)) >> 7));
$s12 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 31, 4)) >> 4));
$s13 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 34, 3)) >> 1));
$s14 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 36, 4)) >> 6));
$s15 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 39, 4)) >> 3));
$s16 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($s, 42, 3)));
$s17 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 44, 4)) >> 5));
$s18 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 47, 3)) >> 2));
$s19 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 49, 4)) >> 7));
$s20 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 52, 4)) >> 4));
$s21 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 55, 3)) >> 1));
$s22 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 57, 4)) >> 6));
$s23 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($s, 60, 4)) >> 3));
$s11 = $s11->addInt64($s23->mulInt(666643, 20));
$s12 = $s12->addInt64($s23->mulInt(470296, 19));
$s13 = $s13->addInt64($s23->mulInt(654183, 20));
$s14 = $s14->subInt64($s23->mulInt(997805, 20));
$s15 = $s15->addInt64($s23->mulInt(136657, 18));
$s16 = $s16->subInt64($s23->mulInt(683901, 20));
$s10 = $s10->addInt64($s22->mulInt(666643, 20));
$s11 = $s11->addInt64($s22->mulInt(470296, 19));
$s12 = $s12->addInt64($s22->mulInt(654183, 20));
$s13 = $s13->subInt64($s22->mulInt(997805, 20));
$s14 = $s14->addInt64($s22->mulInt(136657, 18));
$s15 = $s15->subInt64($s22->mulInt(683901, 20));
$s9 = $s9->addInt64($s21->mulInt(666643, 20));
$s10 = $s10->addInt64($s21->mulInt(470296, 19));
$s11 = $s11->addInt64($s21->mulInt(654183, 20));
$s12 = $s12->subInt64($s21->mulInt(997805, 20));
$s13 = $s13->addInt64($s21->mulInt(136657, 18));
$s14 = $s14->subInt64($s21->mulInt(683901, 20));
$s8 = $s8->addInt64($s20->mulInt(666643, 20));
$s9 = $s9->addInt64($s20->mulInt(470296, 19));
$s10 = $s10->addInt64($s20->mulInt(654183, 20));
$s11 = $s11->subInt64($s20->mulInt(997805, 20));
$s12 = $s12->addInt64($s20->mulInt(136657, 18));
$s13 = $s13->subInt64($s20->mulInt(683901, 20));
$s7 = $s7->addInt64($s19->mulInt(666643, 20));
$s8 = $s8->addInt64($s19->mulInt(470296, 19));
$s9 = $s9->addInt64($s19->mulInt(654183, 20));
$s10 = $s10->subInt64($s19->mulInt(997805, 20));
$s11 = $s11->addInt64($s19->mulInt(136657, 18));
$s12 = $s12->subInt64($s19->mulInt(683901, 20));
$s6 = $s6->addInt64($s18->mulInt(666643, 20));
$s7 = $s7->addInt64($s18->mulInt(470296, 19));
$s8 = $s8->addInt64($s18->mulInt(654183, 20));
$s9 = $s9->subInt64($s18->mulInt(997805, 20));
$s10 = $s10->addInt64($s18->mulInt(136657, 18));
$s11 = $s11->subInt64($s18->mulInt(683901, 20));
$carry6 = $s6->addInt(1 << 20)->shiftRight(21);
$s7 = $s7->addInt64($carry6);
$s6 = $s6->subInt64($carry6->shiftLeft(21));
$carry8 = $s8->addInt(1 << 20)->shiftRight(21);
$s9 = $s9->addInt64($carry8);
$s8 = $s8->subInt64($carry8->shiftLeft(21));
$carry10 = $s10->addInt(1 << 20)->shiftRight(21);
$s11 = $s11->addInt64($carry10);
$s10 = $s10->subInt64($carry10->shiftLeft(21));
$carry12 = $s12->addInt(1 << 20)->shiftRight(21);
$s13 = $s13->addInt64($carry12);
$s12 = $s12->subInt64($carry12->shiftLeft(21));
$carry14 = $s14->addInt(1 << 20)->shiftRight(21);
$s15 = $s15->addInt64($carry14);
$s14 = $s14->subInt64($carry14->shiftLeft(21));
$carry16 = $s16->addInt(1 << 20)->shiftRight(21);
$s17 = $s17->addInt64($carry16);
$s16 = $s16->subInt64($carry16->shiftLeft(21));
$carry7 = $s7->addInt(1 << 20)->shiftRight(21);
$s8 = $s8->addInt64($carry7);
$s7 = $s7->subInt64($carry7->shiftLeft(21));
$carry9 = $s9->addInt(1 << 20)->shiftRight(21);
$s10 = $s10->addInt64($carry9);
$s9 = $s9->subInt64($carry9->shiftLeft(21));
$carry11 = $s11->addInt(1 << 20)->shiftRight(21);
$s12 = $s12->addInt64($carry11);
$s11 = $s11->subInt64($carry11->shiftLeft(21));
$carry13 = $s13->addInt(1 << 20)->shiftRight(21);
$s14 = $s14->addInt64($carry13);
$s13 = $s13->subInt64($carry13->shiftLeft(21));
$carry15 = $s15->addInt(1 << 20)->shiftRight(21);
$s16 = $s16->addInt64($carry15);
$s15 = $s15->subInt64($carry15->shiftLeft(21));
$s5 = $s5->addInt64($s17->mulInt(666643, 20));
$s6 = $s6->addInt64($s17->mulInt(470296, 19));
$s7 = $s7->addInt64($s17->mulInt(654183, 20));
$s8 = $s8->subInt64($s17->mulInt(997805, 20));
$s9 = $s9->addInt64($s17->mulInt(136657, 18));
$s10 = $s10->subInt64($s17->mulInt(683901, 20));
$s4 = $s4->addInt64($s16->mulInt(666643, 20));
$s5 = $s5->addInt64($s16->mulInt(470296, 19));
$s6 = $s6->addInt64($s16->mulInt(654183, 20));
$s7 = $s7->subInt64($s16->mulInt(997805, 20));
$s8 = $s8->addInt64($s16->mulInt(136657, 18));
$s9 = $s9->subInt64($s16->mulInt(683901, 20));
$s3 = $s3->addInt64($s15->mulInt(666643, 20));
$s4 = $s4->addInt64($s15->mulInt(470296, 19));
$s5 = $s5->addInt64($s15->mulInt(654183, 20));
$s6 = $s6->subInt64($s15->mulInt(997805, 20));
$s7 = $s7->addInt64($s15->mulInt(136657, 18));
$s8 = $s8->subInt64($s15->mulInt(683901, 20));
$s2 = $s2->addInt64($s14->mulInt(666643, 20));
$s3 = $s3->addInt64($s14->mulInt(470296, 19));
$s4 = $s4->addInt64($s14->mulInt(654183, 20));
$s5 = $s5->subInt64($s14->mulInt(997805, 20));
$s6 = $s6->addInt64($s14->mulInt(136657, 18));
$s7 = $s7->subInt64($s14->mulInt(683901, 20));
$s1 = $s1->addInt64($s13->mulInt(666643, 20));
$s2 = $s2->addInt64($s13->mulInt(470296, 19));
$s3 = $s3->addInt64($s13->mulInt(654183, 20));
$s4 = $s4->subInt64($s13->mulInt(997805, 20));
$s5 = $s5->addInt64($s13->mulInt(136657, 18));
$s6 = $s6->subInt64($s13->mulInt(683901, 20));
$s0 = $s0->addInt64($s12->mulInt(666643, 20));
$s1 = $s1->addInt64($s12->mulInt(470296, 19));
$s2 = $s2->addInt64($s12->mulInt(654183, 20));
$s3 = $s3->subInt64($s12->mulInt(997805, 20));
$s4 = $s4->addInt64($s12->mulInt(136657, 18));
$s5 = $s5->subInt64($s12->mulInt(683901, 20));
$s12 = new ParagonIE_Sodium_Core32_Int64();
$carry0 = $s0->addInt(1 << 20)->shiftRight(21);
$s1 = $s1->addInt64($carry0);
$s0 = $s0->subInt64($carry0->shiftLeft(21));
$carry2 = $s2->addInt(1 << 20)->shiftRight(21);
$s3 = $s3->addInt64($carry2);
$s2 = $s2->subInt64($carry2->shiftLeft(21));
$carry4 = $s4->addInt(1 << 20)->shiftRight(21);
$s5 = $s5->addInt64($carry4);
$s4 = $s4->subInt64($carry4->shiftLeft(21));
$carry6 = $s6->addInt(1 << 20)->shiftRight(21);
$s7 = $s7->addInt64($carry6);
$s6 = $s6->subInt64($carry6->shiftLeft(21));
$carry8 = $s8->addInt(1 << 20)->shiftRight(21);
$s9 = $s9->addInt64($carry8);
$s8 = $s8->subInt64($carry8->shiftLeft(21));
$carry10 = $s10->addInt(1 << 20)->shiftRight(21);
$s11 = $s11->addInt64($carry10);
$s10 = $s10->subInt64($carry10->shiftLeft(21));
$carry1 = $s1->addInt(1 << 20)->shiftRight(21);
$s2 = $s2->addInt64($carry1);
$s1 = $s1->subInt64($carry1->shiftLeft(21));
$carry3 = $s3->addInt(1 << 20)->shiftRight(21);
$s4 = $s4->addInt64($carry3);
$s3 = $s3->subInt64($carry3->shiftLeft(21));
$carry5 = $s5->addInt(1 << 20)->shiftRight(21);
$s6 = $s6->addInt64($carry5);
$s5 = $s5->subInt64($carry5->shiftLeft(21));
$carry7 = $s7->addInt(1 << 20)->shiftRight(21);
$s8 = $s8->addInt64($carry7);
$s7 = $s7->subInt64($carry7->shiftLeft(21));
$carry9 = $s9->addInt(1 << 20)->shiftRight(21);
$s10 = $s10->addInt64($carry9);
$s9 = $s9->subInt64($carry9->shiftLeft(21));
$carry11 = $s11->addInt(1 << 20)->shiftRight(21);
$s12 = $s12->addInt64($carry11);
$s11 = $s11->subInt64($carry11->shiftLeft(21));
$s0 = $s0->addInt64($s12->mulInt(666643, 20));
$s1 = $s1->addInt64($s12->mulInt(470296, 19));
$s2 = $s2->addInt64($s12->mulInt(654183, 20));
$s3 = $s3->subInt64($s12->mulInt(997805, 20));
$s4 = $s4->addInt64($s12->mulInt(136657, 18));
$s5 = $s5->subInt64($s12->mulInt(683901, 20));
$s12 = new ParagonIE_Sodium_Core32_Int64();
$carry0 = $s0->shiftRight(21);
$s1 = $s1->addInt64($carry0);
$s0 = $s0->subInt64($carry0->shiftLeft(21));
$carry1 = $s1->shiftRight(21);
$s2 = $s2->addInt64($carry1);
$s1 = $s1->subInt64($carry1->shiftLeft(21));
$carry2 = $s2->shiftRight(21);
$s3 = $s3->addInt64($carry2);
$s2 = $s2->subInt64($carry2->shiftLeft(21));
$carry3 = $s3->shiftRight(21);
$s4 = $s4->addInt64($carry3);
$s3 = $s3->subInt64($carry3->shiftLeft(21));
$carry4 = $s4->shiftRight(21);
$s5 = $s5->addInt64($carry4);
$s4 = $s4->subInt64($carry4->shiftLeft(21));
$carry5 = $s5->shiftRight(21);
$s6 = $s6->addInt64($carry5);
$s5 = $s5->subInt64($carry5->shiftLeft(21));
$carry6 = $s6->shiftRight(21);
$s7 = $s7->addInt64($carry6);
$s6 = $s6->subInt64($carry6->shiftLeft(21));
$carry7 = $s7->shiftRight(21);
$s8 = $s8->addInt64($carry7);
$s7 = $s7->subInt64($carry7->shiftLeft(21));
$carry8 = $s8->shiftRight(21);
$s9 = $s9->addInt64($carry8);
$s8 = $s8->subInt64($carry8->shiftLeft(21));
$carry9 = $s9->shiftRight(21);
$s10 = $s10->addInt64($carry9);
$s9 = $s9->subInt64($carry9->shiftLeft(21));
$carry10 = $s10->shiftRight(21);
$s11 = $s11->addInt64($carry10);
$s10 = $s10->subInt64($carry10->shiftLeft(21));
$carry11 = $s11->shiftRight(21);
$s12 = $s12->addInt64($carry11);
$s11 = $s11->subInt64($carry11->shiftLeft(21));
$s0 = $s0->addInt64($s12->mulInt(666643, 20));
$s1 = $s1->addInt64($s12->mulInt(470296, 19));
$s2 = $s2->addInt64($s12->mulInt(654183, 20));
$s3 = $s3->subInt64($s12->mulInt(997805, 20));
$s4 = $s4->addInt64($s12->mulInt(136657, 18));
$s5 = $s5->subInt64($s12->mulInt(683901, 20));
$carry0 = $s0->shiftRight(21);
$s1 = $s1->addInt64($carry0);
$s0 = $s0->subInt64($carry0->shiftLeft(21));
$carry1 = $s1->shiftRight(21);
$s2 = $s2->addInt64($carry1);
$s1 = $s1->subInt64($carry1->shiftLeft(21));
$carry2 = $s2->shiftRight(21);
$s3 = $s3->addInt64($carry2);
$s2 = $s2->subInt64($carry2->shiftLeft(21));
$carry3 = $s3->shiftRight(21);
$s4 = $s4->addInt64($carry3);
$s3 = $s3->subInt64($carry3->shiftLeft(21));
$carry4 = $s4->shiftRight(21);
$s5 = $s5->addInt64($carry4);
$s4 = $s4->subInt64($carry4->shiftLeft(21));
$carry5 = $s5->shiftRight(21);
$s6 = $s6->addInt64($carry5);
$s5 = $s5->subInt64($carry5->shiftLeft(21));
$carry6 = $s6->shiftRight(21);
$s7 = $s7->addInt64($carry6);
$s6 = $s6->subInt64($carry6->shiftLeft(21));
$carry7 = $s7->shiftRight(21);
$s8 = $s8->addInt64($carry7);
$s7 = $s7->subInt64($carry7->shiftLeft(21));
$carry8 = $s8->shiftRight(21);
$s9 = $s9->addInt64($carry8);
$s8 = $s8->subInt64($carry8->shiftLeft(21));
$carry9 = $s9->shiftRight(21);
$s10 = $s10->addInt64($carry9);
$s9 = $s9->subInt64($carry9->shiftLeft(21));
$carry10 = $s10->shiftRight(21);
$s11 = $s11->addInt64($carry10);
$s10 = $s10->subInt64($carry10->shiftLeft(21));
$S0 = $s0->toInt32()->toInt();
$S1 = $s1->toInt32()->toInt();
$S2 = $s2->toInt32()->toInt();
$S3 = $s3->toInt32()->toInt();
$S4 = $s4->toInt32()->toInt();
$S5 = $s5->toInt32()->toInt();
$S6 = $s6->toInt32()->toInt();
$S7 = $s7->toInt32()->toInt();
$S8 = $s8->toInt32()->toInt();
$S9 = $s9->toInt32()->toInt();
$S10 = $s10->toInt32()->toInt();
$S11 = $s11->toInt32()->toInt();
/**
* @var array<int, int>
*/
$arr = array(
(int) ($S0 >> 0),
(int) ($S0 >> 8),
(int) (($S0 >> 16) | ($S1 << 5)),
(int) ($S1 >> 3),
(int) ($S1 >> 11),
(int) (($S1 >> 19) | ($S2 << 2)),
(int) ($S2 >> 6),
(int) (($S2 >> 14) | ($S3 << 7)),
(int) ($S3 >> 1),
(int) ($S3 >> 9),
(int) (($S3 >> 17) | ($S4 << 4)),
(int) ($S4 >> 4),
(int) ($S4 >> 12),
(int) (($S4 >> 20) | ($S5 << 1)),
(int) ($S5 >> 7),
(int) (($S5 >> 15) | ($S6 << 6)),
(int) ($S6 >> 2),
(int) ($S6 >> 10),
(int) (($S6 >> 18) | ($S7 << 3)),
(int) ($S7 >> 5),
(int) ($S7 >> 13),
(int) ($S8 >> 0),
(int) ($S8 >> 8),
(int) (($S8 >> 16) | ($S9 << 5)),
(int) ($S9 >> 3),
(int) ($S9 >> 11),
(int) (($S9 >> 19) | ($S10 << 2)),
(int) ($S10 >> 6),
(int) (($S10 >> 14) | ($S11 << 7)),
(int) ($S11 >> 1),
(int) ($S11 >> 9),
(int) $S11 >> 17
);
return self::intArrayToString($arr);
}
/**
* multiply by the order of the main subgroup l = 2^252+27742317777372353535851937790883648493
*
* @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A
* @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
* @throws SodiumException
* @throws TypeError
*/
public static function ge_mul_l(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A)
{
$aslide = array(
13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0,
0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0,
0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0,
0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1,
0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0,
0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
);
/** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai size 8 */
$Ai = array();
# ge_p3_to_cached(&Ai[0], A);
$Ai[0] = self::ge_p3_to_cached($A);
# ge_p3_dbl(&t, A);
$t = self::ge_p3_dbl($A);
# ge_p1p1_to_p3(&A2, &t);
$A2 = self::ge_p1p1_to_p3($t);
for ($i = 1; $i < 8; ++$i) {
# ge_add(&t, &A2, &Ai[0]);
$t = self::ge_add($A2, $Ai[$i - 1]);
# ge_p1p1_to_p3(&u, &t);
$u = self::ge_p1p1_to_p3($t);
# ge_p3_to_cached(&Ai[i], &u);
$Ai[$i] = self::ge_p3_to_cached($u);
}
$r = self::ge_p3_0();
for ($i = 252; $i >= 0; --$i) {
$t = self::ge_p3_dbl($r);
if ($aslide[$i] > 0) {
# ge_p1p1_to_p3(&u, &t);
$u = self::ge_p1p1_to_p3($t);
# ge_add(&t, &u, &Ai[aslide[i] / 2]);
$t = self::ge_add($u, $Ai[(int)($aslide[$i] / 2)]);
} elseif ($aslide[$i] < 0) {
# ge_p1p1_to_p3(&u, &t);
$u = self::ge_p1p1_to_p3($t);
# ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
$t = self::ge_sub($u, $Ai[(int)(-$aslide[$i] / 2)]);
}
}
# ge_p1p1_to_p3(r, &t);
return self::ge_p1p1_to_p3($t);
}
}
Core32/Salsa20.php 0000644 00000026362 15051413232 0007524 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core32_Salsa20', false)) {
return;
}
/**
* Class ParagonIE_Sodium_Core32_Salsa20
*/
abstract class ParagonIE_Sodium_Core32_Salsa20 extends ParagonIE_Sodium_Core32_Util
{
const ROUNDS = 20;
/**
* Calculate an salsa20 hash of a single block
*
* @internal You should not use this directly from another application
*
* @param string $in
* @param string $k
* @param string|null $c
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function core_salsa20($in, $k, $c = null)
{
/**
* @var ParagonIE_Sodium_Core32_Int32 $x0
* @var ParagonIE_Sodium_Core32_Int32 $x1
* @var ParagonIE_Sodium_Core32_Int32 $x2
* @var ParagonIE_Sodium_Core32_Int32 $x3
* @var ParagonIE_Sodium_Core32_Int32 $x4
* @var ParagonIE_Sodium_Core32_Int32 $x5
* @var ParagonIE_Sodium_Core32_Int32 $x6
* @var ParagonIE_Sodium_Core32_Int32 $x7
* @var ParagonIE_Sodium_Core32_Int32 $x8
* @var ParagonIE_Sodium_Core32_Int32 $x9
* @var ParagonIE_Sodium_Core32_Int32 $x10
* @var ParagonIE_Sodium_Core32_Int32 $x11
* @var ParagonIE_Sodium_Core32_Int32 $x12
* @var ParagonIE_Sodium_Core32_Int32 $x13
* @var ParagonIE_Sodium_Core32_Int32 $x14
* @var ParagonIE_Sodium_Core32_Int32 $x15
* @var ParagonIE_Sodium_Core32_Int32 $j0
* @var ParagonIE_Sodium_Core32_Int32 $j1
* @var ParagonIE_Sodium_Core32_Int32 $j2
* @var ParagonIE_Sodium_Core32_Int32 $j3
* @var ParagonIE_Sodium_Core32_Int32 $j4
* @var ParagonIE_Sodium_Core32_Int32 $j5
* @var ParagonIE_Sodium_Core32_Int32 $j6
* @var ParagonIE_Sodium_Core32_Int32 $j7
* @var ParagonIE_Sodium_Core32_Int32 $j8
* @var ParagonIE_Sodium_Core32_Int32 $j9
* @var ParagonIE_Sodium_Core32_Int32 $j10
* @var ParagonIE_Sodium_Core32_Int32 $j11
* @var ParagonIE_Sodium_Core32_Int32 $j12
* @var ParagonIE_Sodium_Core32_Int32 $j13
* @var ParagonIE_Sodium_Core32_Int32 $j14
* @var ParagonIE_Sodium_Core32_Int32 $j15
*/
if (self::strlen($k) < 32) {
throw new RangeException('Key must be 32 bytes long');
}
if ($c === null) {
$x0 = new ParagonIE_Sodium_Core32_Int32(array(0x6170, 0x7865));
$x5 = new ParagonIE_Sodium_Core32_Int32(array(0x3320, 0x646e));
$x10 = new ParagonIE_Sodium_Core32_Int32(array(0x7962, 0x2d32));
$x15 = new ParagonIE_Sodium_Core32_Int32(array(0x6b20, 0x6574));
} else {
$x0 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 0, 4));
$x5 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 4, 4));
$x10 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 8, 4));
$x15 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 12, 4));
}
$x1 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 0, 4));
$x2 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 4, 4));
$x3 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 8, 4));
$x4 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 12, 4));
$x6 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 0, 4));
$x7 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 4, 4));
$x8 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 8, 4));
$x9 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 12, 4));
$x11 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 16, 4));
$x12 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 20, 4));
$x13 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 24, 4));
$x14 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 28, 4));
$j0 = clone $x0;
$j1 = clone $x1;
$j2 = clone $x2;
$j3 = clone $x3;
$j4 = clone $x4;
$j5 = clone $x5;
$j6 = clone $x6;
$j7 = clone $x7;
$j8 = clone $x8;
$j9 = clone $x9;
$j10 = clone $x10;
$j11 = clone $x11;
$j12 = clone $x12;
$j13 = clone $x13;
$j14 = clone $x14;
$j15 = clone $x15;
for ($i = self::ROUNDS; $i > 0; $i -= 2) {
$x4 = $x4->xorInt32($x0->addInt32($x12)->rotateLeft(7));
$x8 = $x8->xorInt32($x4->addInt32($x0)->rotateLeft(9));
$x12 = $x12->xorInt32($x8->addInt32($x4)->rotateLeft(13));
$x0 = $x0->xorInt32($x12->addInt32($x8)->rotateLeft(18));
$x9 = $x9->xorInt32($x5->addInt32($x1)->rotateLeft(7));
$x13 = $x13->xorInt32($x9->addInt32($x5)->rotateLeft(9));
$x1 = $x1->xorInt32($x13->addInt32($x9)->rotateLeft(13));
$x5 = $x5->xorInt32($x1->addInt32($x13)->rotateLeft(18));
$x14 = $x14->xorInt32($x10->addInt32($x6)->rotateLeft(7));
$x2 = $x2->xorInt32($x14->addInt32($x10)->rotateLeft(9));
$x6 = $x6->xorInt32($x2->addInt32($x14)->rotateLeft(13));
$x10 = $x10->xorInt32($x6->addInt32($x2)->rotateLeft(18));
$x3 = $x3->xorInt32($x15->addInt32($x11)->rotateLeft(7));
$x7 = $x7->xorInt32($x3->addInt32($x15)->rotateLeft(9));
$x11 = $x11->xorInt32($x7->addInt32($x3)->rotateLeft(13));
$x15 = $x15->xorInt32($x11->addInt32($x7)->rotateLeft(18));
$x1 = $x1->xorInt32($x0->addInt32($x3)->rotateLeft(7));
$x2 = $x2->xorInt32($x1->addInt32($x0)->rotateLeft(9));
$x3 = $x3->xorInt32($x2->addInt32($x1)->rotateLeft(13));
$x0 = $x0->xorInt32($x3->addInt32($x2)->rotateLeft(18));
$x6 = $x6->xorInt32($x5->addInt32($x4)->rotateLeft(7));
$x7 = $x7->xorInt32($x6->addInt32($x5)->rotateLeft(9));
$x4 = $x4->xorInt32($x7->addInt32($x6)->rotateLeft(13));
$x5 = $x5->xorInt32($x4->addInt32($x7)->rotateLeft(18));
$x11 = $x11->xorInt32($x10->addInt32($x9)->rotateLeft(7));
$x8 = $x8->xorInt32($x11->addInt32($x10)->rotateLeft(9));
$x9 = $x9->xorInt32($x8->addInt32($x11)->rotateLeft(13));
$x10 = $x10->xorInt32($x9->addInt32($x8)->rotateLeft(18));
$x12 = $x12->xorInt32($x15->addInt32($x14)->rotateLeft(7));
$x13 = $x13->xorInt32($x12->addInt32($x15)->rotateLeft(9));
$x14 = $x14->xorInt32($x13->addInt32($x12)->rotateLeft(13));
$x15 = $x15->xorInt32($x14->addInt32($x13)->rotateLeft(18));
}
$x0 = $x0->addInt32($j0);
$x1 = $x1->addInt32($j1);
$x2 = $x2->addInt32($j2);
$x3 = $x3->addInt32($j3);
$x4 = $x4->addInt32($j4);
$x5 = $x5->addInt32($j5);
$x6 = $x6->addInt32($j6);
$x7 = $x7->addInt32($j7);
$x8 = $x8->addInt32($j8);
$x9 = $x9->addInt32($j9);
$x10 = $x10->addInt32($j10);
$x11 = $x11->addInt32($j11);
$x12 = $x12->addInt32($j12);
$x13 = $x13->addInt32($j13);
$x14 = $x14->addInt32($j14);
$x15 = $x15->addInt32($j15);
return $x0->toReverseString() .
$x1->toReverseString() .
$x2->toReverseString() .
$x3->toReverseString() .
$x4->toReverseString() .
$x5->toReverseString() .
$x6->toReverseString() .
$x7->toReverseString() .
$x8->toReverseString() .
$x9->toReverseString() .
$x10->toReverseString() .
$x11->toReverseString() .
$x12->toReverseString() .
$x13->toReverseString() .
$x14->toReverseString() .
$x15->toReverseString();
}
/**
* @internal You should not use this directly from another application
*
* @param int $len
* @param string $nonce
* @param string $key
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function salsa20($len, $nonce, $key)
{
if (self::strlen($key) !== 32) {
throw new RangeException('Key must be 32 bytes long');
}
$kcopy = '' . $key;
$in = self::substr($nonce, 0, 8) . str_repeat("\0", 8);
$c = '';
while ($len >= 64) {
$c .= self::core_salsa20($in, $kcopy, null);
$u = 1;
// Internal counter.
for ($i = 8; $i < 16; ++$i) {
$u += self::chrToInt($in[$i]);
$in[$i] = self::intToChr($u & 0xff);
$u >>= 8;
}
$len -= 64;
}
if ($len > 0) {
$c .= self::substr(
self::core_salsa20($in, $kcopy, null),
0,
$len
);
}
try {
ParagonIE_Sodium_Compat::memzero($kcopy);
} catch (SodiumException $ex) {
$kcopy = null;
}
return $c;
}
/**
* @internal You should not use this directly from another application
*
* @param string $m
* @param string $n
* @param int $ic
* @param string $k
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function salsa20_xor_ic($m, $n, $ic, $k)
{
$mlen = self::strlen($m);
if ($mlen < 1) {
return '';
}
$kcopy = self::substr($k, 0, 32);
$in = self::substr($n, 0, 8);
// Initialize the counter
$in .= ParagonIE_Sodium_Core32_Util::store64_le($ic);
$c = '';
while ($mlen >= 64) {
$block = self::core_salsa20($in, $kcopy, null);
$c .= self::xorStrings(
self::substr($m, 0, 64),
self::substr($block, 0, 64)
);
$u = 1;
for ($i = 8; $i < 16; ++$i) {
$u += self::chrToInt($in[$i]);
$in[$i] = self::intToChr($u & 0xff);
$u >>= 8;
}
$mlen -= 64;
$m = self::substr($m, 64);
}
if ($mlen) {
$block = self::core_salsa20($in, $kcopy, null);
$c .= self::xorStrings(
self::substr($m, 0, $mlen),
self::substr($block, 0, $mlen)
);
}
try {
ParagonIE_Sodium_Compat::memzero($block);
ParagonIE_Sodium_Compat::memzero($kcopy);
} catch (SodiumException $ex) {
$block = null;
$kcopy = null;
}
return $c;
}
/**
* @internal You should not use this directly from another application
*
* @param string $message
* @param string $nonce
* @param string $key
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function salsa20_xor($message, $nonce, $key)
{
return self::xorStrings(
$message,
self::salsa20(
self::strlen($message),
$nonce,
$key
)
);
}
}
Core32/Poly1305.php 0000644 00000003062 15051413232 0007543 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core32_Poly1305', false)) {
return;
}
/**
* Class ParagonIE_Sodium_Core32_Poly1305
*/
abstract class ParagonIE_Sodium_Core32_Poly1305 extends ParagonIE_Sodium_Core32_Util
{
const BLOCK_SIZE = 16;
/**
* @internal You should not use this directly from another application
*
* @param string $m
* @param string $key
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function onetimeauth($m, $key)
{
if (self::strlen($key) < 32) {
throw new InvalidArgumentException(
'Key must be 32 bytes long.'
);
}
$state = new ParagonIE_Sodium_Core32_Poly1305_State(
self::substr($key, 0, 32)
);
return $state
->update($m)
->finish();
}
/**
* @internal You should not use this directly from another application
*
* @param string $mac
* @param string $m
* @param string $key
* @return bool
* @throws SodiumException
* @throws TypeError
*/
public static function onetimeauth_verify($mac, $m, $key)
{
if (self::strlen($key) < 32) {
throw new InvalidArgumentException(
'Key must be 32 bytes long.'
);
}
$state = new ParagonIE_Sodium_Core32_Poly1305_State(
self::substr($key, 0, 32)
);
$calc = $state
->update($m)
->finish();
return self::verify_16($calc, $mac);
}
}
Core32/XChaCha20.php 0000644 00000004626 15051413233 0007720 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core32_XChaCha20', false)) {
return;
}
/**
* Class ParagonIE_Sodium_Core32_XChaCha20
*/
class ParagonIE_Sodium_Core32_XChaCha20 extends ParagonIE_Sodium_Core32_HChaCha20
{
/**
* @internal You should not use this directly from another application
*
* @param int $len
* @param string $nonce
* @param string $key
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function stream($len = 64, $nonce = '', $key = '')
{
if (self::strlen($nonce) !== 24) {
throw new SodiumException('Nonce must be 24 bytes long');
}
return self::encryptBytes(
new ParagonIE_Sodium_Core32_ChaCha20_Ctx(
self::hChaCha20(
self::substr($nonce, 0, 16),
$key
),
self::substr($nonce, 16, 8)
),
str_repeat("\x00", $len)
);
}
/**
* @internal You should not use this directly from another application
*
* @param string $message
* @param string $nonce
* @param string $key
* @param string $ic
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function streamXorIc($message, $nonce = '', $key = '', $ic = '')
{
if (self::strlen($nonce) !== 24) {
throw new SodiumException('Nonce must be 24 bytes long');
}
return self::encryptBytes(
new ParagonIE_Sodium_Core32_ChaCha20_Ctx(
self::hChaCha20(self::substr($nonce, 0, 16), $key),
self::substr($nonce, 16, 8),
$ic
),
$message
);
}
/**
* @internal You should not use this directly from another application
*
* @param string $message
* @param string $nonce
* @param string $key
* @param string $ic
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '')
{
return self::encryptBytes(
new ParagonIE_Sodium_Core32_ChaCha20_IetfCtx(
self::hChaCha20(self::substr($nonce, 0, 16), $key),
"\x00\x00\x00\x00" . self::substr($nonce, 16, 8),
$ic
),
$message
);
}
}
Core32/Poly1305/State.php 0000644 00000037135 15051413233 0010634 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core32_Poly1305_State', false)) {
return;
}
/**
* Class ParagonIE_Sodium_Core32_Poly1305_State
*/
class ParagonIE_Sodium_Core32_Poly1305_State extends ParagonIE_Sodium_Core32_Util
{
/**
* @var array<int, int>
*/
protected $buffer = array();
/**
* @var bool
*/
protected $final = false;
/**
* @var array<int, ParagonIE_Sodium_Core32_Int32>
*/
public $h;
/**
* @var int
*/
protected $leftover = 0;
/**
* @var array<int, ParagonIE_Sodium_Core32_Int32>
*/
public $r;
/**
* @var array<int, ParagonIE_Sodium_Core32_Int64>
*/
public $pad;
/**
* ParagonIE_Sodium_Core32_Poly1305_State constructor.
*
* @internal You should not use this directly from another application
*
* @param string $key
* @throws InvalidArgumentException
* @throws SodiumException
* @throws TypeError
*/
public function __construct($key = '')
{
if (self::strlen($key) < 32) {
throw new InvalidArgumentException(
'Poly1305 requires a 32-byte key'
);
}
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
$this->r = array(
// st->r[0] = ...
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4))
->setUnsignedInt(true)
->mask(0x3ffffff),
// st->r[1] = ...
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 3, 4))
->setUnsignedInt(true)
->shiftRight(2)
->mask(0x3ffff03),
// st->r[2] = ...
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 6, 4))
->setUnsignedInt(true)
->shiftRight(4)
->mask(0x3ffc0ff),
// st->r[3] = ...
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 9, 4))
->setUnsignedInt(true)
->shiftRight(6)
->mask(0x3f03fff),
// st->r[4] = ...
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12, 4))
->setUnsignedInt(true)
->shiftRight(8)
->mask(0x00fffff)
);
/* h = 0 */
$this->h = array(
new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
new ParagonIE_Sodium_Core32_Int32(array(0, 0), true)
);
/* save pad for later */
$this->pad = array(
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16, 4))
->setUnsignedInt(true)->toInt64(),
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20, 4))
->setUnsignedInt(true)->toInt64(),
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24, 4))
->setUnsignedInt(true)->toInt64(),
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28, 4))
->setUnsignedInt(true)->toInt64(),
);
$this->leftover = 0;
$this->final = false;
}
/**
* @internal You should not use this directly from another application
*
* @param string $message
* @return self
* @throws SodiumException
* @throws TypeError
*/
public function update($message = '')
{
$bytes = self::strlen($message);
/* handle leftover */
if ($this->leftover) {
/** @var int $want */
$want = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - $this->leftover;
if ($want > $bytes) {
$want = $bytes;
}
for ($i = 0; $i < $want; ++$i) {
$mi = self::chrToInt($message[$i]);
$this->buffer[$this->leftover + $i] = $mi;
}
// We snip off the leftmost bytes.
$message = self::substr($message, $want);
$bytes = self::strlen($message);
$this->leftover += $want;
if ($this->leftover < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
// We still don't have enough to run $this->blocks()
return $this;
}
$this->blocks(
self::intArrayToString($this->buffer),
ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
);
$this->leftover = 0;
}
/* process full blocks */
if ($bytes >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
/** @var int $want */
$want = $bytes & ~(ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - 1);
if ($want >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
/** @var string $block */
$block = self::substr($message, 0, $want);
if (self::strlen($block) >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
$this->blocks($block, $want);
$message = self::substr($message, $want);
$bytes = self::strlen($message);
}
}
}
/* store leftover */
if ($bytes) {
for ($i = 0; $i < $bytes; ++$i) {
$mi = self::chrToInt($message[$i]);
$this->buffer[$this->leftover + $i] = $mi;
}
$this->leftover = (int) $this->leftover + $bytes;
}
return $this;
}
/**
* @internal You should not use this directly from another application
*
* @param string $message
* @param int $bytes
* @return self
* @throws SodiumException
* @throws TypeError
*/
public function blocks($message, $bytes)
{
if (self::strlen($message) < 16) {
$message = str_pad($message, 16, "\x00", STR_PAD_RIGHT);
}
$hibit = ParagonIE_Sodium_Core32_Int32::fromInt((int) ($this->final ? 0 : 1 << 24)); /* 1 << 128 */
$hibit->setUnsignedInt(true);
$zero = new ParagonIE_Sodium_Core32_Int64(array(0, 0, 0, 0), true);
/**
* @var ParagonIE_Sodium_Core32_Int64 $d0
* @var ParagonIE_Sodium_Core32_Int64 $d1
* @var ParagonIE_Sodium_Core32_Int64 $d2
* @var ParagonIE_Sodium_Core32_Int64 $d3
* @var ParagonIE_Sodium_Core32_Int64 $d4
* @var ParagonIE_Sodium_Core32_Int64 $r0
* @var ParagonIE_Sodium_Core32_Int64 $r1
* @var ParagonIE_Sodium_Core32_Int64 $r2
* @var ParagonIE_Sodium_Core32_Int64 $r3
* @var ParagonIE_Sodium_Core32_Int64 $r4
*
* @var ParagonIE_Sodium_Core32_Int32 $h0
* @var ParagonIE_Sodium_Core32_Int32 $h1
* @var ParagonIE_Sodium_Core32_Int32 $h2
* @var ParagonIE_Sodium_Core32_Int32 $h3
* @var ParagonIE_Sodium_Core32_Int32 $h4
*/
$r0 = $this->r[0]->toInt64();
$r1 = $this->r[1]->toInt64();
$r2 = $this->r[2]->toInt64();
$r3 = $this->r[3]->toInt64();
$r4 = $this->r[4]->toInt64();
$s1 = $r1->toInt64()->mulInt(5, 3);
$s2 = $r2->toInt64()->mulInt(5, 3);
$s3 = $r3->toInt64()->mulInt(5, 3);
$s4 = $r4->toInt64()->mulInt(5, 3);
$h0 = $this->h[0];
$h1 = $this->h[1];
$h2 = $this->h[2];
$h3 = $this->h[3];
$h4 = $this->h[4];
while ($bytes >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
/* h += m[i] */
$h0 = $h0->addInt32(
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 0, 4))
->mask(0x3ffffff)
)->toInt64();
$h1 = $h1->addInt32(
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 3, 4))
->shiftRight(2)
->mask(0x3ffffff)
)->toInt64();
$h2 = $h2->addInt32(
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 6, 4))
->shiftRight(4)
->mask(0x3ffffff)
)->toInt64();
$h3 = $h3->addInt32(
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 9, 4))
->shiftRight(6)
->mask(0x3ffffff)
)->toInt64();
$h4 = $h4->addInt32(
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 12, 4))
->shiftRight(8)
->orInt32($hibit)
)->toInt64();
/* h *= r */
$d0 = $zero
->addInt64($h0->mulInt64($r0, 27))
->addInt64($s4->mulInt64($h1, 27))
->addInt64($s3->mulInt64($h2, 27))
->addInt64($s2->mulInt64($h3, 27))
->addInt64($s1->mulInt64($h4, 27));
$d1 = $zero
->addInt64($h0->mulInt64($r1, 27))
->addInt64($h1->mulInt64($r0, 27))
->addInt64($s4->mulInt64($h2, 27))
->addInt64($s3->mulInt64($h3, 27))
->addInt64($s2->mulInt64($h4, 27));
$d2 = $zero
->addInt64($h0->mulInt64($r2, 27))
->addInt64($h1->mulInt64($r1, 27))
->addInt64($h2->mulInt64($r0, 27))
->addInt64($s4->mulInt64($h3, 27))
->addInt64($s3->mulInt64($h4, 27));
$d3 = $zero
->addInt64($h0->mulInt64($r3, 27))
->addInt64($h1->mulInt64($r2, 27))
->addInt64($h2->mulInt64($r1, 27))
->addInt64($h3->mulInt64($r0, 27))
->addInt64($s4->mulInt64($h4, 27));
$d4 = $zero
->addInt64($h0->mulInt64($r4, 27))
->addInt64($h1->mulInt64($r3, 27))
->addInt64($h2->mulInt64($r2, 27))
->addInt64($h3->mulInt64($r1, 27))
->addInt64($h4->mulInt64($r0, 27));
/* (partial) h %= p */
$c = $d0->shiftRight(26);
$h0 = $d0->toInt32()->mask(0x3ffffff);
$d1 = $d1->addInt64($c);
$c = $d1->shiftRight(26);
$h1 = $d1->toInt32()->mask(0x3ffffff);
$d2 = $d2->addInt64($c);
$c = $d2->shiftRight(26);
$h2 = $d2->toInt32()->mask(0x3ffffff);
$d3 = $d3->addInt64($c);
$c = $d3->shiftRight(26);
$h3 = $d3->toInt32()->mask(0x3ffffff);
$d4 = $d4->addInt64($c);
$c = $d4->shiftRight(26);
$h4 = $d4->toInt32()->mask(0x3ffffff);
$h0 = $h0->addInt32($c->toInt32()->mulInt(5, 3));
$c = $h0->shiftRight(26);
$h0 = $h0->mask(0x3ffffff);
$h1 = $h1->addInt32($c);
// Chop off the left 32 bytes.
$message = self::substr(
$message,
ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
);
$bytes -= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE;
}
/** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
$this->h = array($h0, $h1, $h2, $h3, $h4);
return $this;
}
/**
* @internal You should not use this directly from another application
*
* @return string
* @throws SodiumException
* @throws TypeError
*/
public function finish()
{
/* process the remaining block */
if ($this->leftover) {
$i = $this->leftover;
$this->buffer[$i++] = 1;
for (; $i < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE; ++$i) {
$this->buffer[$i] = 0;
}
$this->final = true;
$this->blocks(
self::substr(
self::intArrayToString($this->buffer),
0,
ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
),
$b = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
);
}
/**
* @var ParagonIE_Sodium_Core32_Int32 $f
* @var ParagonIE_Sodium_Core32_Int32 $g0
* @var ParagonIE_Sodium_Core32_Int32 $g1
* @var ParagonIE_Sodium_Core32_Int32 $g2
* @var ParagonIE_Sodium_Core32_Int32 $g3
* @var ParagonIE_Sodium_Core32_Int32 $g4
* @var ParagonIE_Sodium_Core32_Int32 $h0
* @var ParagonIE_Sodium_Core32_Int32 $h1
* @var ParagonIE_Sodium_Core32_Int32 $h2
* @var ParagonIE_Sodium_Core32_Int32 $h3
* @var ParagonIE_Sodium_Core32_Int32 $h4
*/
$h0 = $this->h[0];
$h1 = $this->h[1];
$h2 = $this->h[2];
$h3 = $this->h[3];
$h4 = $this->h[4];
$c = $h1->shiftRight(26); # $c = $h1 >> 26;
$h1 = $h1->mask(0x3ffffff); # $h1 &= 0x3ffffff;
$h2 = $h2->addInt32($c); # $h2 += $c;
$c = $h2->shiftRight(26); # $c = $h2 >> 26;
$h2 = $h2->mask(0x3ffffff); # $h2 &= 0x3ffffff;
$h3 = $h3->addInt32($c); # $h3 += $c;
$c = $h3->shiftRight(26); # $c = $h3 >> 26;
$h3 = $h3->mask(0x3ffffff); # $h3 &= 0x3ffffff;
$h4 = $h4->addInt32($c); # $h4 += $c;
$c = $h4->shiftRight(26); # $c = $h4 >> 26;
$h4 = $h4->mask(0x3ffffff); # $h4 &= 0x3ffffff;
$h0 = $h0->addInt32($c->mulInt(5, 3)); # $h0 += self::mul($c, 5);
$c = $h0->shiftRight(26); # $c = $h0 >> 26;
$h0 = $h0->mask(0x3ffffff); # $h0 &= 0x3ffffff;
$h1 = $h1->addInt32($c); # $h1 += $c;
/* compute h + -p */
$g0 = $h0->addInt(5);
$c = $g0->shiftRight(26);
$g0 = $g0->mask(0x3ffffff);
$g1 = $h1->addInt32($c);
$c = $g1->shiftRight(26);
$g1 = $g1->mask(0x3ffffff);
$g2 = $h2->addInt32($c);
$c = $g2->shiftRight(26);
$g2 = $g2->mask(0x3ffffff);
$g3 = $h3->addInt32($c);
$c = $g3->shiftRight(26);
$g3 = $g3->mask(0x3ffffff);
$g4 = $h4->addInt32($c)->subInt(1 << 26);
# $mask = ($g4 >> 31) - 1;
/* select h if h < p, or h + -p if h >= p */
$mask = (int) (($g4->toInt() >> 31) + 1);
$g0 = $g0->mask($mask);
$g1 = $g1->mask($mask);
$g2 = $g2->mask($mask);
$g3 = $g3->mask($mask);
$g4 = $g4->mask($mask);
/** @var int $mask */
$mask = ~$mask;
$h0 = $h0->mask($mask)->orInt32($g0);
$h1 = $h1->mask($mask)->orInt32($g1);
$h2 = $h2->mask($mask)->orInt32($g2);
$h3 = $h3->mask($mask)->orInt32($g3);
$h4 = $h4->mask($mask)->orInt32($g4);
/* h = h % (2^128) */
$h0 = $h0->orInt32($h1->shiftLeft(26));
$h1 = $h1->shiftRight(6)->orInt32($h2->shiftLeft(20));
$h2 = $h2->shiftRight(12)->orInt32($h3->shiftLeft(14));
$h3 = $h3->shiftRight(18)->orInt32($h4->shiftLeft(8));
/* mac = (h + pad) % (2^128) */
$f = $h0->toInt64()->addInt64($this->pad[0]);
$h0 = $f->toInt32();
$f = $h1->toInt64()->addInt64($this->pad[1])->addInt($h0->overflow);
$h1 = $f->toInt32();
$f = $h2->toInt64()->addInt64($this->pad[2])->addInt($h1->overflow);
$h2 = $f->toInt32();
$f = $h3->toInt64()->addInt64($this->pad[3])->addInt($h2->overflow);
$h3 = $f->toInt32();
return $h0->toReverseString() .
$h1->toReverseString() .
$h2->toReverseString() .
$h3->toReverseString();
}
}
Core32/Poly1305/error_log 0000644 00000000550 15051413233 0010747 0 ustar 00 [19-Aug-2025 17:33:12 UTC] PHP Fatal error: Uncaught Error: Class 'ParagonIE_Sodium_Core32_Util' not found in /home/deltahospital/test.delta-hospital.com/wp-includes/sodium_compat/src/Core32/Poly1305/State.php:10
Stack trace:
#0 {main}
thrown in /home/deltahospital/test.delta-hospital.com/wp-includes/sodium_compat/src/Core32/Poly1305/State.php on line 10
Core32/HChaCha20.php 0000644 00000012261 15051413234 0007673 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core32_HChaCha20', false)) {
return;
}
/**
* Class ParagonIE_Sodium_Core_HChaCha20
*/
class ParagonIE_Sodium_Core32_HChaCha20 extends ParagonIE_Sodium_Core32_ChaCha20
{
/**
* @param string $in
* @param string $key
* @param string|null $c
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function hChaCha20($in = '', $key = '', $c = null)
{
$ctx = array();
if ($c === null) {
$ctx[0] = new ParagonIE_Sodium_Core32_Int32(array(0x6170, 0x7865));
$ctx[1] = new ParagonIE_Sodium_Core32_Int32(array(0x3320, 0x646e));
$ctx[2] = new ParagonIE_Sodium_Core32_Int32(array(0x7962, 0x2d32));
$ctx[3] = new ParagonIE_Sodium_Core32_Int32(array(0x6b20, 0x6574));
} else {
$ctx[0] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 0, 4));
$ctx[1] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 4, 4));
$ctx[2] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 8, 4));
$ctx[3] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 12, 4));
}
$ctx[4] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4));
$ctx[5] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 4, 4));
$ctx[6] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 8, 4));
$ctx[7] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12, 4));
$ctx[8] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16, 4));
$ctx[9] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20, 4));
$ctx[10] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24, 4));
$ctx[11] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28, 4));
$ctx[12] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 0, 4));
$ctx[13] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 4, 4));
$ctx[14] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 8, 4));
$ctx[15] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 12, 4));
return self::hChaCha20Bytes($ctx);
}
/**
* @param array $ctx
* @return string
* @throws SodiumException
* @throws TypeError
*/
protected static function hChaCha20Bytes(array $ctx)
{
/** @var ParagonIE_Sodium_Core32_Int32 $x0 */
$x0 = $ctx[0];
/** @var ParagonIE_Sodium_Core32_Int32 $x1 */
$x1 = $ctx[1];
/** @var ParagonIE_Sodium_Core32_Int32 $x2 */
$x2 = $ctx[2];
/** @var ParagonIE_Sodium_Core32_Int32 $x3 */
$x3 = $ctx[3];
/** @var ParagonIE_Sodium_Core32_Int32 $x4 */
$x4 = $ctx[4];
/** @var ParagonIE_Sodium_Core32_Int32 $x5 */
$x5 = $ctx[5];
/** @var ParagonIE_Sodium_Core32_Int32 $x6 */
$x6 = $ctx[6];
/** @var ParagonIE_Sodium_Core32_Int32 $x7 */
$x7 = $ctx[7];
/** @var ParagonIE_Sodium_Core32_Int32 $x8 */
$x8 = $ctx[8];
/** @var ParagonIE_Sodium_Core32_Int32 $x9 */
$x9 = $ctx[9];
/** @var ParagonIE_Sodium_Core32_Int32 $x10 */
$x10 = $ctx[10];
/** @var ParagonIE_Sodium_Core32_Int32 $x11 */
$x11 = $ctx[11];
/** @var ParagonIE_Sodium_Core32_Int32 $x12 */
$x12 = $ctx[12];
/** @var ParagonIE_Sodium_Core32_Int32 $x13 */
$x13 = $ctx[13];
/** @var ParagonIE_Sodium_Core32_Int32 $x14 */
$x14 = $ctx[14];
/** @var ParagonIE_Sodium_Core32_Int32 $x15 */
$x15 = $ctx[15];
for ($i = 0; $i < 10; ++$i) {
# QUARTERROUND( x0, x4, x8, x12)
list($x0, $x4, $x8, $x12) = self::quarterRound($x0, $x4, $x8, $x12);
# QUARTERROUND( x1, x5, x9, x13)
list($x1, $x5, $x9, $x13) = self::quarterRound($x1, $x5, $x9, $x13);
# QUARTERROUND( x2, x6, x10, x14)
list($x2, $x6, $x10, $x14) = self::quarterRound($x2, $x6, $x10, $x14);
# QUARTERROUND( x3, x7, x11, x15)
list($x3, $x7, $x11, $x15) = self::quarterRound($x3, $x7, $x11, $x15);
# QUARTERROUND( x0, x5, x10, x15)
list($x0, $x5, $x10, $x15) = self::quarterRound($x0, $x5, $x10, $x15);
# QUARTERROUND( x1, x6, x11, x12)
list($x1, $x6, $x11, $x12) = self::quarterRound($x1, $x6, $x11, $x12);
# QUARTERROUND( x2, x7, x8, x13)
list($x2, $x7, $x8, $x13) = self::quarterRound($x2, $x7, $x8, $x13);
# QUARTERROUND( x3, x4, x9, x14)
list($x3, $x4, $x9, $x14) = self::quarterRound($x3, $x4, $x9, $x14);
}
return $x0->toReverseString() .
$x1->toReverseString() .
$x2->toReverseString() .
$x3->toReverseString() .
$x12->toReverseString() .
$x13->toReverseString() .
$x14->toReverseString() .
$x15->toReverseString();
}
}
Core32/BLAKE2b.php 0000644 00000053464 15051413234 0007366 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core_BLAKE2b', false)) {
return;
}
/**
* Class ParagonIE_Sodium_Core_BLAKE2b
*
* Based on the work of Devi Mandiri in devi/salt.
*/
abstract class ParagonIE_Sodium_Core32_BLAKE2b extends ParagonIE_Sodium_Core_Util
{
/**
* @var SplFixedArray
*/
public static $iv;
/**
* @var array<int, array<int, int>>
*/
public static $sigma = array(
array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
array( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3),
array( 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4),
array( 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8),
array( 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13),
array( 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9),
array( 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11),
array( 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10),
array( 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5),
array( 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0),
array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
array( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3)
);
const BLOCKBYTES = 128;
const OUTBYTES = 64;
const KEYBYTES = 64;
/**
* Turn two 32-bit integers into a fixed array representing a 64-bit integer.
*
* @internal You should not use this directly from another application
*
* @param int $high
* @param int $low
* @return ParagonIE_Sodium_Core32_Int64
* @throws SodiumException
* @throws TypeError
*/
public static function new64($high, $low)
{
return ParagonIE_Sodium_Core32_Int64::fromInts($low, $high);
}
/**
* Convert an arbitrary number into an SplFixedArray of two 32-bit integers
* that represents a 64-bit integer.
*
* @internal You should not use this directly from another application
*
* @param int $num
* @return ParagonIE_Sodium_Core32_Int64
* @throws SodiumException
* @throws TypeError
*/
protected static function to64($num)
{
list($hi, $lo) = self::numericTo64BitInteger($num);
return self::new64($hi, $lo);
}
/**
* Adds two 64-bit integers together, returning their sum as a SplFixedArray
* containing two 32-bit integers (representing a 64-bit integer).
*
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Int64 $x
* @param ParagonIE_Sodium_Core32_Int64 $y
* @return ParagonIE_Sodium_Core32_Int64
*/
protected static function add64($x, $y)
{
return $x->addInt64($y);
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Int64 $x
* @param ParagonIE_Sodium_Core32_Int64 $y
* @param ParagonIE_Sodium_Core32_Int64 $z
* @return ParagonIE_Sodium_Core32_Int64
*/
public static function add364($x, $y, $z)
{
return $x->addInt64($y)->addInt64($z);
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Int64 $x
* @param ParagonIE_Sodium_Core32_Int64 $y
* @return ParagonIE_Sodium_Core32_Int64
* @throws TypeError
*/
public static function xor64(ParagonIE_Sodium_Core32_Int64 $x, ParagonIE_Sodium_Core32_Int64 $y)
{
return $x->xorInt64($y);
}
/**
* @internal You should not use this directly from another application
*
* @param ParagonIE_Sodium_Core32_Int64 $x
* @param int $c
* @return ParagonIE_Sodium_Core32_Int64
* @throws SodiumException
* @throws TypeError
*/
public static function rotr64(ParagonIE_Sodium_Core32_Int64 $x, $c)
{
return $x->rotateRight($c);
}
/**
* @internal You should not use this directly from another application
*
* @param SplFixedArray $x
* @param int $i
* @return ParagonIE_Sodium_Core32_Int64
* @throws SodiumException
* @throws TypeError
*/
public static function load64($x, $i)
{
/** @var int $l */
$l = (int) ($x[$i])
| ((int) ($x[$i+1]) << 8)
| ((int) ($x[$i+2]) << 16)
| ((int) ($x[$i+3]) << 24);
/** @var int $h */
$h = (int) ($x[$i+4])
| ((int) ($x[$i+5]) << 8)
| ((int) ($x[$i+6]) << 16)
| ((int) ($x[$i+7]) << 24);
return self::new64($h, $l);
}
/**
* @internal You should not use this directly from another application
*
* @param SplFixedArray $x
* @param int $i
* @param ParagonIE_Sodium_Core32_Int64 $u
* @return void
* @throws TypeError
* @psalm-suppress MixedArgument
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedArrayAccess
* @psalm-suppress MixedArrayAssignment
* @psalm-suppress MixedArrayOffset
*/
public static function store64(SplFixedArray $x, $i, ParagonIE_Sodium_Core32_Int64 $u)
{
$v = clone $u;
$maxLength = $x->getSize() - 1;
for ($j = 0; $j < 8; ++$j) {
$k = 3 - ($j >> 1);
$x[$i] = $v->limbs[$k] & 0xff;
if (++$i > $maxLength) {
return;
}
$v->limbs[$k] >>= 8;
}
}
/**
* This just sets the $iv static variable.
*
* @internal You should not use this directly from another application
*
* @return void
* @throws SodiumException
* @throws TypeError
*/
public static function pseudoConstructor()
{
static $called = false;
if ($called) {
return;
}
self::$iv = new SplFixedArray(8);
self::$iv[0] = self::new64(0x6a09e667, 0xf3bcc908);
self::$iv[1] = self::new64(0xbb67ae85, 0x84caa73b);
self::$iv[2] = self::new64(0x3c6ef372, 0xfe94f82b);
self::$iv[3] = self::new64(0xa54ff53a, 0x5f1d36f1);
self::$iv[4] = self::new64(0x510e527f, 0xade682d1);
self::$iv[5] = self::new64(0x9b05688c, 0x2b3e6c1f);
self::$iv[6] = self::new64(0x1f83d9ab, 0xfb41bd6b);
self::$iv[7] = self::new64(0x5be0cd19, 0x137e2179);
$called = true;
}
/**
* Returns a fresh BLAKE2 context.
*
* @internal You should not use this directly from another application
*
* @return SplFixedArray
* @throws TypeError
* @psalm-suppress MixedArgument
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedArrayAccess
* @psalm-suppress MixedArrayAssignment
* @psalm-suppress MixedArrayOffset
* @throws SodiumException
* @throws TypeError
*/
protected static function context()
{
$ctx = new SplFixedArray(6);
$ctx[0] = new SplFixedArray(8); // h
$ctx[1] = new SplFixedArray(2); // t
$ctx[2] = new SplFixedArray(2); // f
$ctx[3] = new SplFixedArray(256); // buf
$ctx[4] = 0; // buflen
$ctx[5] = 0; // last_node (uint8_t)
for ($i = 8; $i--;) {
$ctx[0][$i] = self::$iv[$i];
}
for ($i = 256; $i--;) {
$ctx[3][$i] = 0;
}
$zero = self::new64(0, 0);
$ctx[1][0] = $zero;
$ctx[1][1] = $zero;
$ctx[2][0] = $zero;
$ctx[2][1] = $zero;
return $ctx;
}
/**
* @internal You should not use this directly from another application
*
* @param SplFixedArray $ctx
* @param SplFixedArray $buf
* @return void
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArgument
* @psalm-suppress MixedArrayAccess
* @psalm-suppress MixedArrayAssignment
* @psalm-suppress MixedAssignment
*/
protected static function compress(SplFixedArray $ctx, SplFixedArray $buf)
{
$m = new SplFixedArray(16);
$v = new SplFixedArray(16);
for ($i = 16; $i--;) {
$m[$i] = self::load64($buf, $i << 3);
}
for ($i = 8; $i--;) {
$v[$i] = $ctx[0][$i];
}
$v[ 8] = self::$iv[0];
$v[ 9] = self::$iv[1];
$v[10] = self::$iv[2];
$v[11] = self::$iv[3];
$v[12] = self::xor64($ctx[1][0], self::$iv[4]);
$v[13] = self::xor64($ctx[1][1], self::$iv[5]);
$v[14] = self::xor64($ctx[2][0], self::$iv[6]);
$v[15] = self::xor64($ctx[2][1], self::$iv[7]);
for ($r = 0; $r < 12; ++$r) {
$v = self::G($r, 0, 0, 4, 8, 12, $v, $m);
$v = self::G($r, 1, 1, 5, 9, 13, $v, $m);
$v = self::G($r, 2, 2, 6, 10, 14, $v, $m);
$v = self::G($r, 3, 3, 7, 11, 15, $v, $m);
$v = self::G($r, 4, 0, 5, 10, 15, $v, $m);
$v = self::G($r, 5, 1, 6, 11, 12, $v, $m);
$v = self::G($r, 6, 2, 7, 8, 13, $v, $m);
$v = self::G($r, 7, 3, 4, 9, 14, $v, $m);
}
for ($i = 8; $i--;) {
$ctx[0][$i] = self::xor64(
$ctx[0][$i], self::xor64($v[$i], $v[$i+8])
);
}
}
/**
* @internal You should not use this directly from another application
*
* @param int $r
* @param int $i
* @param int $a
* @param int $b
* @param int $c
* @param int $d
* @param SplFixedArray $v
* @param SplFixedArray $m
* @return SplFixedArray
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArgument
* @psalm-suppress MixedArrayOffset
*/
public static function G($r, $i, $a, $b, $c, $d, SplFixedArray $v, SplFixedArray $m)
{
$v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][$i << 1]]);
$v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 32);
$v[$c] = self::add64($v[$c], $v[$d]);
$v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 24);
$v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][($i << 1) + 1]]);
$v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 16);
$v[$c] = self::add64($v[$c], $v[$d]);
$v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 63);
return $v;
}
/**
* @internal You should not use this directly from another application
*
* @param SplFixedArray $ctx
* @param int $inc
* @return void
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArgument
* @psalm-suppress MixedArrayAccess
* @psalm-suppress MixedArrayAssignment
*/
public static function increment_counter($ctx, $inc)
{
if ($inc < 0) {
throw new SodiumException('Increasing by a negative number makes no sense.');
}
$t = self::to64($inc);
# S->t is $ctx[1] in our implementation
# S->t[0] = ( uint64_t )( t >> 0 );
$ctx[1][0] = self::add64($ctx[1][0], $t);
# S->t[1] += ( S->t[0] < inc );
if (!($ctx[1][0] instanceof ParagonIE_Sodium_Core32_Int64)) {
throw new TypeError('Not an int64');
}
/** @var ParagonIE_Sodium_Core32_Int64 $c*/
$c = $ctx[1][0];
if ($c->isLessThanInt($inc)) {
$ctx[1][1] = self::add64($ctx[1][1], self::to64(1));
}
}
/**
* @internal You should not use this directly from another application
*
* @param SplFixedArray $ctx
* @param SplFixedArray $p
* @param int $plen
* @return void
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArgument
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedArrayAccess
* @psalm-suppress MixedArrayAssignment
* @psalm-suppress MixedArrayOffset
* @psalm-suppress MixedMethodCall
* @psalm-suppress MixedOperand
*/
public static function update(SplFixedArray $ctx, SplFixedArray $p, $plen)
{
self::pseudoConstructor();
$offset = 0;
while ($plen > 0) {
$left = $ctx[4];
$fill = 256 - $left;
if ($plen > $fill) {
# memcpy( S->buf + left, in, fill ); /* Fill buffer */
for ($i = $fill; $i--;) {
$ctx[3][$i + $left] = $p[$i + $offset];
}
# S->buflen += fill;
$ctx[4] += $fill;
# blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
self::increment_counter($ctx, 128);
# blake2b_compress( S, S->buf ); /* Compress */
self::compress($ctx, $ctx[3]);
# memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); /* Shift buffer left */
for ($i = 128; $i--;) {
$ctx[3][$i] = $ctx[3][$i + 128];
}
# S->buflen -= BLAKE2B_BLOCKBYTES;
$ctx[4] -= 128;
# in += fill;
$offset += $fill;
# inlen -= fill;
$plen -= $fill;
} else {
for ($i = $plen; $i--;) {
$ctx[3][$i + $left] = $p[$i + $offset];
}
$ctx[4] += $plen;
$offset += $plen;
$plen -= $plen;
}
}
}
/**
* @internal You should not use this directly from another application
*
* @param SplFixedArray $ctx
* @param SplFixedArray $out
* @return SplFixedArray
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArgument
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedArrayAccess
* @psalm-suppress MixedArrayAssignment
* @psalm-suppress MixedArrayOffset
* @psalm-suppress MixedMethodCall
* @psalm-suppress MixedOperand
*/
public static function finish(SplFixedArray $ctx, SplFixedArray $out)
{
self::pseudoConstructor();
if ($ctx[4] > 128) {
self::increment_counter($ctx, 128);
self::compress($ctx, $ctx[3]);
$ctx[4] -= 128;
if ($ctx[4] > 128) {
throw new SodiumException('Failed to assert that buflen <= 128 bytes');
}
for ($i = $ctx[4]; $i--;) {
$ctx[3][$i] = $ctx[3][$i + 128];
}
}
self::increment_counter($ctx, $ctx[4]);
$ctx[2][0] = self::new64(0xffffffff, 0xffffffff);
for ($i = 256 - $ctx[4]; $i--;) {
/** @var int $i */
$ctx[3][$i + $ctx[4]] = 0;
}
self::compress($ctx, $ctx[3]);
$i = (int) (($out->getSize() - 1) / 8);
for (; $i >= 0; --$i) {
self::store64($out, $i << 3, $ctx[0][$i]);
}
return $out;
}
/**
* @internal You should not use this directly from another application
*
* @param SplFixedArray|null $key
* @param int $outlen
* @param SplFixedArray|null $salt
* @param SplFixedArray|null $personal
* @return SplFixedArray
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArgument
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedArrayAccess
* @psalm-suppress MixedArrayAssignment
* @psalm-suppress MixedMethodCall
*/
public static function init(
$key = null,
$outlen = 64,
$salt = null,
$personal = null
) {
self::pseudoConstructor();
$klen = 0;
if ($key !== null) {
if (count($key) > 64) {
throw new SodiumException('Invalid key size');
}
$klen = count($key);
}
if ($outlen > 64) {
throw new SodiumException('Invalid output size');
}
$ctx = self::context();
$p = new SplFixedArray(64);
// Zero our param buffer...
for ($i = 64; --$i;) {
$p[$i] = 0;
}
$p[0] = $outlen; // digest_length
$p[1] = $klen; // key_length
$p[2] = 1; // fanout
$p[3] = 1; // depth
if ($salt instanceof SplFixedArray) {
// salt: [32] through [47]
for ($i = 0; $i < 16; ++$i) {
$p[32 + $i] = (int) $salt[$i];
}
}
if ($personal instanceof SplFixedArray) {
// personal: [48] through [63]
for ($i = 0; $i < 16; ++$i) {
$p[48 + $i] = (int) $personal[$i];
}
}
$ctx[0][0] = self::xor64(
$ctx[0][0],
self::load64($p, 0)
);
if ($salt instanceof SplFixedArray || $personal instanceof SplFixedArray) {
// We need to do what blake2b_init_param() does:
for ($i = 1; $i < 8; ++$i) {
$ctx[0][$i] = self::xor64(
$ctx[0][$i],
self::load64($p, $i << 3)
);
}
}
if ($klen > 0 && $key instanceof SplFixedArray) {
$block = new SplFixedArray(128);
for ($i = 128; $i--;) {
$block[$i] = 0;
}
for ($i = $klen; $i--;) {
$block[$i] = $key[$i];
}
self::update($ctx, $block, 128);
$ctx[4] = 128;
}
return $ctx;
}
/**
* Convert a string into an SplFixedArray of integers
*
* @internal You should not use this directly from another application
*
* @param string $str
* @return SplFixedArray
* @psalm-suppress MixedArgumentTypeCoercion
*/
public static function stringToSplFixedArray($str = '')
{
$values = unpack('C*', $str);
return SplFixedArray::fromArray(array_values($values));
}
/**
* Convert an SplFixedArray of integers into a string
*
* @internal You should not use this directly from another application
*
* @param SplFixedArray $a
* @return string
*/
public static function SplFixedArrayToString(SplFixedArray $a)
{
/**
* @var array<int, string|int>
*/
$arr = $a->toArray();
$c = $a->count();
array_unshift($arr, str_repeat('C', $c));
return (string) (call_user_func_array('pack', $arr));
}
/**
* @internal You should not use this directly from another application
*
* @param SplFixedArray $ctx
* @return string
* @throws TypeError
* @psalm-suppress MixedArgument
* @psalm-suppress MixedArrayAccess
* @psalm-suppress MixedArrayAssignment
* @psalm-suppress MixedMethodCall
*/
public static function contextToString(SplFixedArray $ctx)
{
$str = '';
/** @var array<int, ParagonIE_Sodium_Core32_Int64> $ctxA */
$ctxA = $ctx[0]->toArray();
# uint64_t h[8];
for ($i = 0; $i < 8; ++$i) {
if (!($ctxA[$i] instanceof ParagonIE_Sodium_Core32_Int64)) {
throw new TypeError('Not an instance of Int64');
}
/** @var ParagonIE_Sodium_Core32_Int64 $ctxAi */
$ctxAi = $ctxA[$i];
$str .= $ctxAi->toReverseString();
}
# uint64_t t[2];
# uint64_t f[2];
for ($i = 1; $i < 3; ++$i) {
/** @var array<int, ParagonIE_Sodium_Core32_Int64> $ctxA */
$ctxA = $ctx[$i]->toArray();
/** @var ParagonIE_Sodium_Core32_Int64 $ctxA1 */
$ctxA1 = $ctxA[0];
/** @var ParagonIE_Sodium_Core32_Int64 $ctxA2 */
$ctxA2 = $ctxA[1];
$str .= $ctxA1->toReverseString();
$str .= $ctxA2->toReverseString();
}
# uint8_t buf[2 * 128];
$str .= self::SplFixedArrayToString($ctx[3]);
/** @var int $ctx4 */
$ctx4 = $ctx[4];
# size_t buflen;
$str .= implode('', array(
self::intToChr($ctx4 & 0xff),
self::intToChr(($ctx4 >> 8) & 0xff),
self::intToChr(($ctx4 >> 16) & 0xff),
self::intToChr(($ctx4 >> 24) & 0xff),
"\x00\x00\x00\x00"
/*
self::intToChr(($ctx4 >> 32) & 0xff),
self::intToChr(($ctx4 >> 40) & 0xff),
self::intToChr(($ctx4 >> 48) & 0xff),
self::intToChr(($ctx4 >> 56) & 0xff)
*/
));
# uint8_t last_node;
return $str . self::intToChr($ctx[5]) . str_repeat("\x00", 23);
}
/**
* Creates an SplFixedArray containing other SplFixedArray elements, from
* a string (compatible with \Sodium\crypto_generichash_{init, update, final})
*
* @internal You should not use this directly from another application
*
* @param string $string
* @return SplFixedArray
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArrayAccess
* @psalm-suppress MixedArrayAssignment
*/
public static function stringToContext($string)
{
$ctx = self::context();
# uint64_t h[8];
for ($i = 0; $i < 8; ++$i) {
$ctx[0][$i] = ParagonIE_Sodium_Core32_Int64::fromReverseString(
self::substr($string, (($i << 3) + 0), 8)
);
}
# uint64_t t[2];
# uint64_t f[2];
for ($i = 1; $i < 3; ++$i) {
$ctx[$i][1] = ParagonIE_Sodium_Core32_Int64::fromReverseString(
self::substr($string, 72 + (($i - 1) << 4), 8)
);
$ctx[$i][0] = ParagonIE_Sodium_Core32_Int64::fromReverseString(
self::substr($string, 64 + (($i - 1) << 4), 8)
);
}
# uint8_t buf[2 * 128];
$ctx[3] = self::stringToSplFixedArray(self::substr($string, 96, 256));
# uint8_t buf[2 * 128];
$int = 0;
for ($i = 0; $i < 8; ++$i) {
$int |= self::chrToInt($string[352 + $i]) << ($i << 3);
}
$ctx[4] = $int;
return $ctx;
}
}
Core32/Int64.php 0000644 00000074704 15051413234 0007230 0 ustar 00 <?php
/**
* Class ParagonIE_Sodium_Core32_Int64
*
* Encapsulates a 64-bit integer.
*
* These are immutable. It always returns a new instance.
*/
class ParagonIE_Sodium_Core32_Int64
{
/**
* @var array<int, int> - four 16-bit integers
*/
public $limbs = array(0, 0, 0, 0);
/**
* @var int
*/
public $overflow = 0;
/**
* @var bool
*/
public $unsignedInt = false;
/**
* ParagonIE_Sodium_Core32_Int64 constructor.
* @param array $array
* @param bool $unsignedInt
*/
public function __construct($array = array(0, 0, 0, 0), $unsignedInt = false)
{
$this->limbs = array(
(int) $array[0],
(int) $array[1],
(int) $array[2],
(int) $array[3]
);
$this->overflow = 0;
$this->unsignedInt = $unsignedInt;
}
/**
* Adds two int64 objects
*
* @param ParagonIE_Sodium_Core32_Int64 $addend
* @return ParagonIE_Sodium_Core32_Int64
*/
public function addInt64(ParagonIE_Sodium_Core32_Int64 $addend)
{
$i0 = $this->limbs[0];
$i1 = $this->limbs[1];
$i2 = $this->limbs[2];
$i3 = $this->limbs[3];
$j0 = $addend->limbs[0];
$j1 = $addend->limbs[1];
$j2 = $addend->limbs[2];
$j3 = $addend->limbs[3];
$r3 = $i3 + ($j3 & 0xffff);
$carry = $r3 >> 16;
$r2 = $i2 + ($j2 & 0xffff) + $carry;
$carry = $r2 >> 16;
$r1 = $i1 + ($j1 & 0xffff) + $carry;
$carry = $r1 >> 16;
$r0 = $i0 + ($j0 & 0xffff) + $carry;
$carry = $r0 >> 16;
$r0 &= 0xffff;
$r1 &= 0xffff;
$r2 &= 0xffff;
$r3 &= 0xffff;
$return = new ParagonIE_Sodium_Core32_Int64(
array($r0, $r1, $r2, $r3)
);
$return->overflow = $carry;
$return->unsignedInt = $this->unsignedInt;
return $return;
}
/**
* Adds a normal integer to an int64 object
*
* @param int $int
* @return ParagonIE_Sodium_Core32_Int64
* @throws SodiumException
* @throws TypeError
*/
public function addInt($int)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
/** @var int $int */
$int = (int) $int;
$i0 = $this->limbs[0];
$i1 = $this->limbs[1];
$i2 = $this->limbs[2];
$i3 = $this->limbs[3];
$r3 = $i3 + ($int & 0xffff);
$carry = $r3 >> 16;
$r2 = $i2 + (($int >> 16) & 0xffff) + $carry;
$carry = $r2 >> 16;
$r1 = $i1 + $carry;
$carry = $r1 >> 16;
$r0 = $i0 + $carry;
$carry = $r0 >> 16;
$r0 &= 0xffff;
$r1 &= 0xffff;
$r2 &= 0xffff;
$r3 &= 0xffff;
$return = new ParagonIE_Sodium_Core32_Int64(
array($r0, $r1, $r2, $r3)
);
$return->overflow = $carry;
$return->unsignedInt = $this->unsignedInt;
return $return;
}
/**
* @param int $b
* @return int
*/
public function compareInt($b = 0)
{
$gt = 0;
$eq = 1;
$i = 4;
$j = 0;
while ($i > 0) {
--$i;
/** @var int $x1 */
$x1 = $this->limbs[$i];
/** @var int $x2 */
$x2 = ($b >> ($j << 4)) & 0xffff;
/** int */
$gt |= (($x2 - $x1) >> 8) & $eq;
/** int */
$eq &= (($x2 ^ $x1) - 1) >> 8;
}
return ($gt + $gt - $eq) + 1;
}
/**
* @param int $b
* @return bool
*/
public function isGreaterThan($b = 0)
{
return $this->compareInt($b) > 0;
}
/**
* @param int $b
* @return bool
*/
public function isLessThanInt($b = 0)
{
return $this->compareInt($b) < 0;
}
/**
* @param int $hi
* @param int $lo
* @return ParagonIE_Sodium_Core32_Int64
*/
public function mask64($hi = 0, $lo = 0)
{
/** @var int $a */
$a = ($hi >> 16) & 0xffff;
/** @var int $b */
$b = ($hi) & 0xffff;
/** @var int $c */
$c = ($lo >> 16) & 0xffff;
/** @var int $d */
$d = ($lo & 0xffff);
return new ParagonIE_Sodium_Core32_Int64(
array(
$this->limbs[0] & $a,
$this->limbs[1] & $b,
$this->limbs[2] & $c,
$this->limbs[3] & $d
),
$this->unsignedInt
);
}
/**
* @param int $int
* @param int $size
* @return ParagonIE_Sodium_Core32_Int64
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedAssignment
*/
public function mulInt($int = 0, $size = 0)
{
if (ParagonIE_Sodium_Compat::$fastMult) {
return $this->mulIntFast($int);
}
ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
/** @var int $int */
$int = (int) $int;
/** @var int $size */
$size = (int) $size;
if (!$size) {
$size = 63;
}
$a = clone $this;
$return = new ParagonIE_Sodium_Core32_Int64();
$return->unsignedInt = $this->unsignedInt;
// Initialize:
$ret0 = 0;
$ret1 = 0;
$ret2 = 0;
$ret3 = 0;
$a0 = $a->limbs[0];
$a1 = $a->limbs[1];
$a2 = $a->limbs[2];
$a3 = $a->limbs[3];
/** @var int $size */
/** @var int $i */
for ($i = $size; $i >= 0; --$i) {
$mask = -($int & 1);
$x0 = $a0 & $mask;
$x1 = $a1 & $mask;
$x2 = $a2 & $mask;
$x3 = $a3 & $mask;
$ret3 += $x3;
$c = $ret3 >> 16;
$ret2 += $x2 + $c;
$c = $ret2 >> 16;
$ret1 += $x1 + $c;
$c = $ret1 >> 16;
$ret0 += $x0 + $c;
$ret0 &= 0xffff;
$ret1 &= 0xffff;
$ret2 &= 0xffff;
$ret3 &= 0xffff;
$a3 = $a3 << 1;
$x3 = $a3 >> 16;
$a2 = ($a2 << 1) | $x3;
$x2 = $a2 >> 16;
$a1 = ($a1 << 1) | $x2;
$x1 = $a1 >> 16;
$a0 = ($a0 << 1) | $x1;
$a0 &= 0xffff;
$a1 &= 0xffff;
$a2 &= 0xffff;
$a3 &= 0xffff;
$int >>= 1;
}
$return->limbs[0] = $ret0;
$return->limbs[1] = $ret1;
$return->limbs[2] = $ret2;
$return->limbs[3] = $ret3;
return $return;
}
/**
* @param ParagonIE_Sodium_Core32_Int64 $A
* @param ParagonIE_Sodium_Core32_Int64 $B
* @return array<int, ParagonIE_Sodium_Core32_Int64>
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedInferredReturnType
*/
public static function ctSelect(
ParagonIE_Sodium_Core32_Int64 $A,
ParagonIE_Sodium_Core32_Int64 $B
) {
$a = clone $A;
$b = clone $B;
/** @var int $aNeg */
$aNeg = ($a->limbs[0] >> 15) & 1;
/** @var int $bNeg */
$bNeg = ($b->limbs[0] >> 15) & 1;
/** @var int $m */
$m = (-($aNeg & $bNeg)) | 1;
/** @var int $swap */
$swap = $bNeg & ~$aNeg;
/** @var int $d */
$d = -$swap;
/*
if ($bNeg && !$aNeg) {
$a = clone $int;
$b = clone $this;
} elseif($bNeg && $aNeg) {
$a = $this->mulInt(-1);
$b = $int->mulInt(-1);
}
*/
$x = $a->xorInt64($b)->mask64($d, $d);
return array(
$a->xorInt64($x)->mulInt($m),
$b->xorInt64($x)->mulInt($m)
);
}
/**
* @param array<int, int> $a
* @param array<int, int> $b
* @param int $baseLog2
* @return array<int, int>
*/
public function multiplyLong(array $a, array $b, $baseLog2 = 16)
{
$a_l = count($a);
$b_l = count($b);
/** @var array<int, int> $r */
$r = array_fill(0, $a_l + $b_l + 1, 0);
$base = 1 << $baseLog2;
for ($i = 0; $i < $a_l; ++$i) {
$a_i = $a[$i];
for ($j = 0; $j < $a_l; ++$j) {
$b_j = $b[$j];
$product = (($a_i * $b_j) + $r[$i + $j]);
$carry = (((int) $product >> $baseLog2) & 0xffff);
$r[$i + $j] = ((int) $product - (int) ($carry * $base)) & 0xffff;
$r[$i + $j + 1] += $carry;
}
}
return array_slice($r, 0, 5);
}
/**
* @param int $int
* @return ParagonIE_Sodium_Core32_Int64
*/
public function mulIntFast($int)
{
// Handle negative numbers
$aNeg = ($this->limbs[0] >> 15) & 1;
$bNeg = ($int >> 31) & 1;
$a = array_reverse($this->limbs);
$b = array(
$int & 0xffff,
($int >> 16) & 0xffff,
-$bNeg & 0xffff,
-$bNeg & 0xffff
);
if ($aNeg) {
for ($i = 0; $i < 4; ++$i) {
$a[$i] = ($a[$i] ^ 0xffff) & 0xffff;
}
++$a[0];
}
if ($bNeg) {
for ($i = 0; $i < 4; ++$i) {
$b[$i] = ($b[$i] ^ 0xffff) & 0xffff;
}
++$b[0];
}
// Multiply
$res = $this->multiplyLong($a, $b);
// Re-apply negation to results
if ($aNeg !== $bNeg) {
for ($i = 0; $i < 4; ++$i) {
$res[$i] = (0xffff ^ $res[$i]) & 0xffff;
}
// Handle integer overflow
$c = 1;
for ($i = 0; $i < 4; ++$i) {
$res[$i] += $c;
$c = $res[$i] >> 16;
$res[$i] &= 0xffff;
}
}
// Return our values
$return = new ParagonIE_Sodium_Core32_Int64();
$return->limbs = array(
$res[3] & 0xffff,
$res[2] & 0xffff,
$res[1] & 0xffff,
$res[0] & 0xffff
);
if (count($res) > 4) {
$return->overflow = $res[4] & 0xffff;
}
$return->unsignedInt = $this->unsignedInt;
return $return;
}
/**
* @param ParagonIE_Sodium_Core32_Int64 $right
* @return ParagonIE_Sodium_Core32_Int64
*/
public function mulInt64Fast(ParagonIE_Sodium_Core32_Int64 $right)
{
$aNeg = ($this->limbs[0] >> 15) & 1;
$bNeg = ($right->limbs[0] >> 15) & 1;
$a = array_reverse($this->limbs);
$b = array_reverse($right->limbs);
if ($aNeg) {
for ($i = 0; $i < 4; ++$i) {
$a[$i] = ($a[$i] ^ 0xffff) & 0xffff;
}
++$a[0];
}
if ($bNeg) {
for ($i = 0; $i < 4; ++$i) {
$b[$i] = ($b[$i] ^ 0xffff) & 0xffff;
}
++$b[0];
}
$res = $this->multiplyLong($a, $b);
if ($aNeg !== $bNeg) {
if ($aNeg !== $bNeg) {
for ($i = 0; $i < 4; ++$i) {
$res[$i] = ($res[$i] ^ 0xffff) & 0xffff;
}
$c = 1;
for ($i = 0; $i < 4; ++$i) {
$res[$i] += $c;
$c = $res[$i] >> 16;
$res[$i] &= 0xffff;
}
}
}
$return = new ParagonIE_Sodium_Core32_Int64();
$return->limbs = array(
$res[3] & 0xffff,
$res[2] & 0xffff,
$res[1] & 0xffff,
$res[0] & 0xffff
);
if (count($res) > 4) {
$return->overflow = $res[4];
}
return $return;
}
/**
* @param ParagonIE_Sodium_Core32_Int64 $int
* @param int $size
* @return ParagonIE_Sodium_Core32_Int64
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedAssignment
*/
public function mulInt64(ParagonIE_Sodium_Core32_Int64 $int, $size = 0)
{
if (ParagonIE_Sodium_Compat::$fastMult) {
return $this->mulInt64Fast($int);
}
ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
if (!$size) {
$size = 63;
}
list($a, $b) = self::ctSelect($this, $int);
$return = new ParagonIE_Sodium_Core32_Int64();
$return->unsignedInt = $this->unsignedInt;
// Initialize:
$ret0 = 0;
$ret1 = 0;
$ret2 = 0;
$ret3 = 0;
$a0 = $a->limbs[0];
$a1 = $a->limbs[1];
$a2 = $a->limbs[2];
$a3 = $a->limbs[3];
$b0 = $b->limbs[0];
$b1 = $b->limbs[1];
$b2 = $b->limbs[2];
$b3 = $b->limbs[3];
/** @var int $size */
/** @var int $i */
for ($i = (int) $size; $i >= 0; --$i) {
$mask = -($b3 & 1);
$x0 = $a0 & $mask;
$x1 = $a1 & $mask;
$x2 = $a2 & $mask;
$x3 = $a3 & $mask;
$ret3 += $x3;
$c = $ret3 >> 16;
$ret2 += $x2 + $c;
$c = $ret2 >> 16;
$ret1 += $x1 + $c;
$c = $ret1 >> 16;
$ret0 += $x0 + $c;
$ret0 &= 0xffff;
$ret1 &= 0xffff;
$ret2 &= 0xffff;
$ret3 &= 0xffff;
$a3 = $a3 << 1;
$x3 = $a3 >> 16;
$a2 = ($a2 << 1) | $x3;
$x2 = $a2 >> 16;
$a1 = ($a1 << 1) | $x2;
$x1 = $a1 >> 16;
$a0 = ($a0 << 1) | $x1;
$a0 &= 0xffff;
$a1 &= 0xffff;
$a2 &= 0xffff;
$a3 &= 0xffff;
$x0 = ($b0 & 1) << 16;
$x1 = ($b1 & 1) << 16;
$x2 = ($b2 & 1) << 16;
$b0 = ($b0 >> 1);
$b1 = (($b1 | $x0) >> 1);
$b2 = (($b2 | $x1) >> 1);
$b3 = (($b3 | $x2) >> 1);
$b0 &= 0xffff;
$b1 &= 0xffff;
$b2 &= 0xffff;
$b3 &= 0xffff;
}
$return->limbs[0] = $ret0;
$return->limbs[1] = $ret1;
$return->limbs[2] = $ret2;
$return->limbs[3] = $ret3;
return $return;
}
/**
* OR this 64-bit integer with another.
*
* @param ParagonIE_Sodium_Core32_Int64 $b
* @return ParagonIE_Sodium_Core32_Int64
*/
public function orInt64(ParagonIE_Sodium_Core32_Int64 $b)
{
$return = new ParagonIE_Sodium_Core32_Int64();
$return->unsignedInt = $this->unsignedInt;
$return->limbs = array(
(int) ($this->limbs[0] | $b->limbs[0]),
(int) ($this->limbs[1] | $b->limbs[1]),
(int) ($this->limbs[2] | $b->limbs[2]),
(int) ($this->limbs[3] | $b->limbs[3])
);
return $return;
}
/**
* @param int $c
* @return ParagonIE_Sodium_Core32_Int64
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArrayAccess
*/
public function rotateLeft($c = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
/** @var int $c */
$c = (int) $c;
$return = new ParagonIE_Sodium_Core32_Int64();
$return->unsignedInt = $this->unsignedInt;
$c &= 63;
if ($c === 0) {
// NOP, but we want a copy.
$return->limbs = $this->limbs;
} else {
/** @var array<int, int> $limbs */
$limbs =& $return->limbs;
/** @var array<int, int> $myLimbs */
$myLimbs =& $this->limbs;
/** @var int $idx_shift */
$idx_shift = ($c >> 4) & 3;
/** @var int $sub_shift */
$sub_shift = $c & 15;
for ($i = 3; $i >= 0; --$i) {
/** @var int $j */
$j = ($i + $idx_shift) & 3;
/** @var int $k */
$k = ($i + $idx_shift + 1) & 3;
$limbs[$i] = (int) (
(
((int) ($myLimbs[$j]) << $sub_shift)
|
((int) ($myLimbs[$k]) >> (16 - $sub_shift))
) & 0xffff
);
}
}
return $return;
}
/**
* Rotate to the right
*
* @param int $c
* @return ParagonIE_Sodium_Core32_Int64
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArrayAccess
*/
public function rotateRight($c = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
/** @var int $c */
$c = (int) $c;
/** @var ParagonIE_Sodium_Core32_Int64 $return */
$return = new ParagonIE_Sodium_Core32_Int64();
$return->unsignedInt = $this->unsignedInt;
$c &= 63;
/** @var int $c */
if ($c === 0) {
// NOP, but we want a copy.
$return->limbs = $this->limbs;
} else {
/** @var array<int, int> $limbs */
$limbs =& $return->limbs;
/** @var array<int, int> $myLimbs */
$myLimbs =& $this->limbs;
/** @var int $idx_shift */
$idx_shift = ($c >> 4) & 3;
/** @var int $sub_shift */
$sub_shift = $c & 15;
for ($i = 3; $i >= 0; --$i) {
/** @var int $j */
$j = ($i - $idx_shift) & 3;
/** @var int $k */
$k = ($i - $idx_shift - 1) & 3;
$limbs[$i] = (int) (
(
((int) ($myLimbs[$j]) >> (int) ($sub_shift))
|
((int) ($myLimbs[$k]) << (16 - (int) ($sub_shift)))
) & 0xffff
);
}
}
return $return;
}
/**
* @param int $c
* @return ParagonIE_Sodium_Core32_Int64
* @throws SodiumException
* @throws TypeError
*/
public function shiftLeft($c = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
/** @var int $c */
$c = (int) $c;
$return = new ParagonIE_Sodium_Core32_Int64();
$return->unsignedInt = $this->unsignedInt;
$c &= 63;
if ($c >= 16) {
if ($c >= 48) {
$return->limbs = array(
$this->limbs[3], 0, 0, 0
);
} elseif ($c >= 32) {
$return->limbs = array(
$this->limbs[2], $this->limbs[3], 0, 0
);
} else {
$return->limbs = array(
$this->limbs[1], $this->limbs[2], $this->limbs[3], 0
);
}
return $return->shiftLeft($c & 15);
}
if ($c === 0) {
$return->limbs = $this->limbs;
} elseif ($c < 0) {
/** @var int $c */
return $this->shiftRight(-$c);
} else {
if (!is_int($c)) {
throw new TypeError();
}
/** @var int $carry */
$carry = 0;
for ($i = 3; $i >= 0; --$i) {
/** @var int $tmp */
$tmp = ($this->limbs[$i] << $c) | ($carry & 0xffff);
$return->limbs[$i] = (int) ($tmp & 0xffff);
/** @var int $carry */
$carry = $tmp >> 16;
}
}
return $return;
}
/**
* @param int $c
* @return ParagonIE_Sodium_Core32_Int64
* @throws SodiumException
* @throws TypeError
*/
public function shiftRight($c = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
$c = (int) $c;
/** @var int $c */
$return = new ParagonIE_Sodium_Core32_Int64();
$return->unsignedInt = $this->unsignedInt;
$c &= 63;
$negative = -(($this->limbs[0] >> 15) & 1);
if ($c >= 16) {
if ($c >= 48) {
$return->limbs = array(
(int) ($negative & 0xffff),
(int) ($negative & 0xffff),
(int) ($negative & 0xffff),
(int) $this->limbs[0]
);
} elseif ($c >= 32) {
$return->limbs = array(
(int) ($negative & 0xffff),
(int) ($negative & 0xffff),
(int) $this->limbs[0],
(int) $this->limbs[1]
);
} else {
$return->limbs = array(
(int) ($negative & 0xffff),
(int) $this->limbs[0],
(int) $this->limbs[1],
(int) $this->limbs[2]
);
}
return $return->shiftRight($c & 15);
}
if ($c === 0) {
$return->limbs = $this->limbs;
} elseif ($c < 0) {
return $this->shiftLeft(-$c);
} else {
if (!is_int($c)) {
throw new TypeError();
}
/** @var int $carryRight */
$carryRight = ($negative & 0xffff);
$mask = (int) (((1 << ($c + 1)) - 1) & 0xffff);
for ($i = 0; $i < 4; ++$i) {
$return->limbs[$i] = (int) (
(($this->limbs[$i] >> $c) | ($carryRight << (16 - $c))) & 0xffff
);
$carryRight = (int) ($this->limbs[$i] & $mask);
}
}
return $return;
}
/**
* Subtract a normal integer from an int64 object.
*
* @param int $int
* @return ParagonIE_Sodium_Core32_Int64
* @throws SodiumException
* @throws TypeError
*/
public function subInt($int)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
$int = (int) $int;
$return = new ParagonIE_Sodium_Core32_Int64();
$return->unsignedInt = $this->unsignedInt;
/** @var int $carry */
$carry = 0;
for ($i = 3; $i >= 0; --$i) {
/** @var int $tmp */
$tmp = $this->limbs[$i] - (($int >> 16) & 0xffff) + $carry;
/** @var int $carry */
$carry = $tmp >> 16;
$return->limbs[$i] = (int) ($tmp & 0xffff);
}
return $return;
}
/**
* The difference between two Int64 objects.
*
* @param ParagonIE_Sodium_Core32_Int64 $b
* @return ParagonIE_Sodium_Core32_Int64
*/
public function subInt64(ParagonIE_Sodium_Core32_Int64 $b)
{
$return = new ParagonIE_Sodium_Core32_Int64();
$return->unsignedInt = $this->unsignedInt;
/** @var int $carry */
$carry = 0;
for ($i = 3; $i >= 0; --$i) {
/** @var int $tmp */
$tmp = $this->limbs[$i] - $b->limbs[$i] + $carry;
/** @var int $carry */
$carry = ($tmp >> 16);
$return->limbs[$i] = (int) ($tmp & 0xffff);
}
return $return;
}
/**
* XOR this 64-bit integer with another.
*
* @param ParagonIE_Sodium_Core32_Int64 $b
* @return ParagonIE_Sodium_Core32_Int64
*/
public function xorInt64(ParagonIE_Sodium_Core32_Int64 $b)
{
$return = new ParagonIE_Sodium_Core32_Int64();
$return->unsignedInt = $this->unsignedInt;
$return->limbs = array(
(int) ($this->limbs[0] ^ $b->limbs[0]),
(int) ($this->limbs[1] ^ $b->limbs[1]),
(int) ($this->limbs[2] ^ $b->limbs[2]),
(int) ($this->limbs[3] ^ $b->limbs[3])
);
return $return;
}
/**
* @param int $low
* @param int $high
* @return self
* @throws SodiumException
* @throws TypeError
*/
public static function fromInts($low, $high)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($low, 'int', 1);
ParagonIE_Sodium_Core32_Util::declareScalarType($high, 'int', 2);
$high = (int) $high;
$low = (int) $low;
return new ParagonIE_Sodium_Core32_Int64(
array(
(int) (($high >> 16) & 0xffff),
(int) ($high & 0xffff),
(int) (($low >> 16) & 0xffff),
(int) ($low & 0xffff)
)
);
}
/**
* @param int $low
* @return self
* @throws SodiumException
* @throws TypeError
*/
public static function fromInt($low)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($low, 'int', 1);
$low = (int) $low;
return new ParagonIE_Sodium_Core32_Int64(
array(
0,
0,
(int) (($low >> 16) & 0xffff),
(int) ($low & 0xffff)
)
);
}
/**
* @return int
*/
public function toInt()
{
return (int) (
(($this->limbs[2] & 0xffff) << 16)
|
($this->limbs[3] & 0xffff)
);
}
/**
* @param string $string
* @return self
* @throws SodiumException
* @throws TypeError
*/
public static function fromString($string)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1);
$string = (string) $string;
if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 8) {
throw new RangeException(
'String must be 8 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
);
}
$return = new ParagonIE_Sodium_Core32_Int64();
$return->limbs[0] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff) << 8);
$return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff);
$return->limbs[1] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff) << 8);
$return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff);
$return->limbs[2] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[4]) & 0xff) << 8);
$return->limbs[2] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[5]) & 0xff);
$return->limbs[3] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[6]) & 0xff) << 8);
$return->limbs[3] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[7]) & 0xff);
return $return;
}
/**
* @param string $string
* @return self
* @throws SodiumException
* @throws TypeError
*/
public static function fromReverseString($string)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1);
$string = (string) $string;
if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 8) {
throw new RangeException(
'String must be 8 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
);
}
$return = new ParagonIE_Sodium_Core32_Int64();
$return->limbs[0] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[7]) & 0xff) << 8);
$return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[6]) & 0xff);
$return->limbs[1] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[5]) & 0xff) << 8);
$return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[4]) & 0xff);
$return->limbs[2] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff) << 8);
$return->limbs[2] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff);
$return->limbs[3] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff) << 8);
$return->limbs[3] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff);
return $return;
}
/**
* @return array<int, int>
*/
public function toArray()
{
return array(
(int) ((($this->limbs[0] & 0xffff) << 16) | ($this->limbs[1] & 0xffff)),
(int) ((($this->limbs[2] & 0xffff) << 16) | ($this->limbs[3] & 0xffff))
);
}
/**
* @return ParagonIE_Sodium_Core32_Int32
*/
public function toInt32()
{
$return = new ParagonIE_Sodium_Core32_Int32();
$return->limbs[0] = (int) ($this->limbs[2]);
$return->limbs[1] = (int) ($this->limbs[3]);
$return->unsignedInt = $this->unsignedInt;
$return->overflow = (int) (ParagonIE_Sodium_Core32_Util::abs($this->limbs[1], 16) & 0xffff);
return $return;
}
/**
* @return ParagonIE_Sodium_Core32_Int64
*/
public function toInt64()
{
$return = new ParagonIE_Sodium_Core32_Int64();
$return->limbs[0] = (int) ($this->limbs[0]);
$return->limbs[1] = (int) ($this->limbs[1]);
$return->limbs[2] = (int) ($this->limbs[2]);
$return->limbs[3] = (int) ($this->limbs[3]);
$return->unsignedInt = $this->unsignedInt;
$return->overflow = ParagonIE_Sodium_Core32_Util::abs($this->overflow);
return $return;
}
/**
* @param bool $bool
* @return self
*/
public function setUnsignedInt($bool = false)
{
$this->unsignedInt = !empty($bool);
return $this;
}
/**
* @return string
* @throws TypeError
*/
public function toString()
{
return ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[2] >> 8) & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[3] >> 8) & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] & 0xff);
}
/**
* @return string
* @throws TypeError
*/
public function toReverseString()
{
return ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[3] >> 8) & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[2] >> 8) & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff);
}
/**
* @return string
*/
public function __toString()
{
try {
return $this->toString();
} catch (TypeError $ex) {
// PHP engine can't handle exceptions from __toString()
return '';
}
}
}
Core32/Int32.php 0000644 00000060004 15051413235 0007210 0 ustar 00 <?php
/**
* Class ParagonIE_Sodium_Core32_Int32
*
* Encapsulates a 32-bit integer.
*
* These are immutable. It always returns a new instance.
*/
class ParagonIE_Sodium_Core32_Int32
{
/**
* @var array<int, int> - two 16-bit integers
*
* 0 is the higher 16 bits
* 1 is the lower 16 bits
*/
public $limbs = array(0, 0);
/**
* @var int
*/
public $overflow = 0;
/**
* @var bool
*/
public $unsignedInt = false;
/**
* ParagonIE_Sodium_Core32_Int32 constructor.
* @param array $array
* @param bool $unsignedInt
*/
public function __construct($array = array(0, 0), $unsignedInt = false)
{
$this->limbs = array(
(int) $array[0],
(int) $array[1]
);
$this->overflow = 0;
$this->unsignedInt = $unsignedInt;
}
/**
* Adds two int32 objects
*
* @param ParagonIE_Sodium_Core32_Int32 $addend
* @return ParagonIE_Sodium_Core32_Int32
*/
public function addInt32(ParagonIE_Sodium_Core32_Int32 $addend)
{
$i0 = $this->limbs[0];
$i1 = $this->limbs[1];
$j0 = $addend->limbs[0];
$j1 = $addend->limbs[1];
$r1 = $i1 + ($j1 & 0xffff);
$carry = $r1 >> 16;
$r0 = $i0 + ($j0 & 0xffff) + $carry;
$carry = $r0 >> 16;
$r0 &= 0xffff;
$r1 &= 0xffff;
$return = new ParagonIE_Sodium_Core32_Int32(
array($r0, $r1)
);
$return->overflow = $carry;
$return->unsignedInt = $this->unsignedInt;
return $return;
}
/**
* Adds a normal integer to an int32 object
*
* @param int $int
* @return ParagonIE_Sodium_Core32_Int32
* @throws SodiumException
* @throws TypeError
*/
public function addInt($int)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
/** @var int $int */
$int = (int) $int;
$int = (int) $int;
$i0 = $this->limbs[0];
$i1 = $this->limbs[1];
$r1 = $i1 + ($int & 0xffff);
$carry = $r1 >> 16;
$r0 = $i0 + (($int >> 16) & 0xffff) + $carry;
$carry = $r0 >> 16;
$r0 &= 0xffff;
$r1 &= 0xffff;
$return = new ParagonIE_Sodium_Core32_Int32(
array($r0, $r1)
);
$return->overflow = $carry;
$return->unsignedInt = $this->unsignedInt;
return $return;
}
/**
* @param int $b
* @return int
*/
public function compareInt($b = 0)
{
$gt = 0;
$eq = 1;
$i = 2;
$j = 0;
while ($i > 0) {
--$i;
/** @var int $x1 */
$x1 = $this->limbs[$i];
/** @var int $x2 */
$x2 = ($b >> ($j << 4)) & 0xffff;
/** @var int $gt */
$gt |= (($x2 - $x1) >> 8) & $eq;
/** @var int $eq */
$eq &= (($x2 ^ $x1) - 1) >> 8;
}
return ($gt + $gt - $eq) + 1;
}
/**
* @param int $m
* @return ParagonIE_Sodium_Core32_Int32
*/
public function mask($m = 0)
{
/** @var int $hi */
$hi = ((int) $m >> 16);
$hi &= 0xffff;
/** @var int $lo */
$lo = ((int) $m) & 0xffff;
return new ParagonIE_Sodium_Core32_Int32(
array(
(int) ($this->limbs[0] & $hi),
(int) ($this->limbs[1] & $lo)
),
$this->unsignedInt
);
}
/**
* @param array<int, int> $a
* @param array<int, int> $b
* @param int $baseLog2
* @return array<int, int>
*/
public function multiplyLong(array $a, array $b, $baseLog2 = 16)
{
$a_l = count($a);
$b_l = count($b);
/** @var array<int, int> $r */
$r = array_fill(0, $a_l + $b_l + 1, 0);
$base = 1 << $baseLog2;
for ($i = 0; $i < $a_l; ++$i) {
$a_i = $a[$i];
for ($j = 0; $j < $a_l; ++$j) {
$b_j = $b[$j];
$product = ($a_i * $b_j) + $r[$i + $j];
$carry = ((int) $product >> $baseLog2 & 0xffff);
$r[$i + $j] = ((int) $product - (int) ($carry * $base)) & 0xffff;
$r[$i + $j + 1] += $carry;
}
}
return array_slice($r, 0, 5);
}
/**
* @param int $int
* @return ParagonIE_Sodium_Core32_Int32
*/
public function mulIntFast($int)
{
// Handle negative numbers
$aNeg = ($this->limbs[0] >> 15) & 1;
$bNeg = ($int >> 31) & 1;
$a = array_reverse($this->limbs);
$b = array(
$int & 0xffff,
($int >> 16) & 0xffff
);
if ($aNeg) {
for ($i = 0; $i < 2; ++$i) {
$a[$i] = ($a[$i] ^ 0xffff) & 0xffff;
}
++$a[0];
}
if ($bNeg) {
for ($i = 0; $i < 2; ++$i) {
$b[$i] = ($b[$i] ^ 0xffff) & 0xffff;
}
++$b[0];
}
// Multiply
$res = $this->multiplyLong($a, $b);
// Re-apply negation to results
if ($aNeg !== $bNeg) {
for ($i = 0; $i < 2; ++$i) {
$res[$i] = (0xffff ^ $res[$i]) & 0xffff;
}
// Handle integer overflow
$c = 1;
for ($i = 0; $i < 2; ++$i) {
$res[$i] += $c;
$c = $res[$i] >> 16;
$res[$i] &= 0xffff;
}
}
// Return our values
$return = new ParagonIE_Sodium_Core32_Int32();
$return->limbs = array(
$res[1] & 0xffff,
$res[0] & 0xffff
);
if (count($res) > 2) {
$return->overflow = $res[2] & 0xffff;
}
$return->unsignedInt = $this->unsignedInt;
return $return;
}
/**
* @param ParagonIE_Sodium_Core32_Int32 $right
* @return ParagonIE_Sodium_Core32_Int32
*/
public function mulInt32Fast(ParagonIE_Sodium_Core32_Int32 $right)
{
$aNeg = ($this->limbs[0] >> 15) & 1;
$bNeg = ($right->limbs[0] >> 15) & 1;
$a = array_reverse($this->limbs);
$b = array_reverse($right->limbs);
if ($aNeg) {
for ($i = 0; $i < 2; ++$i) {
$a[$i] = ($a[$i] ^ 0xffff) & 0xffff;
}
++$a[0];
}
if ($bNeg) {
for ($i = 0; $i < 2; ++$i) {
$b[$i] = ($b[$i] ^ 0xffff) & 0xffff;
}
++$b[0];
}
$res = $this->multiplyLong($a, $b);
if ($aNeg !== $bNeg) {
if ($aNeg !== $bNeg) {
for ($i = 0; $i < 2; ++$i) {
$res[$i] = ($res[$i] ^ 0xffff) & 0xffff;
}
$c = 1;
for ($i = 0; $i < 2; ++$i) {
$res[$i] += $c;
$c = $res[$i] >> 16;
$res[$i] &= 0xffff;
}
}
}
$return = new ParagonIE_Sodium_Core32_Int32();
$return->limbs = array(
$res[1] & 0xffff,
$res[0] & 0xffff
);
if (count($res) > 2) {
$return->overflow = $res[2];
}
return $return;
}
/**
* @param int $int
* @param int $size
* @return ParagonIE_Sodium_Core32_Int32
* @throws SodiumException
* @throws TypeError
*/
public function mulInt($int = 0, $size = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
if (ParagonIE_Sodium_Compat::$fastMult) {
return $this->mulIntFast((int) $int);
}
/** @var int $int */
$int = (int) $int;
/** @var int $size */
$size = (int) $size;
if (!$size) {
$size = 31;
}
/** @var int $size */
$a = clone $this;
$return = new ParagonIE_Sodium_Core32_Int32();
$return->unsignedInt = $this->unsignedInt;
// Initialize:
$ret0 = 0;
$ret1 = 0;
$a0 = $a->limbs[0];
$a1 = $a->limbs[1];
/** @var int $size */
/** @var int $i */
for ($i = $size; $i >= 0; --$i) {
$m = (int) (-($int & 1));
$x0 = $a0 & $m;
$x1 = $a1 & $m;
$ret1 += $x1;
$c = $ret1 >> 16;
$ret0 += $x0 + $c;
$ret0 &= 0xffff;
$ret1 &= 0xffff;
$a1 = ($a1 << 1);
$x1 = $a1 >> 16;
$a0 = ($a0 << 1) | $x1;
$a0 &= 0xffff;
$a1 &= 0xffff;
$int >>= 1;
}
$return->limbs[0] = $ret0;
$return->limbs[1] = $ret1;
return $return;
}
/**
* @param ParagonIE_Sodium_Core32_Int32 $int
* @param int $size
* @return ParagonIE_Sodium_Core32_Int32
* @throws SodiumException
* @throws TypeError
*/
public function mulInt32(ParagonIE_Sodium_Core32_Int32 $int, $size = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
if (ParagonIE_Sodium_Compat::$fastMult) {
return $this->mulInt32Fast($int);
}
if (!$size) {
$size = 31;
}
/** @var int $size */
$a = clone $this;
$b = clone $int;
$return = new ParagonIE_Sodium_Core32_Int32();
$return->unsignedInt = $this->unsignedInt;
// Initialize:
$ret0 = 0;
$ret1 = 0;
$a0 = $a->limbs[0];
$a1 = $a->limbs[1];
$b0 = $b->limbs[0];
$b1 = $b->limbs[1];
/** @var int $size */
/** @var int $i */
for ($i = $size; $i >= 0; --$i) {
$m = (int) (-($b1 & 1));
$x0 = $a0 & $m;
$x1 = $a1 & $m;
$ret1 += $x1;
$c = $ret1 >> 16;
$ret0 += $x0 + $c;
$ret0 &= 0xffff;
$ret1 &= 0xffff;
$a1 = ($a1 << 1);
$x1 = $a1 >> 16;
$a0 = ($a0 << 1) | $x1;
$a0 &= 0xffff;
$a1 &= 0xffff;
$x0 = ($b0 & 1) << 16;
$b0 = ($b0 >> 1);
$b1 = (($b1 | $x0) >> 1);
$b0 &= 0xffff;
$b1 &= 0xffff;
}
$return->limbs[0] = $ret0;
$return->limbs[1] = $ret1;
return $return;
}
/**
* OR this 32-bit integer with another.
*
* @param ParagonIE_Sodium_Core32_Int32 $b
* @return ParagonIE_Sodium_Core32_Int32
*/
public function orInt32(ParagonIE_Sodium_Core32_Int32 $b)
{
$return = new ParagonIE_Sodium_Core32_Int32();
$return->unsignedInt = $this->unsignedInt;
$return->limbs = array(
(int) ($this->limbs[0] | $b->limbs[0]),
(int) ($this->limbs[1] | $b->limbs[1])
);
/** @var int overflow */
$return->overflow = $this->overflow | $b->overflow;
return $return;
}
/**
* @param int $b
* @return bool
*/
public function isGreaterThan($b = 0)
{
return $this->compareInt($b) > 0;
}
/**
* @param int $b
* @return bool
*/
public function isLessThanInt($b = 0)
{
return $this->compareInt($b) < 0;
}
/**
* @param int $c
* @return ParagonIE_Sodium_Core32_Int32
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArrayAccess
*/
public function rotateLeft($c = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
/** @var int $c */
$c = (int) $c;
$return = new ParagonIE_Sodium_Core32_Int32();
$return->unsignedInt = $this->unsignedInt;
$c &= 31;
if ($c === 0) {
// NOP, but we want a copy.
$return->limbs = $this->limbs;
} else {
/** @var int $c */
/** @var int $idx_shift */
$idx_shift = ($c >> 4) & 1;
/** @var int $sub_shift */
$sub_shift = $c & 15;
/** @var array<int, int> $limbs */
$limbs =& $return->limbs;
/** @var array<int, int> $myLimbs */
$myLimbs =& $this->limbs;
for ($i = 1; $i >= 0; --$i) {
/** @var int $j */
$j = ($i + $idx_shift) & 1;
/** @var int $k */
$k = ($i + $idx_shift + 1) & 1;
$limbs[$i] = (int) (
(
((int) ($myLimbs[$j]) << $sub_shift)
|
((int) ($myLimbs[$k]) >> (16 - $sub_shift))
) & 0xffff
);
}
}
return $return;
}
/**
* Rotate to the right
*
* @param int $c
* @return ParagonIE_Sodium_Core32_Int32
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedArrayAccess
*/
public function rotateRight($c = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
/** @var int $c */
$c = (int) $c;
$return = new ParagonIE_Sodium_Core32_Int32();
$return->unsignedInt = $this->unsignedInt;
$c &= 31;
/** @var int $c */
if ($c === 0) {
// NOP, but we want a copy.
$return->limbs = $this->limbs;
} else {
/** @var int $c */
/** @var int $idx_shift */
$idx_shift = ($c >> 4) & 1;
/** @var int $sub_shift */
$sub_shift = $c & 15;
/** @var array<int, int> $limbs */
$limbs =& $return->limbs;
/** @var array<int, int> $myLimbs */
$myLimbs =& $this->limbs;
for ($i = 1; $i >= 0; --$i) {
/** @var int $j */
$j = ($i - $idx_shift) & 1;
/** @var int $k */
$k = ($i - $idx_shift - 1) & 1;
$limbs[$i] = (int) (
(
((int) ($myLimbs[$j]) >> (int) ($sub_shift))
|
((int) ($myLimbs[$k]) << (16 - (int) ($sub_shift)))
) & 0xffff
);
}
}
return $return;
}
/**
* @param bool $bool
* @return self
*/
public function setUnsignedInt($bool = false)
{
$this->unsignedInt = !empty($bool);
return $this;
}
/**
* @param int $c
* @return ParagonIE_Sodium_Core32_Int32
* @throws SodiumException
* @throws TypeError
*/
public function shiftLeft($c = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
/** @var int $c */
$c = (int) $c;
$return = new ParagonIE_Sodium_Core32_Int32();
$return->unsignedInt = $this->unsignedInt;
$c &= 63;
/** @var int $c */
if ($c === 0) {
$return->limbs = $this->limbs;
} elseif ($c < 0) {
/** @var int $c */
return $this->shiftRight(-$c);
} else {
/** @var int $c */
/** @var int $tmp */
$tmp = $this->limbs[1] << $c;
$return->limbs[1] = (int)($tmp & 0xffff);
/** @var int $carry */
$carry = $tmp >> 16;
/** @var int $tmp */
$tmp = ($this->limbs[0] << $c) | ($carry & 0xffff);
$return->limbs[0] = (int) ($tmp & 0xffff);
}
return $return;
}
/**
* @param int $c
* @return ParagonIE_Sodium_Core32_Int32
* @throws SodiumException
* @throws TypeError
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedOperand
*/
public function shiftRight($c = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
/** @var int $c */
$c = (int) $c;
$return = new ParagonIE_Sodium_Core32_Int32();
$return->unsignedInt = $this->unsignedInt;
$c &= 63;
/** @var int $c */
if ($c >= 16) {
$return->limbs = array(
(int) ($this->overflow & 0xffff),
(int) ($this->limbs[0])
);
$return->overflow = $this->overflow >> 16;
return $return->shiftRight($c & 15);
}
if ($c === 0) {
$return->limbs = $this->limbs;
} elseif ($c < 0) {
/** @var int $c */
return $this->shiftLeft(-$c);
} else {
if (!is_int($c)) {
throw new TypeError();
}
/** @var int $c */
// $return->limbs[0] = (int) (($this->limbs[0] >> $c) & 0xffff);
$carryLeft = (int) ($this->overflow & ((1 << ($c + 1)) - 1));
$return->limbs[0] = (int) ((($this->limbs[0] >> $c) | ($carryLeft << (16 - $c))) & 0xffff);
$carryRight = (int) ($this->limbs[0] & ((1 << ($c + 1)) - 1));
$return->limbs[1] = (int) ((($this->limbs[1] >> $c) | ($carryRight << (16 - $c))) & 0xffff);
$return->overflow >>= $c;
}
return $return;
}
/**
* Subtract a normal integer from an int32 object.
*
* @param int $int
* @return ParagonIE_Sodium_Core32_Int32
* @throws SodiumException
* @throws TypeError
*/
public function subInt($int)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
/** @var int $int */
$int = (int) $int;
$return = new ParagonIE_Sodium_Core32_Int32();
$return->unsignedInt = $this->unsignedInt;
/** @var int $tmp */
$tmp = $this->limbs[1] - ($int & 0xffff);
/** @var int $carry */
$carry = $tmp >> 16;
$return->limbs[1] = (int) ($tmp & 0xffff);
/** @var int $tmp */
$tmp = $this->limbs[0] - (($int >> 16) & 0xffff) + $carry;
$return->limbs[0] = (int) ($tmp & 0xffff);
return $return;
}
/**
* Subtract two int32 objects from each other
*
* @param ParagonIE_Sodium_Core32_Int32 $b
* @return ParagonIE_Sodium_Core32_Int32
*/
public function subInt32(ParagonIE_Sodium_Core32_Int32 $b)
{
$return = new ParagonIE_Sodium_Core32_Int32();
$return->unsignedInt = $this->unsignedInt;
/** @var int $tmp */
$tmp = $this->limbs[1] - ($b->limbs[1] & 0xffff);
/** @var int $carry */
$carry = $tmp >> 16;
$return->limbs[1] = (int) ($tmp & 0xffff);
/** @var int $tmp */
$tmp = $this->limbs[0] - ($b->limbs[0] & 0xffff) + $carry;
$return->limbs[0] = (int) ($tmp & 0xffff);
return $return;
}
/**
* XOR this 32-bit integer with another.
*
* @param ParagonIE_Sodium_Core32_Int32 $b
* @return ParagonIE_Sodium_Core32_Int32
*/
public function xorInt32(ParagonIE_Sodium_Core32_Int32 $b)
{
$return = new ParagonIE_Sodium_Core32_Int32();
$return->unsignedInt = $this->unsignedInt;
$return->limbs = array(
(int) ($this->limbs[0] ^ $b->limbs[0]),
(int) ($this->limbs[1] ^ $b->limbs[1])
);
return $return;
}
/**
* @param int $signed
* @return self
* @throws SodiumException
* @throws TypeError
*/
public static function fromInt($signed)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($signed, 'int', 1);;
/** @var int $signed */
$signed = (int) $signed;
return new ParagonIE_Sodium_Core32_Int32(
array(
(int) (($signed >> 16) & 0xffff),
(int) ($signed & 0xffff)
)
);
}
/**
* @param string $string
* @return self
* @throws SodiumException
* @throws TypeError
*/
public static function fromString($string)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1);
$string = (string) $string;
if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 4) {
throw new RangeException(
'String must be 4 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
);
}
$return = new ParagonIE_Sodium_Core32_Int32();
$return->limbs[0] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff) << 8);
$return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff);
$return->limbs[1] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff) << 8);
$return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff);
return $return;
}
/**
* @param string $string
* @return self
* @throws SodiumException
* @throws TypeError
*/
public static function fromReverseString($string)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1);
$string = (string) $string;
if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 4) {
throw new RangeException(
'String must be 4 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
);
}
$return = new ParagonIE_Sodium_Core32_Int32();
$return->limbs[0] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff) << 8);
$return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff);
$return->limbs[1] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff) << 8);
$return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff);
return $return;
}
/**
* @return array<int, int>
*/
public function toArray()
{
return array((int) ($this->limbs[0] << 16 | $this->limbs[1]));
}
/**
* @return string
* @throws TypeError
*/
public function toString()
{
return
ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff);
}
/**
* @return int
*/
public function toInt()
{
return (int) (
(($this->limbs[0] & 0xffff) << 16)
|
($this->limbs[1] & 0xffff)
);
}
/**
* @return ParagonIE_Sodium_Core32_Int32
*/
public function toInt32()
{
$return = new ParagonIE_Sodium_Core32_Int32();
$return->limbs[0] = (int) ($this->limbs[0] & 0xffff);
$return->limbs[1] = (int) ($this->limbs[1] & 0xffff);
$return->unsignedInt = $this->unsignedInt;
$return->overflow = (int) ($this->overflow & 0x7fffffff);
return $return;
}
/**
* @return ParagonIE_Sodium_Core32_Int64
*/
public function toInt64()
{
$return = new ParagonIE_Sodium_Core32_Int64();
$return->unsignedInt = $this->unsignedInt;
if ($this->unsignedInt) {
$return->limbs[0] += (($this->overflow >> 16) & 0xffff);
$return->limbs[1] += (($this->overflow) & 0xffff);
} else {
$neg = -(($this->limbs[0] >> 15) & 1);
$return->limbs[0] = (int)($neg & 0xffff);
$return->limbs[1] = (int)($neg & 0xffff);
}
$return->limbs[2] = (int) ($this->limbs[0] & 0xffff);
$return->limbs[3] = (int) ($this->limbs[1] & 0xffff);
return $return;
}
/**
* @return string
* @throws TypeError
*/
public function toReverseString()
{
return ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) .
ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff);
}
/**
* @return string
*/
public function __toString()
{
try {
return $this->toString();
} catch (TypeError $ex) {
// PHP engine can't handle exceptions from __toString()
return '';
}
}
}
Core32/ChaCha20/Ctx.php 0000644 00000011450 15051413235 0010321 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core_ChaCha20_Ctx', false)) {
return;
}
/**
* Class ParagonIE_Sodium_Core32_ChaCha20_Ctx
*/
class ParagonIE_Sodium_Core32_ChaCha20_Ctx extends ParagonIE_Sodium_Core32_Util implements ArrayAccess
{
/**
* @var SplFixedArray internally, <int, ParagonIE_Sodium_Core32_Int32>
*/
protected $container;
/**
* ParagonIE_Sodium_Core_ChaCha20_Ctx constructor.
*
* @internal You should not use this directly from another application
*
* @param string $key ChaCha20 key.
* @param string $iv Initialization Vector (a.k.a. nonce).
* @param string $counter The initial counter value.
* Defaults to 8 0x00 bytes.
* @throws InvalidArgumentException
* @throws SodiumException
* @throws TypeError
*/
public function __construct($key = '', $iv = '', $counter = '')
{
if (self::strlen($key) !== 32) {
throw new InvalidArgumentException('ChaCha20 expects a 256-bit key.');
}
if (self::strlen($iv) !== 8) {
throw new InvalidArgumentException('ChaCha20 expects a 64-bit nonce.');
}
$this->container = new SplFixedArray(16);
/* "expand 32-byte k" as per ChaCha20 spec */
$this->container[0] = new ParagonIE_Sodium_Core32_Int32(array(0x6170, 0x7865));
$this->container[1] = new ParagonIE_Sodium_Core32_Int32(array(0x3320, 0x646e));
$this->container[2] = new ParagonIE_Sodium_Core32_Int32(array(0x7962, 0x2d32));
$this->container[3] = new ParagonIE_Sodium_Core32_Int32(array(0x6b20, 0x6574));
$this->container[4] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4));
$this->container[5] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 4, 4));
$this->container[6] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 8, 4));
$this->container[7] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12, 4));
$this->container[8] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16, 4));
$this->container[9] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20, 4));
$this->container[10] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24, 4));
$this->container[11] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28, 4));
if (empty($counter)) {
$this->container[12] = new ParagonIE_Sodium_Core32_Int32();
$this->container[13] = new ParagonIE_Sodium_Core32_Int32();
} else {
$this->container[12] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($counter, 0, 4));
$this->container[13] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($counter, 4, 4));
}
$this->container[14] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 0, 4));
$this->container[15] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 4, 4));
}
/**
* @internal You should not use this directly from another application
*
* @param int $offset
* @param int|ParagonIE_Sodium_Core32_Int32 $value
* @return void
*/
#[ReturnTypeWillChange]
public function offsetSet($offset, $value)
{
if (!is_int($offset)) {
throw new InvalidArgumentException('Expected an integer');
}
if ($value instanceof ParagonIE_Sodium_Core32_Int32) {
/*
} elseif (is_int($value)) {
$value = ParagonIE_Sodium_Core32_Int32::fromInt($value);
*/
} else {
throw new InvalidArgumentException('Expected an integer');
}
$this->container[$offset] = $value;
}
/**
* @internal You should not use this directly from another application
*
* @param int $offset
* @return bool
* @psalm-suppress MixedArrayOffset
*/
#[ReturnTypeWillChange]
public function offsetExists($offset)
{
return isset($this->container[$offset]);
}
/**
* @internal You should not use this directly from another application
*
* @param int $offset
* @return void
* @psalm-suppress MixedArrayOffset
*/
#[ReturnTypeWillChange]
public function offsetUnset($offset)
{
unset($this->container[$offset]);
}
/**
* @internal You should not use this directly from another application
*
* @param int $offset
* @return mixed|null
* @psalm-suppress MixedArrayOffset
*/
#[ReturnTypeWillChange]
public function offsetGet($offset)
{
return isset($this->container[$offset])
? $this->container[$offset]
: null;
}
}
Core32/ChaCha20/IetfCtx.php 0000644 00000002737 15051413235 0011141 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core_ChaCha20_IetfCtx', false)) {
return;
}
/**
* Class ParagonIE_Sodium_Core32_ChaCha20_IetfCtx
*/
class ParagonIE_Sodium_Core32_ChaCha20_IetfCtx extends ParagonIE_Sodium_Core32_ChaCha20_Ctx
{
/**
* ParagonIE_Sodium_Core_ChaCha20_IetfCtx constructor.
*
* @internal You should not use this directly from another application
*
* @param string $key ChaCha20 key.
* @param string $iv Initialization Vector (a.k.a. nonce).
* @param string $counter The initial counter value.
* Defaults to 4 0x00 bytes.
* @throws InvalidArgumentException
* @throws SodiumException
* @throws TypeError
*/
public function __construct($key = '', $iv = '', $counter = '')
{
if (self::strlen($iv) !== 12) {
throw new InvalidArgumentException('ChaCha20 expects a 96-bit nonce in IETF mode.');
}
parent::__construct($key, self::substr($iv, 0, 8), $counter);
if (!empty($counter)) {
$this->container[12] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($counter, 0, 4));
}
$this->container[13] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 0, 4));
$this->container[14] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 4, 4));
$this->container[15] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 8, 4));
}
}
Core32/ChaCha20/error_log 0000644 00000001330 15051413235 0010763 0 ustar 00 [19-Aug-2025 17:26:06 UTC] PHP Fatal error: Uncaught Error: Class 'ParagonIE_Sodium_Core32_Util' not found in /home/deltahospital/test.delta-hospital.com/wp-includes/sodium_compat/src/Core32/ChaCha20/Ctx.php:10
Stack trace:
#0 {main}
thrown in /home/deltahospital/test.delta-hospital.com/wp-includes/sodium_compat/src/Core32/ChaCha20/Ctx.php on line 10
[19-Aug-2025 17:29:04 UTC] PHP Fatal error: Uncaught Error: Class 'ParagonIE_Sodium_Core32_ChaCha20_Ctx' not found in /home/deltahospital/test.delta-hospital.com/wp-includes/sodium_compat/src/Core32/ChaCha20/IetfCtx.php:10
Stack trace:
#0 {main}
thrown in /home/deltahospital/test.delta-hospital.com/wp-includes/sodium_compat/src/Core32/ChaCha20/IetfCtx.php on line 10
Core32/Ed25519.php 0000644 00000036567 15051413235 0007270 0 ustar 00 <?php
if (class_exists('ParagonIE_Sodium_Core32_Ed25519', false)) {
return;
}
if (!class_exists('ParagonIE_Sodium_Core32_Curve25519')) {
require_once dirname(__FILE__) . '/Curve25519.php';
}
/**
* Class ParagonIE_Sodium_Core32_Ed25519
*/
abstract class ParagonIE_Sodium_Core32_Ed25519 extends ParagonIE_Sodium_Core32_Curve25519
{
const KEYPAIR_BYTES = 96;
const SEED_BYTES = 32;
/**
* @internal You should not use this directly from another application
*
* @return string (96 bytes)
* @throws Exception
* @throws SodiumException
* @throws TypeError
*/
public static function keypair()
{
$seed = random_bytes(self::SEED_BYTES);
$pk = '';
$sk = '';
self::seed_keypair($pk, $sk, $seed);
return $sk . $pk;
}
/**
* @internal You should not use this directly from another application
*
* @param string $pk
* @param string $sk
* @param string $seed
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function seed_keypair(&$pk, &$sk, $seed)
{
if (self::strlen($seed) !== self::SEED_BYTES) {
throw new RangeException('crypto_sign keypair seed must be 32 bytes long');
}
/** @var string $pk */
$pk = self::publickey_from_secretkey($seed);
$sk = $seed . $pk;
return $sk;
}
/**
* @internal You should not use this directly from another application
*
* @param string $keypair
* @return string
* @throws TypeError
*/
public static function secretkey($keypair)
{
if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
throw new RangeException('crypto_sign keypair must be 96 bytes long');
}
return self::substr($keypair, 0, 64);
}
/**
* @internal You should not use this directly from another application
*
* @param string $keypair
* @return string
* @throws RangeException
* @throws TypeError
*/
public static function publickey($keypair)
{
if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
throw new RangeException('crypto_sign keypair must be 96 bytes long');
}
return self::substr($keypair, 64, 32);
}
/**
* @internal You should not use this directly from another application
*
* @param string $sk
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function publickey_from_secretkey($sk)
{
/** @var string $sk */
$sk = hash('sha512', self::substr($sk, 0, 32), true);
$sk[0] = self::intToChr(
self::chrToInt($sk[0]) & 248
);
$sk[31] = self::intToChr(
(self::chrToInt($sk[31]) & 63) | 64
);
return self::sk_to_pk($sk);
}
/**
* @param string $pk
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function pk_to_curve25519($pk)
{
if (self::small_order($pk)) {
throw new SodiumException('Public key is on a small order');
}
$A = self::ge_frombytes_negate_vartime($pk);
$p1 = self::ge_mul_l($A);
if (!self::fe_isnonzero($p1->X)) {
throw new SodiumException('Unexpected zero result');
}
# fe_1(one_minus_y);
# fe_sub(one_minus_y, one_minus_y, A.Y);
# fe_invert(one_minus_y, one_minus_y);
$one_minux_y = self::fe_invert(
self::fe_sub(
self::fe_1(),
$A->Y
)
);
# fe_1(x);
# fe_add(x, x, A.Y);
# fe_mul(x, x, one_minus_y);
$x = self::fe_mul(
self::fe_add(self::fe_1(), $A->Y),
$one_minux_y
);
# fe_tobytes(curve25519_pk, x);
return self::fe_tobytes($x);
}
/**
* @internal You should not use this directly from another application
*
* @param string $sk
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function sk_to_pk($sk)
{
return self::ge_p3_tobytes(
self::ge_scalarmult_base(
self::substr($sk, 0, 32)
)
);
}
/**
* @internal You should not use this directly from another application
*
* @param string $message
* @param string $sk
* @return string
* @throws SodiumException
* @throws TypeError
*/
public static function sign($message, $sk)
{
/** @var string $signature */
$signature = self::sign_detached($message, $sk);
return $signature . $message;
}
/**
* @internal You should not use this directly from another application
*
* @param string $message A signed message
* @param string $pk Public key
* @return string Message (without signature)
* @throws SodiumException
* @throws TypeError
*/
public static function sign_open($message, $pk)
{
/** @var string $signature */
$signature = self::substr($message, 0, 64);
/** @var string $message */
$message = self::substr($message, 64);
if (self::verify_detached($signature, $message, $pk)) {
return $message;
}
throw new SodiumException('Invalid signature');
}
/**
* @internal You should not use this directly from another application
*
* @param string $message
* @param string $sk
* @return string
* @throws SodiumException
* @throws TypeError
* @psalm-suppress PossiblyInvalidArgument
*/
public static function sign_detached($message, $sk)
{
# crypto_hash_sha512(az, sk, 32);
$az = hash('sha512', self::substr($sk, 0, 32), true);
# az[0] &= 248;
# az[31] &= 63;
# az[31] |= 64;
$az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
$az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);
# crypto_hash_sha512_init(&hs);
# crypto_hash_sha512_update(&hs, az + 32, 32);
# crypto_hash_sha512_update(&hs, m, mlen);
# crypto_hash_sha512_final(&hs, nonce);
$hs = hash_init('sha512');
self::hash_update($hs, self::substr($az, 32, 32));
self::hash_update($hs, $message);
$nonceHash = hash_final($hs, true);
# memmove(sig + 32, sk + 32, 32);
$pk = self::substr($sk, 32, 32);
# sc_reduce(nonce);
# ge_scalarmult_base(&R, nonce);
# ge_p3_tobytes(sig, &R);
$nonce = self::sc_reduce($nonceHash) . self::substr($nonceHash, 32);
$sig = self::ge_p3_tobytes(
self::ge_scalarmult_base($nonce)
);
# crypto_hash_sha512_init(&hs);
# crypto_hash_sha512_update(&hs, sig, 64);
# crypto_hash_sha512_update(&hs, m, mlen);
# crypto_hash_sha512_final(&hs, hram);
$hs = hash_init('sha512');
self::hash_update($hs, self::substr($sig, 0, 32));
self::hash_update($hs, self::substr($pk, 0, 32));
self::hash_update($hs, $message);
$hramHash = hash_final($hs, true);
# sc_reduce(hram);
# sc_muladd(sig + 32, hram, az, nonce);
$hram = self::sc_reduce($hramHash);
$sigAfter = self::sc_muladd($hram, $az, $nonce);
$sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);
try {
ParagonIE_Sodium_Compat::memzero($az);
} catch (SodiumException $ex) {
$az = null;
}
return $sig;
}
/**
* @internal You should not use this directly from another application
*
* @param string $sig
* @param string $message
* @param string $pk
* @return bool
* @throws SodiumException
* @throws TypeError
*/
public static function verify_detached($sig, $message, $pk)
{
if (self::strlen($sig) < 64) {
throw new SodiumException('Signature is too short');
}
if ((self::chrToInt($sig[63]) & 240)