PK!ӈOO Crypto32.phpnu[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 */ $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 */ $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 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); } } PK!lSodiumException.phpnu[ */ private $internalArray = array(); /** @var int $size */ private $size = 0; /** * SplFixedArray constructor. * @param int $size */ public function __construct($size = 0) { $this->size = $size; $this->internalArray = array(); } /** * @return int */ public function count() { return count($this->internalArray); } /** * @return array */ public function toArray() { ksort($this->internalArray); return (array) $this->internalArray; } /** * @param array $array * @param bool $save_indexes * @return SplFixedArray * @psalm-suppress MixedAssignment */ public static function fromArray(array $array, $save_indexes = true) { $self = new SplFixedArray(count($array)); if($save_indexes) { foreach($array as $key => $value) { $self[(int) $key] = $value; } } else { $i = 0; foreach (array_values($array) as $value) { $self[$i] = $value; $i++; } } return $self; } /** * @return int */ public function getSize() { return $this->size; } /** * @param int $size * @return bool */ public function setSize($size) { $this->size = $size; return true; } /** * @param string|int $index * @return bool */ public function offsetExists($index) { return array_key_exists((int) $index, $this->internalArray); } /** * @param string|int $index * @return mixed */ public function offsetGet($index) { /** @psalm-suppress MixedReturnStatement */ return $this->internalArray[(int) $index]; } /** * @param string|int $index * @param mixed $newval * @psalm-suppress MixedAssignment */ public function offsetSet($index, $newval) { $this->internalArray[(int) $index] = $newval; } /** * @param string|int $index */ public function offsetUnset($index) { unset($this->internalArray[(int) $index]); } /** * Rewind iterator back to the start * @link https://php.net/manual/en/splfixedarray.rewind.php * @return void * @since 5.3.0 */ public function rewind() { reset($this->internalArray); } /** * Return current array entry * @link https://php.net/manual/en/splfixedarray.current.php * @return mixed The current element value. * @since 5.3.0 */ public function current() { /** @psalm-suppress MixedReturnStatement */ return current($this->internalArray); } /** * Return current array index * @return int The current array index. */ public function key() { return key($this->internalArray); } /** * @return void */ public function next() { next($this->internalArray); } /** * Check whether the array contains more elements * @link https://php.net/manual/en/splfixedarray.valid.php * @return bool true if the array contains any more elements, false otherwise. */ public function valid() { if (empty($this->internalArray)) { return false; } $result = next($this->internalArray) !== false; prev($this->internalArray); return $result; } /** * Do nothing. */ public function __wakeup() { // NOP } }PK!"((Core/SecretStream/State.phpnu[key = $key; $this->counter = 1; if (is_null($nonce)) { $nonce = str_repeat("\0", 12); } $this->nonce = str_pad($nonce, 12, "\0", STR_PAD_RIGHT);; $this->_pad = str_repeat("\0", 4); } /** * @return self */ public function counterReset() { $this->counter = 1; $this->_pad = str_repeat("\0", 4); return $this; } /** * @return string */ public function getKey() { return $this->key; } /** * @return string */ public function getCounter() { return ParagonIE_Sodium_Core_Util::store32_le($this->counter); } /** * @return string */ public function getNonce() { if (!is_string($this->nonce)) { $this->nonce = str_repeat("\0", 12); } if (ParagonIE_Sodium_Core_Util::strlen($this->nonce) !== 12) { $this->nonce = str_pad($this->nonce, 12, "\0", STR_PAD_RIGHT); } return $this->nonce; } /** * @return string */ public function getCombinedNonce() { return $this->getCounter() . ParagonIE_Sodium_Core_Util::substr($this->getNonce(), 0, 8); } /** * @return self */ public function incrementCounter() { ++$this->counter; return $this; } /** * @return bool */ public function needsRekey() { return ($this->counter & 0xffff) === 0; } /** * @param string $newKeyAndNonce * @return self */ public function rekey($newKeyAndNonce) { $this->key = ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 0, 32); $this->nonce = str_pad( ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 32), 12, "\0", STR_PAD_RIGHT ); return $this; } /** * @param string $str * @return self */ public function xorNonce($str) { $this->nonce = ParagonIE_Sodium_Core_Util::xorStrings( $this->getNonce(), str_pad( ParagonIE_Sodium_Core_Util::substr($str, 0, 8), 12, "\0", STR_PAD_RIGHT ) ); return $this; } /** * @param string $string * @return self */ public static function fromString($string) { $state = new ParagonIE_Sodium_Core_SecretStream_State( ParagonIE_Sodium_Core_Util::substr($string, 0, 32) ); $state->counter = ParagonIE_Sodium_Core_Util::load_4( ParagonIE_Sodium_Core_Util::substr($string, 32, 4) ); $state->nonce = ParagonIE_Sodium_Core_Util::substr($string, 36, 12); $state->_pad = ParagonIE_Sodium_Core_Util::substr($string, 48, 8); return $state; } /** * @return string */ public function toString() { return $this->key . $this->getCounter() . $this->nonce . $this->_pad; } } PK!]iu) ) Core/SipHash.phpnu[ */ public static function add(array $a, array $b) { /** @var int $x1 */ $x1 = $a[1] + $b[1]; /** @var int $c */ $c = $x1 >> 32; // Carry if ($a + $b) > 0xffffffff /** @var int $x0 */ $x0 = $a[0] + $b[0] + $c; return array( $x0 & 0xffffffff, $x1 & 0xffffffff ); } /** * @internal You should not use this directly from another application * * @param int $int0 * @param int $int1 * @param int $c * @return array */ public static function rotl_64($int0, $int1, $c) { $int0 &= 0xffffffff; $int1 &= 0xffffffff; $c &= 63; if ($c === 32) { return array($int1, $int0); } if ($c > 31) { $tmp = $int1; $int1 = $int0; $int0 = $tmp; $c &= 31; } if ($c === 0) { return array($int0, $int1); } return array( 0xffffffff & ( ($int0 << $c) | ($int1 >> (32 - $c)) ), 0xffffffff & ( ($int1 << $c) | ($int0 >> (32 - $c)) ), ); } /** * Implements Siphash-2-4 using only 32-bit numbers. * * When we split an int into two, the higher bits go to the lower index. * e.g. 0xDEADBEEFAB10C92D becomes [ * 0 => 0xDEADBEEF, * 1 => 0xAB10C92D * ]. * * @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( 0x736f6d65, // 0 0x70736575, // 1 0x646f7261, // 2 0x6e646f6d, // 3 0x6c796765, // 4 0x6e657261, // 5 0x74656462, // 6 0x79746573 // 7 ); // v0 => $v[0], $v[1] // v1 => $v[2], $v[3] // v2 => $v[4], $v[5] // v3 => $v[6], $v[7] # u64 k0 = LOAD64_LE( k ); # u64 k1 = LOAD64_LE( k + 8 ); $k = array( self::load_4(self::substr($key, 4, 4)), self::load_4(self::substr($key, 0, 4)), self::load_4(self::substr($key, 12, 4)), self::load_4(self::substr($key, 8, 4)) ); // k0 => $k[0], $k[1] // k1 => $k[2], $k[3] # b = ( ( u64 )inlen ) << 56; $b = array( $inlen << 24, 0 ); // See docblock for why the 0th index gets the higher bits. # v3 ^= k1; $v[6] ^= $k[2]; $v[7] ^= $k[3]; # v2 ^= k0; $v[4] ^= $k[0]; $v[5] ^= $k[1]; # v1 ^= k1; $v[2] ^= $k[2]; $v[3] ^= $k[3]; # v0 ^= k0; $v[0] ^= $k[0]; $v[1] ^= $k[1]; $left = $inlen; # for ( ; in != end; in += 8 ) while ($left >= 8) { # m = LOAD64_LE( in ); $m = array( self::load_4(self::substr($in, 4, 4)), self::load_4(self::substr($in, 0, 4)) ); # v3 ^= m; $v[6] ^= $m[0]; $v[7] ^= $m[1]; # SIPROUND; # SIPROUND; $v = self::sipRound($v); $v = self::sipRound($v); # v0 ^= m; $v[0] ^= $m[0]; $v[1] ^= $m[1]; $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[0] |= self::chrToInt($in[6]) << 16; case 6: $b[0] |= self::chrToInt($in[5]) << 8; case 5: $b[0] |= self::chrToInt($in[4]); case 4: $b[1] |= self::chrToInt($in[3]) << 24; case 3: $b[1] |= self::chrToInt($in[2]) << 16; case 2: $b[1] |= self::chrToInt($in[1]) << 8; case 1: $b[1] |= self::chrToInt($in[0]); case 0: break; } // See docblock for why the 0th index gets the higher bits. # v3 ^= b; $v[6] ^= $b[0]; $v[7] ^= $b[1]; # SIPROUND; # SIPROUND; $v = self::sipRound($v); $v = self::sipRound($v); # v0 ^= b; $v[0] ^= $b[0]; $v[1] ^= $b[1]; // Flip the lower 8 bits of v2 which is ($v[4], $v[5]) in our implementation # v2 ^= 0xff; $v[5] ^= 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 self::store32_le($v[1] ^ $v[3] ^ $v[5] ^ $v[7]) . self::store32_le($v[0] ^ $v[2] ^ $v[4] ^ $v[6]); } } PK!k &p2p2Core/Poly1305/State.phpnu[ */ protected $buffer = array(); /** * @var bool */ protected $final = false; /** * @var array */ public $h; /** * @var int */ protected $leftover = 0; /** * @var int[] */ public $r; /** * @var int[] */ public $pad; /** * ParagonIE_Sodium_Core_Poly1305_State constructor. * * @internal You should not use this directly from another application * * @param string $key * @throws InvalidArgumentException * @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( (int) ((self::load_4(self::substr($key, 0, 4))) & 0x3ffffff), (int) ((self::load_4(self::substr($key, 3, 4)) >> 2) & 0x3ffff03), (int) ((self::load_4(self::substr($key, 6, 4)) >> 4) & 0x3ffc0ff), (int) ((self::load_4(self::substr($key, 9, 4)) >> 6) & 0x3f03fff), (int) ((self::load_4(self::substr($key, 12, 4)) >> 8) & 0x00fffff) ); /* h = 0 */ $this->h = array(0, 0, 0, 0, 0); /* save pad for later */ $this->pad = array( self::load_4(self::substr($key, 16, 4)), self::load_4(self::substr($key, 20, 4)), self::load_4(self::substr($key, 24, 4)), self::load_4(self::substr($key, 28, 4)), ); $this->leftover = 0; $this->final = false; } /** * Zero internal buffer upon destruction */ public function __destruct() { $this->r[0] ^= $this->r[0]; $this->r[1] ^= $this->r[1]; $this->r[2] ^= $this->r[2]; $this->r[3] ^= $this->r[3]; $this->r[4] ^= $this->r[4]; $this->h[0] ^= $this->h[0]; $this->h[1] ^= $this->h[1]; $this->h[2] ^= $this->h[2]; $this->h[3] ^= $this->h[3]; $this->h[4] ^= $this->h[4]; $this->pad[0] ^= $this->pad[0]; $this->pad[1] ^= $this->pad[1]; $this->pad[2] ^= $this->pad[2]; $this->pad[3] ^= $this->pad[3]; $this->leftover = 0; $this->final = true; } /** * @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); if ($bytes < 1) { return $this; } /* handle leftover */ if ($this->leftover) { $want = ParagonIE_Sodium_Core_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_Core_Poly1305::BLOCK_SIZE) { // We still don't have enough to run $this->blocks() return $this; } $this->blocks( self::intArrayToString($this->buffer), ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE ); $this->leftover = 0; } /* process full blocks */ if ($bytes >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) { /** @var int $want */ $want = $bytes & ~(ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE - 1); if ($want >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) { $block = self::substr($message, 0, $want); if (self::strlen($block) >= ParagonIE_Sodium_Core_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 TypeError */ public function blocks($message, $bytes) { if (self::strlen($message) < 16) { $message = str_pad($message, 16, "\x00", STR_PAD_RIGHT); } /** @var int $hibit */ $hibit = $this->final ? 0 : 1 << 24; /* 1 << 128 */ $r0 = (int) $this->r[0]; $r1 = (int) $this->r[1]; $r2 = (int) $this->r[2]; $r3 = (int) $this->r[3]; $r4 = (int) $this->r[4]; $s1 = self::mul($r1, 5, 3); $s2 = self::mul($r2, 5, 3); $s3 = self::mul($r3, 5, 3); $s4 = self::mul($r4, 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_Core_Poly1305::BLOCK_SIZE) { /* h += m[i] */ $h0 += self::load_4(self::substr($message, 0, 4)) & 0x3ffffff; $h1 += (self::load_4(self::substr($message, 3, 4)) >> 2) & 0x3ffffff; $h2 += (self::load_4(self::substr($message, 6, 4)) >> 4) & 0x3ffffff; $h3 += (self::load_4(self::substr($message, 9, 4)) >> 6) & 0x3ffffff; $h4 += (self::load_4(self::substr($message, 12, 4)) >> 8) | $hibit; /* h *= r */ $d0 = ( self::mul($h0, $r0, 27) + self::mul($s4, $h1, 27) + self::mul($s3, $h2, 27) + self::mul($s2, $h3, 27) + self::mul($s1, $h4, 27) ); $d1 = ( self::mul($h0, $r1, 27) + self::mul($h1, $r0, 27) + self::mul($s4, $h2, 27) + self::mul($s3, $h3, 27) + self::mul($s2, $h4, 27) ); $d2 = ( self::mul($h0, $r2, 27) + self::mul($h1, $r1, 27) + self::mul($h2, $r0, 27) + self::mul($s4, $h3, 27) + self::mul($s3, $h4, 27) ); $d3 = ( self::mul($h0, $r3, 27) + self::mul($h1, $r2, 27) + self::mul($h2, $r1, 27) + self::mul($h3, $r0, 27) + self::mul($s4, $h4, 27) ); $d4 = ( self::mul($h0, $r4, 27) + self::mul($h1, $r3, 27) + self::mul($h2, $r2, 27) + self::mul($h3, $r1, 27) + self::mul($h4, $r0, 27) ); /* (partial) h %= p */ /** @var int $c */ $c = $d0 >> 26; /** @var int $h0 */ $h0 = $d0 & 0x3ffffff; $d1 += $c; /** @var int $c */ $c = $d1 >> 26; /** @var int $h1 */ $h1 = $d1 & 0x3ffffff; $d2 += $c; /** @var int $c */ $c = $d2 >> 26; /** @var int $h2 */ $h2 = $d2 & 0x3ffffff; $d3 += $c; /** @var int $c */ $c = $d3 >> 26; /** @var int $h3 */ $h3 = $d3 & 0x3ffffff; $d4 += $c; /** @var int $c */ $c = $d4 >> 26; /** @var int $h4 */ $h4 = $d4 & 0x3ffffff; $h0 += (int) self::mul($c, 5, 3); /** @var int $c */ $c = $h0 >> 26; /** @var int $h0 */ $h0 &= 0x3ffffff; $h1 += $c; // Chop off the left 32 bytes. $message = self::substr( $message, ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE ); $bytes -= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE; } $this->h = array( (int) ($h0 & 0xffffffff), (int) ($h1 & 0xffffffff), (int) ($h2 & 0xffffffff), (int) ($h3 & 0xffffffff), (int) ($h4 & 0xffffffff) ); return $this; } /** * @internal You should not use this directly from another application * * @return string * @throws TypeError */ public function finish() { /* process the remaining block */ if ($this->leftover) { $i = $this->leftover; $this->buffer[$i++] = 1; for (; $i < ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE; ++$i) { $this->buffer[$i] = 0; } $this->final = true; $this->blocks( self::substr( self::intArrayToString($this->buffer), 0, ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE ), ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE ); } $h0 = (int) $this->h[0]; $h1 = (int) $this->h[1]; $h2 = (int) $this->h[2]; $h3 = (int) $this->h[3]; $h4 = (int) $this->h[4]; /** @var int $c */ $c = $h1 >> 26; /** @var int $h1 */ $h1 &= 0x3ffffff; /** @var int $h2 */ $h2 += $c; /** @var int $c */ $c = $h2 >> 26; /** @var int $h2 */ $h2 &= 0x3ffffff; $h3 += $c; /** @var int $c */ $c = $h3 >> 26; $h3 &= 0x3ffffff; $h4 += $c; /** @var int $c */ $c = $h4 >> 26; $h4 &= 0x3ffffff; /** @var int $h0 */ $h0 += self::mul($c, 5, 3); /** @var int $c */ $c = $h0 >> 26; /** @var int $h0 */ $h0 &= 0x3ffffff; /** @var int $h1 */ $h1 += $c; /* compute h + -p */ /** @var int $g0 */ $g0 = $h0 + 5; /** @var int $c */ $c = $g0 >> 26; /** @var int $g0 */ $g0 &= 0x3ffffff; /** @var int $g1 */ $g1 = $h1 + $c; /** @var int $c */ $c = $g1 >> 26; $g1 &= 0x3ffffff; /** @var int $g2 */ $g2 = $h2 + $c; /** @var int $c */ $c = $g2 >> 26; /** @var int $g2 */ $g2 &= 0x3ffffff; /** @var int $g3 */ $g3 = $h3 + $c; /** @var int $c */ $c = $g3 >> 26; /** @var int $g3 */ $g3 &= 0x3ffffff; /** @var int $g4 */ $g4 = ($h4 + $c - (1 << 26)) & 0xffffffff; /* select h if h < p, or h + -p if h >= p */ /** @var int $mask */ $mask = ($g4 >> 31) - 1; $g0 &= $mask; $g1 &= $mask; $g2 &= $mask; $g3 &= $mask; $g4 &= $mask; /** @var int $mask */ $mask = ~$mask & 0xffffffff; /** @var int $h0 */ $h0 = ($h0 & $mask) | $g0; /** @var int $h1 */ $h1 = ($h1 & $mask) | $g1; /** @var int $h2 */ $h2 = ($h2 & $mask) | $g2; /** @var int $h3 */ $h3 = ($h3 & $mask) | $g3; /** @var int $h4 */ $h4 = ($h4 & $mask) | $g4; /* h = h % (2^128) */ /** @var int $h0 */ $h0 = (($h0) | ($h1 << 26)) & 0xffffffff; /** @var int $h1 */ $h1 = (($h1 >> 6) | ($h2 << 20)) & 0xffffffff; /** @var int $h2 */ $h2 = (($h2 >> 12) | ($h3 << 14)) & 0xffffffff; /** @var int $h3 */ $h3 = (($h3 >> 18) | ($h4 << 8)) & 0xffffffff; /* mac = (h + pad) % (2^128) */ $f = (int) ($h0 + $this->pad[0]); $h0 = (int) $f; $f = (int) ($h1 + $this->pad[1] + ($f >> 32)); $h1 = (int) $f; $f = (int) ($h2 + $this->pad[2] + ($f >> 32)); $h2 = (int) $f; $f = (int) ($h3 + $this->pad[3] + ($f >> 32)); $h3 = (int) $f; return self::store32_le($h0 & 0xffffffff) . self::store32_le($h1 & 0xffffffff) . self::store32_le($h2 & 0xffffffff) . self::store32_le($h3 & 0xffffffff); } } PK! &-&-Core/Curve25519.phpnu[ $arr */ $arr = array(); for ($i = 0; $i < 10; ++$i) { $arr[$i] = (int) ($f[$i] + $g[$i]); } return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($arr); } /** * Constant-time conditional move. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @param ParagonIE_Sodium_Core_Curve25519_Fe $g * @param int $b * @return ParagonIE_Sodium_Core_Curve25519_Fe * @psalm-suppress MixedAssignment */ public static function fe_cmov( ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g, $b = 0 ) { /** @var array $h */ $h = array(); $b *= -1; for ($i = 0; $i < 10; ++$i) { $x = (($f[$i] ^ $g[$i]) & $b); $h[$i] = ($f[$i]) ^ $x; } return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h); } /** * Create a copy of a field element. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_copy(ParagonIE_Sodium_Core_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_Core_Curve25519_Fe * @throws RangeException * @throws TypeError */ public static function fe_frombytes($s) { if (self::strlen($s) !== 32) { throw new RangeException('Expected a 32-byte string.'); } $h0 = self::load_4($s); $h1 = self::load_3(self::substr($s, 4, 3)) << 6; $h2 = self::load_3(self::substr($s, 7, 3)) << 5; $h3 = self::load_3(self::substr($s, 10, 3)) << 3; $h4 = self::load_3(self::substr($s, 13, 3)) << 2; $h5 = self::load_4(self::substr($s, 16, 4)); $h6 = self::load_3(self::substr($s, 20, 3)) << 7; $h7 = self::load_3(self::substr($s, 23, 3)) << 5; $h8 = self::load_3(self::substr($s, 26, 3)) << 4; $h9 = (self::load_3(self::substr($s, 29, 3)) & 8388607) << 2; $carry9 = ($h9 + (1 << 24)) >> 25; $h0 += self::mul($carry9, 19, 5); $h9 -= $carry9 << 25; $carry1 = ($h1 + (1 << 24)) >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; $carry3 = ($h3 + (1 << 24)) >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; $carry5 = ($h5 + (1 << 24)) >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; $carry7 = ($h7 + (1 << 24)) >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; $carry2 = ($h2 + (1 << 25)) >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry6 = ($h6 + (1 << 25)) >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; $carry8 = ($h8 + (1 << 25)) >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( array( (int) $h0, (int) $h1, (int) $h2, (int) $h3, (int) $h4, (int) $h5, (int) $h6, (int) $h7, (int) $h8, (int) $h9 ) ); } /** * Convert a field element to a byte string. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $h * @return string */ public static function fe_tobytes(ParagonIE_Sodium_Core_Curve25519_Fe $h) { $h0 = (int) $h[0]; $h1 = (int) $h[1]; $h2 = (int) $h[2]; $h3 = (int) $h[3]; $h4 = (int) $h[4]; $h5 = (int) $h[5]; $h6 = (int) $h[6]; $h7 = (int) $h[7]; $h8 = (int) $h[8]; $h9 = (int) $h[9]; $q = (self::mul($h9, 19, 5) + (1 << 24)) >> 25; $q = ($h0 + $q) >> 26; $q = ($h1 + $q) >> 25; $q = ($h2 + $q) >> 26; $q = ($h3 + $q) >> 25; $q = ($h4 + $q) >> 26; $q = ($h5 + $q) >> 25; $q = ($h6 + $q) >> 26; $q = ($h7 + $q) >> 25; $q = ($h8 + $q) >> 26; $q = ($h9 + $q) >> 25; $h0 += self::mul($q, 19, 5); $carry0 = $h0 >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; $carry1 = $h1 >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; $carry2 = $h2 >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; $carry3 = $h3 >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; $carry4 = $h4 >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry5 = $h5 >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; $carry6 = $h6 >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; $carry7 = $h7 >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; $carry8 = $h8 >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; $carry9 = $h9 >> 25; $h9 -= $carry9 << 25; /** * @var array */ $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_Core_Curve25519_Fe $f * @return int * @throws SodiumException * @throws TypeError */ public static function fe_isnegative(ParagonIE_Sodium_Core_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_Core_Curve25519_Fe $f * @return bool * @throws SodiumException * @throws TypeError */ public static function fe_isnonzero(ParagonIE_Sodium_Core_Curve25519_Fe $f) { static $zero; if ($zero === null) { $zero = str_repeat("\x00", 32); } /** @var string $zero */ /** @var string $str */ $str = self::fe_tobytes($f); return !self::verify_32($str, (string) $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_Core_Curve25519_Fe $f * @param ParagonIE_Sodium_Core_Curve25519_Fe $g * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_mul( ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g ) { // Ensure limbs aren't oversized. $f = self::fe_normalize($f); $g = self::fe_normalize($g); $f0 = $f[0]; $f1 = $f[1]; $f2 = $f[2]; $f3 = $f[3]; $f4 = $f[4]; $f5 = $f[5]; $f6 = $f[6]; $f7 = $f[7]; $f8 = $f[8]; $f9 = $f[9]; $g0 = $g[0]; $g1 = $g[1]; $g2 = $g[2]; $g3 = $g[3]; $g4 = $g[4]; $g5 = $g[5]; $g6 = $g[6]; $g7 = $g[7]; $g8 = $g[8]; $g9 = $g[9]; $g1_19 = self::mul($g1, 19, 5); $g2_19 = self::mul($g2, 19, 5); $g3_19 = self::mul($g3, 19, 5); $g4_19 = self::mul($g4, 19, 5); $g5_19 = self::mul($g5, 19, 5); $g6_19 = self::mul($g6, 19, 5); $g7_19 = self::mul($g7, 19, 5); $g8_19 = self::mul($g8, 19, 5); $g9_19 = self::mul($g9, 19, 5); $f1_2 = $f1 << 1; $f3_2 = $f3 << 1; $f5_2 = $f5 << 1; $f7_2 = $f7 << 1; $f9_2 = $f9 << 1; $f0g0 = self::mul($f0, $g0, 26); $f0g1 = self::mul($f0, $g1, 25); $f0g2 = self::mul($f0, $g2, 26); $f0g3 = self::mul($f0, $g3, 25); $f0g4 = self::mul($f0, $g4, 26); $f0g5 = self::mul($f0, $g5, 25); $f0g6 = self::mul($f0, $g6, 26); $f0g7 = self::mul($f0, $g7, 25); $f0g8 = self::mul($f0, $g8, 26); $f0g9 = self::mul($f0, $g9, 26); $f1g0 = self::mul($f1, $g0, 26); $f1g1_2 = self::mul($f1_2, $g1, 25); $f1g2 = self::mul($f1, $g2, 26); $f1g3_2 = self::mul($f1_2, $g3, 25); $f1g4 = self::mul($f1, $g4, 26); $f1g5_2 = self::mul($f1_2, $g5, 25); $f1g6 = self::mul($f1, $g6, 26); $f1g7_2 = self::mul($f1_2, $g7, 25); $f1g8 = self::mul($f1, $g8, 26); $f1g9_38 = self::mul($g9_19, $f1_2, 26); $f2g0 = self::mul($f2, $g0, 26); $f2g1 = self::mul($f2, $g1, 25); $f2g2 = self::mul($f2, $g2, 26); $f2g3 = self::mul($f2, $g3, 25); $f2g4 = self::mul($f2, $g4, 26); $f2g5 = self::mul($f2, $g5, 25); $f2g6 = self::mul($f2, $g6, 26); $f2g7 = self::mul($f2, $g7, 25); $f2g8_19 = self::mul($g8_19, $f2, 26); $f2g9_19 = self::mul($g9_19, $f2, 26); $f3g0 = self::mul($f3, $g0, 26); $f3g1_2 = self::mul($f3_2, $g1, 25); $f3g2 = self::mul($f3, $g2, 26); $f3g3_2 = self::mul($f3_2, $g3, 25); $f3g4 = self::mul($f3, $g4, 26); $f3g5_2 = self::mul($f3_2, $g5, 25); $f3g6 = self::mul($f3, $g6, 26); $f3g7_38 = self::mul($g7_19, $f3_2, 26); $f3g8_19 = self::mul($g8_19, $f3, 25); $f3g9_38 = self::mul($g9_19, $f3_2, 26); $f4g0 = self::mul($f4, $g0, 26); $f4g1 = self::mul($f4, $g1, 25); $f4g2 = self::mul($f4, $g2, 26); $f4g3 = self::mul($f4, $g3, 25); $f4g4 = self::mul($f4, $g4, 26); $f4g5 = self::mul($f4, $g5, 25); $f4g6_19 = self::mul($g6_19, $f4, 26); $f4g7_19 = self::mul($g7_19, $f4, 26); $f4g8_19 = self::mul($g8_19, $f4, 26); $f4g9_19 = self::mul($g9_19, $f4, 26); $f5g0 = self::mul($f5, $g0, 26); $f5g1_2 = self::mul($f5_2, $g1, 25); $f5g2 = self::mul($f5, $g2, 26); $f5g3_2 = self::mul($f5_2, $g3, 25); $f5g4 = self::mul($f5, $g4, 26); $f5g5_38 = self::mul($g5_19, $f5_2, 26); $f5g6_19 = self::mul($g6_19, $f5, 25); $f5g7_38 = self::mul($g7_19, $f5_2, 26); $f5g8_19 = self::mul($g8_19, $f5, 25); $f5g9_38 = self::mul($g9_19, $f5_2, 26); $f6g0 = self::mul($f6, $g0, 26); $f6g1 = self::mul($f6, $g1, 25); $f6g2 = self::mul($f6, $g2, 26); $f6g3 = self::mul($f6, $g3, 25); $f6g4_19 = self::mul($g4_19, $f6, 26); $f6g5_19 = self::mul($g5_19, $f6, 26); $f6g6_19 = self::mul($g6_19, $f6, 26); $f6g7_19 = self::mul($g7_19, $f6, 26); $f6g8_19 = self::mul($g8_19, $f6, 26); $f6g9_19 = self::mul($g9_19, $f6, 26); $f7g0 = self::mul($f7, $g0, 26); $f7g1_2 = self::mul($f7_2, $g1, 25); $f7g2 = self::mul($f7, $g2, 26); $f7g3_38 = self::mul($g3_19, $f7_2, 26); $f7g4_19 = self::mul($g4_19, $f7, 26); $f7g5_38 = self::mul($g5_19, $f7_2, 26); $f7g6_19 = self::mul($g6_19, $f7, 25); $f7g7_38 = self::mul($g7_19, $f7_2, 26); $f7g8_19 = self::mul($g8_19, $f7, 25); $f7g9_38 = self::mul($g9_19,$f7_2, 26); $f8g0 = self::mul($f8, $g0, 26); $f8g1 = self::mul($f8, $g1, 25); $f8g2_19 = self::mul($g2_19, $f8, 26); $f8g3_19 = self::mul($g3_19, $f8, 26); $f8g4_19 = self::mul($g4_19, $f8, 26); $f8g5_19 = self::mul($g5_19, $f8, 26); $f8g6_19 = self::mul($g6_19, $f8, 26); $f8g7_19 = self::mul($g7_19, $f8, 26); $f8g8_19 = self::mul($g8_19, $f8, 26); $f8g9_19 = self::mul($g9_19, $f8, 26); $f9g0 = self::mul($f9, $g0, 26); $f9g1_38 = self::mul($g1_19, $f9_2, 26); $f9g2_19 = self::mul($g2_19, $f9, 25); $f9g3_38 = self::mul($g3_19, $f9_2, 26); $f9g4_19 = self::mul($g4_19, $f9, 25); $f9g5_38 = self::mul($g5_19, $f9_2, 26); $f9g6_19 = self::mul($g6_19, $f9, 25); $f9g7_38 = self::mul($g7_19, $f9_2, 26); $f9g8_19 = self::mul($g8_19, $f9, 25); $f9g9_38 = self::mul($g9_19, $f9_2, 26); $h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 + $f5g5_38 + $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38; $h1 = $f0g1 + $f1g0 + $f2g9_19 + $f3g8_19 + $f4g7_19 + $f5g6_19 + $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19; $h2 = $f0g2 + $f1g1_2 + $f2g0 + $f3g9_38 + $f4g8_19 + $f5g7_38 + $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38; $h3 = $f0g3 + $f1g2 + $f2g1 + $f3g0 + $f4g9_19 + $f5g8_19 + $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19; $h4 = $f0g4 + $f1g3_2 + $f2g2 + $f3g1_2 + $f4g0 + $f5g9_38 + $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38; $h5 = $f0g5 + $f1g4 + $f2g3 + $f3g2 + $f4g1 + $f5g0 + $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19; $h6 = $f0g6 + $f1g5_2 + $f2g4 + $f3g3_2 + $f4g2 + $f5g1_2 + $f6g0 + $f7g9_38 + $f8g8_19 + $f9g7_38; $h7 = $f0g7 + $f1g6 + $f2g5 + $f3g4 + $f4g3 + $f5g2 + $f6g1 + $f7g0 + $f8g9_19 + $f9g8_19; $h8 = $f0g8 + $f1g7_2 + $f2g6 + $f3g5_2 + $f4g4 + $f5g3_2 + $f6g2 + $f7g1_2 + $f8g0 + $f9g9_38; $h9 = $f0g9 + $f1g8 + $f2g7 + $f3g6 + $f4g5 + $f5g4 + $f6g3 + $f7g2 + $f8g1 + $f9g0 ; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry1 = ($h1 + (1 << 24)) >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; $carry5 = ($h5 + (1 << 24)) >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; $carry2 = ($h2 + (1 << 25)) >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; $carry6 = ($h6 + (1 << 25)) >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; $carry3 = ($h3 + (1 << 24)) >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; $carry7 = ($h7 + (1 << 24)) >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry8 = ($h8 + (1 << 25)) >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; $carry9 = ($h9 + (1 << 24)) >> 25; $h0 += self::mul($carry9, 19, 5); $h9 -= $carry9 << 25; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; return self::fe_normalize( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( array( (int) $h0, (int) $h1, (int) $h2, (int) $h3, (int) $h4, (int) $h5, (int) $h6, (int) $h7, (int) $h8, (int) $h9 ) ) ); } /** * 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_Core_Curve25519_Fe $f * @return ParagonIE_Sodium_Core_Curve25519_Fe * @psalm-suppress MixedAssignment */ public static function fe_neg(ParagonIE_Sodium_Core_Curve25519_Fe $f) { $h = new ParagonIE_Sodium_Core_Curve25519_Fe(); for ($i = 0; $i < 10; ++$i) { $h[$i] = -$f[$i]; } return self::fe_normalize($h); } /** * Square a field element * * h = f * f * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_sq(ParagonIE_Sodium_Core_Curve25519_Fe $f) { $f = self::fe_normalize($f); $f0 = (int) $f[0]; $f1 = (int) $f[1]; $f2 = (int) $f[2]; $f3 = (int) $f[3]; $f4 = (int) $f[4]; $f5 = (int) $f[5]; $f6 = (int) $f[6]; $f7 = (int) $f[7]; $f8 = (int) $f[8]; $f9 = (int) $f[9]; $f0_2 = $f0 << 1; $f1_2 = $f1 << 1; $f2_2 = $f2 << 1; $f3_2 = $f3 << 1; $f4_2 = $f4 << 1; $f5_2 = $f5 << 1; $f6_2 = $f6 << 1; $f7_2 = $f7 << 1; $f5_38 = self::mul($f5, 38, 6); $f6_19 = self::mul($f6, 19, 5); $f7_38 = self::mul($f7, 38, 6); $f8_19 = self::mul($f8, 19, 5); $f9_38 = self::mul($f9, 38, 6); $f0f0 = self::mul($f0, $f0, 26); $f0f1_2 = self::mul($f0_2, $f1, 26); $f0f2_2 = self::mul($f0_2, $f2, 26); $f0f3_2 = self::mul($f0_2, $f3, 26); $f0f4_2 = self::mul($f0_2, $f4, 26); $f0f5_2 = self::mul($f0_2, $f5, 26); $f0f6_2 = self::mul($f0_2, $f6, 26); $f0f7_2 = self::mul($f0_2, $f7, 26); $f0f8_2 = self::mul($f0_2, $f8, 26); $f0f9_2 = self::mul($f0_2, $f9, 26); $f1f1_2 = self::mul($f1_2, $f1, 26); $f1f2_2 = self::mul($f1_2, $f2, 26); $f1f3_4 = self::mul($f1_2, $f3_2, 26); $f1f4_2 = self::mul($f1_2, $f4, 26); $f1f5_4 = self::mul($f1_2, $f5_2, 26); $f1f6_2 = self::mul($f1_2, $f6, 26); $f1f7_4 = self::mul($f1_2, $f7_2, 26); $f1f8_2 = self::mul($f1_2, $f8, 26); $f1f9_76 = self::mul($f9_38, $f1_2, 27); $f2f2 = self::mul($f2, $f2, 27); $f2f3_2 = self::mul($f2_2, $f3, 27); $f2f4_2 = self::mul($f2_2, $f4, 27); $f2f5_2 = self::mul($f2_2, $f5, 27); $f2f6_2 = self::mul($f2_2, $f6, 27); $f2f7_2 = self::mul($f2_2, $f7, 27); $f2f8_38 = self::mul($f8_19, $f2_2, 27); $f2f9_38 = self::mul($f9_38, $f2, 26); $f3f3_2 = self::mul($f3_2, $f3, 26); $f3f4_2 = self::mul($f3_2, $f4, 26); $f3f5_4 = self::mul($f3_2, $f5_2, 26); $f3f6_2 = self::mul($f3_2, $f6, 26); $f3f7_76 = self::mul($f7_38, $f3_2, 26); $f3f8_38 = self::mul($f8_19, $f3_2, 26); $f3f9_76 = self::mul($f9_38, $f3_2, 26); $f4f4 = self::mul($f4, $f4, 26); $f4f5_2 = self::mul($f4_2, $f5, 26); $f4f6_38 = self::mul($f6_19, $f4_2, 27); $f4f7_38 = self::mul($f7_38, $f4, 26); $f4f8_38 = self::mul($f8_19, $f4_2, 27); $f4f9_38 = self::mul($f9_38, $f4, 26); $f5f5_38 = self::mul($f5_38, $f5, 26); $f5f6_38 = self::mul($f6_19, $f5_2, 26); $f5f7_76 = self::mul($f7_38, $f5_2, 26); $f5f8_38 = self::mul($f8_19, $f5_2, 26); $f5f9_76 = self::mul($f9_38, $f5_2, 26); $f6f6_19 = self::mul($f6_19, $f6, 26); $f6f7_38 = self::mul($f7_38, $f6, 26); $f6f8_38 = self::mul($f8_19, $f6_2, 27); $f6f9_38 = self::mul($f9_38, $f6, 26); $f7f7_38 = self::mul($f7_38, $f7, 26); $f7f8_38 = self::mul($f8_19, $f7_2, 26); $f7f9_76 = self::mul($f9_38, $f7_2, 26); $f8f8_19 = self::mul($f8_19, $f8, 26); $f8f9_38 = self::mul($f9_38, $f8, 26); $f9f9_38 = self::mul($f9_38, $f9, 26); $h0 = $f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38; $h1 = $f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38; $h2 = $f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19; $h3 = $f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38; $h4 = $f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38; $h5 = $f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38; $h6 = $f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19; $h7 = $f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38; $h8 = $f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38; $h9 = $f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry1 = ($h1 + (1 << 24)) >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; $carry5 = ($h5 + (1 << 24)) >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; $carry2 = ($h2 + (1 << 25)) >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; $carry6 = ($h6 + (1 << 25)) >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; $carry3 = ($h3 + (1 << 24)) >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; $carry7 = ($h7 + (1 << 24)) >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry8 = ($h8 + (1 << 25)) >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; $carry9 = ($h9 + (1 << 24)) >> 25; $h0 += self::mul($carry9, 19, 5); $h9 -= $carry9 << 25; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; return self::fe_normalize( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( array( (int) $h0, (int) $h1, (int) $h2, (int) $h3, (int) $h4, (int) $h5, (int) $h6, (int) $h7, (int) $h8, (int) $h9 ) ) ); } /** * Square and double a field element * * h = 2 * f * f * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_sq2(ParagonIE_Sodium_Core_Curve25519_Fe $f) { $f = self::fe_normalize($f); $f0 = (int) $f[0]; $f1 = (int) $f[1]; $f2 = (int) $f[2]; $f3 = (int) $f[3]; $f4 = (int) $f[4]; $f5 = (int) $f[5]; $f6 = (int) $f[6]; $f7 = (int) $f[7]; $f8 = (int) $f[8]; $f9 = (int) $f[9]; $f0_2 = $f0 << 1; $f1_2 = $f1 << 1; $f2_2 = $f2 << 1; $f3_2 = $f3 << 1; $f4_2 = $f4 << 1; $f5_2 = $f5 << 1; $f6_2 = $f6 << 1; $f7_2 = $f7 << 1; $f5_38 = self::mul($f5, 38, 6); /* 1.959375*2^30 */ $f6_19 = self::mul($f6, 19, 5); /* 1.959375*2^30 */ $f7_38 = self::mul($f7, 38, 6); /* 1.959375*2^30 */ $f8_19 = self::mul($f8, 19, 5); /* 1.959375*2^30 */ $f9_38 = self::mul($f9, 38, 6); /* 1.959375*2^30 */ $f0f0 = self::mul($f0, $f0, 24); $f0f1_2 = self::mul($f0_2, $f1, 24); $f0f2_2 = self::mul($f0_2, $f2, 24); $f0f3_2 = self::mul($f0_2, $f3, 24); $f0f4_2 = self::mul($f0_2, $f4, 24); $f0f5_2 = self::mul($f0_2, $f5, 24); $f0f6_2 = self::mul($f0_2, $f6, 24); $f0f7_2 = self::mul($f0_2, $f7, 24); $f0f8_2 = self::mul($f0_2, $f8, 24); $f0f9_2 = self::mul($f0_2, $f9, 24); $f1f1_2 = self::mul($f1_2, $f1, 24); $f1f2_2 = self::mul($f1_2, $f2, 24); $f1f3_4 = self::mul($f1_2, $f3_2, 24); $f1f4_2 = self::mul($f1_2, $f4, 24); $f1f5_4 = self::mul($f1_2, $f5_2, 24); $f1f6_2 = self::mul($f1_2, $f6, 24); $f1f7_4 = self::mul($f1_2, $f7_2, 24); $f1f8_2 = self::mul($f1_2, $f8, 24); $f1f9_76 = self::mul($f9_38, $f1_2, 24); $f2f2 = self::mul($f2, $f2, 24); $f2f3_2 = self::mul($f2_2, $f3, 24); $f2f4_2 = self::mul($f2_2, $f4, 24); $f2f5_2 = self::mul($f2_2, $f5, 24); $f2f6_2 = self::mul($f2_2, $f6, 24); $f2f7_2 = self::mul($f2_2, $f7, 24); $f2f8_38 = self::mul($f8_19, $f2_2, 25); $f2f9_38 = self::mul($f9_38, $f2, 24); $f3f3_2 = self::mul($f3_2, $f3, 24); $f3f4_2 = self::mul($f3_2, $f4, 24); $f3f5_4 = self::mul($f3_2, $f5_2, 24); $f3f6_2 = self::mul($f3_2, $f6, 24); $f3f7_76 = self::mul($f7_38, $f3_2, 24); $f3f8_38 = self::mul($f8_19, $f3_2, 24); $f3f9_76 = self::mul($f9_38, $f3_2, 24); $f4f4 = self::mul($f4, $f4, 24); $f4f5_2 = self::mul($f4_2, $f5, 24); $f4f6_38 = self::mul($f6_19, $f4_2, 25); $f4f7_38 = self::mul($f7_38, $f4, 24); $f4f8_38 = self::mul($f8_19, $f4_2, 25); $f4f9_38 = self::mul($f9_38, $f4, 24); $f5f5_38 = self::mul($f5_38, $f5, 24); $f5f6_38 = self::mul($f6_19, $f5_2, 24); $f5f7_76 = self::mul($f7_38, $f5_2, 24); $f5f8_38 = self::mul($f8_19, $f5_2, 24); $f5f9_76 = self::mul($f9_38, $f5_2, 24); $f6f6_19 = self::mul($f6_19, $f6, 24); $f6f7_38 = self::mul($f7_38, $f6, 24); $f6f8_38 = self::mul($f8_19, $f6_2, 25); $f6f9_38 = self::mul($f9_38, $f6, 24); $f7f7_38 = self::mul($f7_38, $f7, 24); $f7f8_38 = self::mul($f8_19, $f7_2, 24); $f7f9_76 = self::mul($f9_38, $f7_2, 24); $f8f8_19 = self::mul($f8_19, $f8, 24); $f8f9_38 = self::mul($f9_38, $f8, 24); $f9f9_38 = self::mul($f9_38, $f9, 24); $h0 = (int) ($f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38) << 1; $h1 = (int) ($f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38) << 1; $h2 = (int) ($f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19) << 1; $h3 = (int) ($f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38) << 1; $h4 = (int) ($f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38) << 1; $h5 = (int) ($f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38) << 1; $h6 = (int) ($f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19) << 1; $h7 = (int) ($f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38) << 1; $h8 = (int) ($f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38) << 1; $h9 = (int) ($f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2) << 1; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry1 = ($h1 + (1 << 24)) >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; $carry5 = ($h5 + (1 << 24)) >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; $carry2 = ($h2 + (1 << 25)) >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; $carry6 = ($h6 + (1 << 25)) >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; $carry3 = ($h3 + (1 << 24)) >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; $carry7 = ($h7 + (1 << 24)) >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry8 = ($h8 + (1 << 25)) >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; $carry9 = ($h9 + (1 << 24)) >> 25; $h0 += self::mul($carry9, 19, 5); $h9 -= $carry9 << 25; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; return self::fe_normalize( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( array( (int) $h0, (int) $h1, (int) $h2, (int) $h3, (int) $h4, (int) $h5, (int) $h6, (int) $h7, (int) $h8, (int) $h9 ) ) ); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $Z * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_invert(ParagonIE_Sodium_Core_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_Core_Curve25519_Fe $z * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_pow22523(ParagonIE_Sodium_Core_Curve25519_Fe $z) { $z = self::fe_normalize($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_Core_Curve25519_Fe $f * @param ParagonIE_Sodium_Core_Curve25519_Fe $g * @return ParagonIE_Sodium_Core_Curve25519_Fe * @psalm-suppress MixedOperand */ public static function fe_sub(ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g) { return self::fe_normalize( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( array( (int) ($f[0] - $g[0]), (int) ($f[1] - $g[1]), (int) ($f[2] - $g[2]), (int) ($f[3] - $g[3]), (int) ($f[4] - $g[4]), (int) ($f[5] - $g[5]), (int) ($f[6] - $g[6]), (int) ($f[7] - $g[7]), (int) ($f[8] - $g[8]), (int) ($f[9] - $g[9]) ) ) ); } /** * Add two group elements. * * r = p + q * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ public static function ge_add( ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p, ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q ) { $r = new ParagonIE_Sodium_Core_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 * @throws SodiumException * @throws TypeError */ 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 $r */ $r = array(); /** @var int $i */ for ($i = 0; $i < 256; ++$i) { $r[$i] = (int) ( 1 & ( self::chrToInt($a[(int) ($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_Core_Curve25519_Ge_P3 * @throws SodiumException * @throws TypeError */ public static function ge_frombytes_negate_vartime($s) { static $d = null; if (!$d) { $d = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d); } # fe_frombytes(h->Y,s); # fe_1(h->Z); $h = new ParagonIE_Sodium_Core_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_Core_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_Core_Curve25519_Fe::fromArray(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_Core_Curve25519_Ge_P1p1 $R * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ public static function ge_madd( ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R, ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p, ParagonIE_Sodium_Core_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_Core_Curve25519_Ge_P1p1 $R * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ public static function ge_msub( ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R, ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p, ParagonIE_Sodium_Core_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_Core_Curve25519_Ge_P1p1 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2 */ public static function ge_p1p1_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p) { $r = new ParagonIE_Sodium_Core_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_Core_Curve25519_Ge_P1p1 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 */ public static function ge_p1p1_to_p3(ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p) { $r = new ParagonIE_Sodium_Core_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_Core_Curve25519_Ge_P2 */ public static function ge_p2_0() { return new ParagonIE_Sodium_Core_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_Core_Curve25519_Ge_P2 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ public static function ge_p2_dbl(ParagonIE_Sodium_Core_Curve25519_Ge_P2 $p) { $r = new ParagonIE_Sodium_Core_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_Core_Curve25519_Ge_P3 */ public static function ge_p3_0() { return new ParagonIE_Sodium_Core_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_Core_Curve25519_Ge_P3 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached */ public static function ge_p3_to_cached(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p) { static $d2 = null; if ($d2 === null) { $d2 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d2); } /** @var ParagonIE_Sodium_Core_Curve25519_Fe $d2 */ $r = new ParagonIE_Sodium_Core_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_Core_Curve25519_Ge_P3 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2 */ public static function ge_p3_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p) { return new ParagonIE_Sodium_Core_Curve25519_Ge_P2( self::fe_copy($p->X), self::fe_copy($p->Y), self::fe_copy($p->Z) ); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h * @return string * @throws SodiumException * @throws TypeError */ public static function ge_p3_tobytes(ParagonIE_Sodium_Core_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_Core_Curve25519_Ge_P3 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ public static function ge_p3_dbl(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p) { $q = self::ge_p3_to_p2($p); return self::ge_p2_dbl($q); } /** * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp */ public static function ge_precomp_0() { return new ParagonIE_Sodium_Core_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 */ public static function equal($b, $c) { return (int) ((($b ^ $c) - 1) >> 31) & 1; } /** * @internal You should not use this directly from another application * * @param int|string $char * @return int (1 = yes, 0 = no) * @throws SodiumException * @throws TypeError */ public static function negative($char) { if (is_int($char)) { return ($char >> 63) & 1; } $x = self::chrToInt(self::substr($char, 0, 1)); return (int) ($x >> 63); } /** * Conditional move * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $t * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $u * @param int $b * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp */ public static function cmov( ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $t, ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $u, $b ) { if (!is_int($b)) { throw new InvalidArgumentException('Expected an integer.'); } return new ParagonIE_Sodium_Core_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) ); } /** * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $t * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $u * @param int $b * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached */ public static function ge_cmov_cached( ParagonIE_Sodium_Core_Curve25519_Ge_Cached $t, ParagonIE_Sodium_Core_Curve25519_Ge_Cached $u, $b ) { $b &= 1; $ret = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(); $ret->YplusX = self::fe_cmov($t->YplusX, $u->YplusX, $b); $ret->YminusX = self::fe_cmov($t->YminusX, $u->YminusX, $b); $ret->Z = self::fe_cmov($t->Z, $u->Z, $b); $ret->T2d = self::fe_cmov($t->T2d, $u->T2d, $b); return $ret; } /** * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached[] $cached * @param int $b * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached * @throws SodiumException */ public static function ge_cmov8_cached(array $cached, $b) { // const unsigned char bnegative = negative(b); // const unsigned char babs = b - (((-bnegative) & b) * ((signed char) 1 << 1)); $bnegative = self::negative($b); $babs = $b - (((-$bnegative) & $b) << 1); // ge25519_cached_0(t); $t = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached( self::fe_1(), self::fe_1(), self::fe_1(), self::fe_0() ); // ge25519_cmov_cached(t, &cached[0], equal(babs, 1)); // ge25519_cmov_cached(t, &cached[1], equal(babs, 2)); // ge25519_cmov_cached(t, &cached[2], equal(babs, 3)); // ge25519_cmov_cached(t, &cached[3], equal(babs, 4)); // ge25519_cmov_cached(t, &cached[4], equal(babs, 5)); // ge25519_cmov_cached(t, &cached[5], equal(babs, 6)); // ge25519_cmov_cached(t, &cached[6], equal(babs, 7)); // ge25519_cmov_cached(t, &cached[7], equal(babs, 8)); for ($x = 0; $x < 8; ++$x) { $t = self::ge_cmov_cached($t, $cached[$x], self::equal($babs, $x + 1)); } // fe25519_copy(minust.YplusX, t->YminusX); // fe25519_copy(minust.YminusX, t->YplusX); // fe25519_copy(minust.Z, t->Z); // fe25519_neg(minust.T2d, t->T2d); $minust = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached( self::fe_copy($t->YminusX), self::fe_copy($t->YplusX), self::fe_copy($t->Z), self::fe_neg($t->T2d) ); return self::ge_cmov_cached($t, $minust, $bnegative); } /** * @internal You should not use this directly from another application * * @param int $pos * @param int $b * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayOffset */ public static function ge_select($pos = 0, $b = 0) { static $base = null; if ($base === null) { $base = array(); /** @var int $i */ foreach (self::$base as $i => $bas) { for ($j = 0; $j < 8; ++$j) { $base[$i][$j] = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][0]), ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][1]), ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][2]) ); } } } /** @var array> $base */ 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_Core_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_Core_Curve25519_Ge_P3 $p * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ public static function ge_sub( ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p, ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q ) { $r = new ParagonIE_Sodium_Core_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_Core_Curve25519_Ge_P2 $h * @return string * @throws SodiumException * @throws TypeError */ public static function ge_tobytes(ParagonIE_Sodium_Core_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_Core_Curve25519_Ge_P3 $A * @param string $b * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedArrayAccess */ public static function ge_double_scalarmult_vartime( $a, ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A, $b ) { /** @var array $Ai */ $Ai = array(); /** @var array $Bi */ static $Bi = array(); if (!$Bi) { for ($i = 0; $i < 8; ++$i) { $Bi[$i] = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][0]), ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][1]), ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][2]) ); } } for ($i = 0; $i < 8; ++$i) { $Ai[$i] = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached( self::fe_0(), self::fe_0(), self::fe_0(), self::fe_0() ); } # slide(aslide,a); # slide(bslide,b); /** @var array $aslide */ $aslide = self::slide($a); /** @var array $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)] ); } # if (bslide[i] > 0) { if ($bslide[$i] > 0) { /** @var int $index */ $index = (int) floor($bslide[$i] / 2); # ge_p1p1_to_p3(&u,&t); # ge_madd(&t,&u,&Bi[bslide[i]/2]); $u = self::ge_p1p1_to_p3($t); $t = self::ge_madd($t, $u, $Bi[$index]); # } else if (bslide[i] < 0) { } elseif ($bslide[$i] < 0) { /** @var int $index */ $index = (int) floor(-$bslide[$i] / 2); # ge_p1p1_to_p3(&u,&t); # ge_msub(&t,&u,&Bi[(-bslide[i])/2]); $u = self::ge_p1p1_to_p3($t); $t = self::ge_msub($t, $u, $Bi[$index]); } # 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 * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedAssignment * @psalm-suppress MixedOperand */ public static function ge_scalarmult($a, $p) { $e = array_fill(0, 64, 0); /** @var ParagonIE_Sodium_Core_Curve25519_Ge_Cached[] $pi */ $pi = array(); // ge25519_p3_to_cached(&pi[1 - 1], p); /* p */ $pi[0] = self::ge_p3_to_cached($p); // ge25519_p3_dbl(&t2, p); // ge25519_p1p1_to_p3(&p2, &t2); // ge25519_p3_to_cached(&pi[2 - 1], &p2); /* 2p = 2*p */ $t2 = self::ge_p3_dbl($p); $p2 = self::ge_p1p1_to_p3($t2); $pi[1] = self::ge_p3_to_cached($p2); // ge25519_add_cached(&t3, p, &pi[2 - 1]); // ge25519_p1p1_to_p3(&p3, &t3); // ge25519_p3_to_cached(&pi[3 - 1], &p3); /* 3p = 2p+p */ $t3 = self::ge_add($p, $pi[1]); $p3 = self::ge_p1p1_to_p3($t3); $pi[2] = self::ge_p3_to_cached($p3); // ge25519_p3_dbl(&t4, &p2); // ge25519_p1p1_to_p3(&p4, &t4); // ge25519_p3_to_cached(&pi[4 - 1], &p4); /* 4p = 2*2p */ $t4 = self::ge_p3_dbl($p2); $p4 = self::ge_p1p1_to_p3($t4); $pi[3] = self::ge_p3_to_cached($p4); // ge25519_add_cached(&t5, p, &pi[4 - 1]); // ge25519_p1p1_to_p3(&p5, &t5); // ge25519_p3_to_cached(&pi[5 - 1], &p5); /* 5p = 4p+p */ $t5 = self::ge_add($p, $pi[3]); $p5 = self::ge_p1p1_to_p3($t5); $pi[4] = self::ge_p3_to_cached($p5); // ge25519_p3_dbl(&t6, &p3); // ge25519_p1p1_to_p3(&p6, &t6); // ge25519_p3_to_cached(&pi[6 - 1], &p6); /* 6p = 2*3p */ $t6 = self::ge_p3_dbl($p3); $p6 = self::ge_p1p1_to_p3($t6); $pi[5] = self::ge_p3_to_cached($p6); // ge25519_add_cached(&t7, p, &pi[6 - 1]); // ge25519_p1p1_to_p3(&p7, &t7); // ge25519_p3_to_cached(&pi[7 - 1], &p7); /* 7p = 6p+p */ $t7 = self::ge_add($p, $pi[5]); $p7 = self::ge_p1p1_to_p3($t7); $pi[6] = self::ge_p3_to_cached($p7); // ge25519_p3_dbl(&t8, &p4); // ge25519_p1p1_to_p3(&p8, &t8); // ge25519_p3_to_cached(&pi[8 - 1], &p8); /* 8p = 2*4p */ $t8 = self::ge_p3_dbl($p4); $p8 = self::ge_p1p1_to_p3($t8); $pi[7] = self::ge_p3_to_cached($p8); // for (i = 0; i < 32; ++i) { // e[2 * i + 0] = (a[i] >> 0) & 15; // e[2 * i + 1] = (a[i] >> 4) & 15; // } for ($i = 0; $i < 32; ++$i) { $e[($i << 1) ] = self::chrToInt($a[$i]) & 15; $e[($i << 1) + 1] = (self::chrToInt($a[$i]) >> 4) & 15; } // /* each e[i] is between 0 and 15 */ // /* e[63] is between 0 and 7 */ // carry = 0; // for (i = 0; i < 63; ++i) { // e[i] += carry; // carry = e[i] + 8; // carry >>= 4; // e[i] -= carry * ((signed char) 1 << 4); // } $carry = 0; for ($i = 0; $i < 63; ++$i) { $e[$i] += $carry; $carry = $e[$i] + 8; $carry >>= 4; $e[$i] -= $carry << 4; } // e[63] += carry; // /* each e[i] is between -8 and 8 */ $e[63] += $carry; // ge25519_p3_0(h); $h = self::ge_p3_0(); // for (i = 63; i != 0; i--) { for ($i = 63; $i != 0; --$i) { // ge25519_cmov8_cached(&t, pi, e[i]); $t = self::ge_cmov8_cached($pi, $e[$i]); // ge25519_add_cached(&r, h, &t); $r = self::ge_add($h, $t); // ge25519_p1p1_to_p2(&s, &r); // ge25519_p2_dbl(&r, &s); // ge25519_p1p1_to_p2(&s, &r); // ge25519_p2_dbl(&r, &s); // ge25519_p1p1_to_p2(&s, &r); // ge25519_p2_dbl(&r, &s); // ge25519_p1p1_to_p2(&s, &r); // ge25519_p2_dbl(&r, &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); $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); // ge25519_p1p1_to_p3(h, &r); /* *16 */ $h = self::ge_p1p1_to_p3($r); /* *16 */ } // ge25519_cmov8_cached(&t, pi, e[i]); // ge25519_add_cached(&r, h, &t); // ge25519_p1p1_to_p3(h, &r); $t = self::ge_cmov8_cached($pi, $e[0]); $r = self::ge_add($h, $t); return self::ge_p1p1_to_p3($r); } /** * @internal You should not use this directly from another application * * @param string $a * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedAssignment * @psalm-suppress MixedOperand */ public static function ge_scalarmult_base($a) { /** @var array $e */ $e = array(); $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(); for ($i = 0; $i < 32; ++$i) { $dbl = (int) $i << 1; $e[$dbl] = (int) self::chrToInt($a[$i]) & 15; $e[$dbl + 1] = (int) (self::chrToInt($a[$i]) >> 4) & 15; } $carry = 0; for ($i = 0; $i < 63; ++$i) { $e[$i] += $carry; $carry = $e[$i] + 8; $carry >>= 4; $e[$i] -= $carry << 4; } $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 TypeError */ public static function sc_muladd($a, $b, $c) { $a0 = 2097151 & self::load_3(self::substr($a, 0, 3)); $a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5); $a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2); $a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7); $a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4); $a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1); $a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6); $a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3); $a8 = 2097151 & self::load_3(self::substr($a, 21, 3)); $a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5); $a10 = 2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2); $a11 = (self::load_4(self::substr($a, 28, 4)) >> 7); $b0 = 2097151 & self::load_3(self::substr($b, 0, 3)); $b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5); $b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2); $b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7); $b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4); $b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1); $b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6); $b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3); $b8 = 2097151 & self::load_3(self::substr($b, 21, 3)); $b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5); $b10 = 2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2); $b11 = (self::load_4(self::substr($b, 28, 4)) >> 7); $c0 = 2097151 & self::load_3(self::substr($c, 0, 3)); $c1 = 2097151 & (self::load_4(self::substr($c, 2, 4)) >> 5); $c2 = 2097151 & (self::load_3(self::substr($c, 5, 3)) >> 2); $c3 = 2097151 & (self::load_4(self::substr($c, 7, 4)) >> 7); $c4 = 2097151 & (self::load_4(self::substr($c, 10, 4)) >> 4); $c5 = 2097151 & (self::load_3(self::substr($c, 13, 3)) >> 1); $c6 = 2097151 & (self::load_4(self::substr($c, 15, 4)) >> 6); $c7 = 2097151 & (self::load_3(self::substr($c, 18, 3)) >> 3); $c8 = 2097151 & self::load_3(self::substr($c, 21, 3)); $c9 = 2097151 & (self::load_4(self::substr($c, 23, 4)) >> 5); $c10 = 2097151 & (self::load_3(self::substr($c, 26, 3)) >> 2); $c11 = (self::load_4(self::substr($c, 28, 4)) >> 7); /* Can't really avoid the pyramid here: */ $s0 = $c0 + self::mul($a0, $b0, 24); $s1 = $c1 + self::mul($a0, $b1, 24) + self::mul($a1, $b0, 24); $s2 = $c2 + self::mul($a0, $b2, 24) + self::mul($a1, $b1, 24) + self::mul($a2, $b0, 24); $s3 = $c3 + self::mul($a0, $b3, 24) + self::mul($a1, $b2, 24) + self::mul($a2, $b1, 24) + self::mul($a3, $b0, 24); $s4 = $c4 + self::mul($a0, $b4, 24) + self::mul($a1, $b3, 24) + self::mul($a2, $b2, 24) + self::mul($a3, $b1, 24) + self::mul($a4, $b0, 24); $s5 = $c5 + self::mul($a0, $b5, 24) + self::mul($a1, $b4, 24) + self::mul($a2, $b3, 24) + self::mul($a3, $b2, 24) + self::mul($a4, $b1, 24) + self::mul($a5, $b0, 24); $s6 = $c6 + self::mul($a0, $b6, 24) + self::mul($a1, $b5, 24) + self::mul($a2, $b4, 24) + self::mul($a3, $b3, 24) + self::mul($a4, $b2, 24) + self::mul($a5, $b1, 24) + self::mul($a6, $b0, 24); $s7 = $c7 + self::mul($a0, $b7, 24) + self::mul($a1, $b6, 24) + self::mul($a2, $b5, 24) + self::mul($a3, $b4, 24) + self::mul($a4, $b3, 24) + self::mul($a5, $b2, 24) + self::mul($a6, $b1, 24) + self::mul($a7, $b0, 24); $s8 = $c8 + self::mul($a0, $b8, 24) + self::mul($a1, $b7, 24) + self::mul($a2, $b6, 24) + self::mul($a3, $b5, 24) + self::mul($a4, $b4, 24) + self::mul($a5, $b3, 24) + self::mul($a6, $b2, 24) + self::mul($a7, $b1, 24) + self::mul($a8, $b0, 24); $s9 = $c9 + self::mul($a0, $b9, 24) + self::mul($a1, $b8, 24) + self::mul($a2, $b7, 24) + self::mul($a3, $b6, 24) + self::mul($a4, $b5, 24) + self::mul($a5, $b4, 24) + self::mul($a6, $b3, 24) + self::mul($a7, $b2, 24) + self::mul($a8, $b1, 24) + self::mul($a9, $b0, 24); $s10 = $c10 + self::mul($a0, $b10, 24) + self::mul($a1, $b9, 24) + self::mul($a2, $b8, 24) + self::mul($a3, $b7, 24) + self::mul($a4, $b6, 24) + self::mul($a5, $b5, 24) + self::mul($a6, $b4, 24) + self::mul($a7, $b3, 24) + self::mul($a8, $b2, 24) + self::mul($a9, $b1, 24) + self::mul($a10, $b0, 24); $s11 = $c11 + self::mul($a0, $b11, 24) + self::mul($a1, $b10, 24) + self::mul($a2, $b9, 24) + self::mul($a3, $b8, 24) + self::mul($a4, $b7, 24) + self::mul($a5, $b6, 24) + self::mul($a6, $b5, 24) + self::mul($a7, $b4, 24) + self::mul($a8, $b3, 24) + self::mul($a9, $b2, 24) + self::mul($a10, $b1, 24) + self::mul($a11, $b0, 24); $s12 = self::mul($a1, $b11, 24) + self::mul($a2, $b10, 24) + self::mul($a3, $b9, 24) + self::mul($a4, $b8, 24) + self::mul($a5, $b7, 24) + self::mul($a6, $b6, 24) + self::mul($a7, $b5, 24) + self::mul($a8, $b4, 24) + self::mul($a9, $b3, 24) + self::mul($a10, $b2, 24) + self::mul($a11, $b1, 24); $s13 = self::mul($a2, $b11, 24) + self::mul($a3, $b10, 24) + self::mul($a4, $b9, 24) + self::mul($a5, $b8, 24) + self::mul($a6, $b7, 24) + self::mul($a7, $b6, 24) + self::mul($a8, $b5, 24) + self::mul($a9, $b4, 24) + self::mul($a10, $b3, 24) + self::mul($a11, $b2, 24); $s14 = self::mul($a3, $b11, 24) + self::mul($a4, $b10, 24) + self::mul($a5, $b9, 24) + self::mul($a6, $b8, 24) + self::mul($a7, $b7, 24) + self::mul($a8, $b6, 24) + self::mul($a9, $b5, 24) + self::mul($a10, $b4, 24) + self::mul($a11, $b3, 24); $s15 = self::mul($a4, $b11, 24) + self::mul($a5, $b10, 24) + self::mul($a6, $b9, 24) + self::mul($a7, $b8, 24) + self::mul($a8, $b7, 24) + self::mul($a9, $b6, 24) + self::mul($a10, $b5, 24) + self::mul($a11, $b4, 24); $s16 = self::mul($a5, $b11, 24) + self::mul($a6, $b10, 24) + self::mul($a7, $b9, 24) + self::mul($a8, $b8, 24) + self::mul($a9, $b7, 24) + self::mul($a10, $b6, 24) + self::mul($a11, $b5, 24); $s17 = self::mul($a6, $b11, 24) + self::mul($a7, $b10, 24) + self::mul($a8, $b9, 24) + self::mul($a9, $b8, 24) + self::mul($a10, $b7, 24) + self::mul($a11, $b6, 24); $s18 = self::mul($a7, $b11, 24) + self::mul($a8, $b10, 24) + self::mul($a9, $b9, 24) + self::mul($a10, $b8, 24) + self::mul($a11, $b7, 24); $s19 = self::mul($a8, $b11, 24) + self::mul($a9, $b10, 24) + self::mul($a10, $b9, 24) + self::mul($a11, $b8, 24); $s20 = self::mul($a9, $b11, 24) + self::mul($a10, $b10, 24) + self::mul($a11, $b9, 24); $s21 = self::mul($a10, $b11, 24) + self::mul($a11, $b10, 24); $s22 = self::mul($a11, $b11, 24); $s23 = 0; $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; $carry18 = ($s18 + (1 << 20)) >> 21; $s19 += $carry18; $s18 -= $carry18 << 21; $carry20 = ($s20 + (1 << 20)) >> 21; $s21 += $carry20; $s20 -= $carry20 << 21; $carry22 = ($s22 + (1 << 20)) >> 21; $s23 += $carry22; $s22 -= $carry22 << 21; $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; $carry17 = ($s17 + (1 << 20)) >> 21; $s18 += $carry17; $s17 -= $carry17 << 21; $carry19 = ($s19 + (1 << 20)) >> 21; $s20 += $carry19; $s19 -= $carry19 << 21; $carry21 = ($s21 + (1 << 20)) >> 21; $s22 += $carry21; $s21 -= $carry21 << 21; $s11 += self::mul($s23, 666643, 20); $s12 += self::mul($s23, 470296, 19); $s13 += self::mul($s23, 654183, 20); $s14 -= self::mul($s23, 997805, 20); $s15 += self::mul($s23, 136657, 18); $s16 -= self::mul($s23, 683901, 20); $s10 += self::mul($s22, 666643, 20); $s11 += self::mul($s22, 470296, 19); $s12 += self::mul($s22, 654183, 20); $s13 -= self::mul($s22, 997805, 20); $s14 += self::mul($s22, 136657, 18); $s15 -= self::mul($s22, 683901, 20); $s9 += self::mul($s21, 666643, 20); $s10 += self::mul($s21, 470296, 19); $s11 += self::mul($s21, 654183, 20); $s12 -= self::mul($s21, 997805, 20); $s13 += self::mul($s21, 136657, 18); $s14 -= self::mul($s21, 683901, 20); $s8 += self::mul($s20, 666643, 20); $s9 += self::mul($s20, 470296, 19); $s10 += self::mul($s20, 654183, 20); $s11 -= self::mul($s20, 997805, 20); $s12 += self::mul($s20, 136657, 18); $s13 -= self::mul($s20, 683901, 20); $s7 += self::mul($s19, 666643, 20); $s8 += self::mul($s19, 470296, 19); $s9 += self::mul($s19, 654183, 20); $s10 -= self::mul($s19, 997805, 20); $s11 += self::mul($s19, 136657, 18); $s12 -= self::mul($s19, 683901, 20); $s6 += self::mul($s18, 666643, 20); $s7 += self::mul($s18, 470296, 19); $s8 += self::mul($s18, 654183, 20); $s9 -= self::mul($s18, 997805, 20); $s10 += self::mul($s18, 136657, 18); $s11 -= self::mul($s18, 683901, 20); $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; $s5 += self::mul($s17, 666643, 20); $s6 += self::mul($s17, 470296, 19); $s7 += self::mul($s17, 654183, 20); $s8 -= self::mul($s17, 997805, 20); $s9 += self::mul($s17, 136657, 18); $s10 -= self::mul($s17, 683901, 20); $s4 += self::mul($s16, 666643, 20); $s5 += self::mul($s16, 470296, 19); $s6 += self::mul($s16, 654183, 20); $s7 -= self::mul($s16, 997805, 20); $s8 += self::mul($s16, 136657, 18); $s9 -= self::mul($s16, 683901, 20); $s3 += self::mul($s15, 666643, 20); $s4 += self::mul($s15, 470296, 19); $s5 += self::mul($s15, 654183, 20); $s6 -= self::mul($s15, 997805, 20); $s7 += self::mul($s15, 136657, 18); $s8 -= self::mul($s15, 683901, 20); $s2 += self::mul($s14, 666643, 20); $s3 += self::mul($s14, 470296, 19); $s4 += self::mul($s14, 654183, 20); $s5 -= self::mul($s14, 997805, 20); $s6 += self::mul($s14, 136657, 18); $s7 -= self::mul($s14, 683901, 20); $s1 += self::mul($s13, 666643, 20); $s2 += self::mul($s13, 470296, 19); $s3 += self::mul($s13, 654183, 20); $s4 -= self::mul($s13, 997805, 20); $s5 += self::mul($s13, 136657, 18); $s6 -= self::mul($s13, 683901, 20); $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $s12 = 0; $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $s12 = 0; $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry11 = $s11 >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; /** * @var array */ $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)), 0xff & ($s11 >> 17) ); return self::intArrayToString($arr); } /** * @internal You should not use this directly from another application * * @param string $s * @return string * @throws TypeError */ public static function sc_reduce($s) { $s0 = 2097151 & self::load_3(self::substr($s, 0, 3)); $s1 = 2097151 & (self::load_4(self::substr($s, 2, 4)) >> 5); $s2 = 2097151 & (self::load_3(self::substr($s, 5, 3)) >> 2); $s3 = 2097151 & (self::load_4(self::substr($s, 7, 4)) >> 7); $s4 = 2097151 & (self::load_4(self::substr($s, 10, 4)) >> 4); $s5 = 2097151 & (self::load_3(self::substr($s, 13, 3)) >> 1); $s6 = 2097151 & (self::load_4(self::substr($s, 15, 4)) >> 6); $s7 = 2097151 & (self::load_3(self::substr($s, 18, 4)) >> 3); $s8 = 2097151 & self::load_3(self::substr($s, 21, 3)); $s9 = 2097151 & (self::load_4(self::substr($s, 23, 4)) >> 5); $s10 = 2097151 & (self::load_3(self::substr($s, 26, 3)) >> 2); $s11 = 2097151 & (self::load_4(self::substr($s, 28, 4)) >> 7); $s12 = 2097151 & (self::load_4(self::substr($s, 31, 4)) >> 4); $s13 = 2097151 & (self::load_3(self::substr($s, 34, 3)) >> 1); $s14 = 2097151 & (self::load_4(self::substr($s, 36, 4)) >> 6); $s15 = 2097151 & (self::load_3(self::substr($s, 39, 4)) >> 3); $s16 = 2097151 & self::load_3(self::substr($s, 42, 3)); $s17 = 2097151 & (self::load_4(self::substr($s, 44, 4)) >> 5); $s18 = 2097151 & (self::load_3(self::substr($s, 47, 3)) >> 2); $s19 = 2097151 & (self::load_4(self::substr($s, 49, 4)) >> 7); $s20 = 2097151 & (self::load_4(self::substr($s, 52, 4)) >> 4); $s21 = 2097151 & (self::load_3(self::substr($s, 55, 3)) >> 1); $s22 = 2097151 & (self::load_4(self::substr($s, 57, 4)) >> 6); $s23 = 0x1fffffff & (self::load_4(self::substr($s, 60, 4)) >> 3); $s11 += self::mul($s23, 666643, 20); $s12 += self::mul($s23, 470296, 19); $s13 += self::mul($s23, 654183, 20); $s14 -= self::mul($s23, 997805, 20); $s15 += self::mul($s23, 136657, 18); $s16 -= self::mul($s23, 683901, 20); $s10 += self::mul($s22, 666643, 20); $s11 += self::mul($s22, 470296, 19); $s12 += self::mul($s22, 654183, 20); $s13 -= self::mul($s22, 997805, 20); $s14 += self::mul($s22, 136657, 18); $s15 -= self::mul($s22, 683901, 20); $s9 += self::mul($s21, 666643, 20); $s10 += self::mul($s21, 470296, 19); $s11 += self::mul($s21, 654183, 20); $s12 -= self::mul($s21, 997805, 20); $s13 += self::mul($s21, 136657, 18); $s14 -= self::mul($s21, 683901, 20); $s8 += self::mul($s20, 666643, 20); $s9 += self::mul($s20, 470296, 19); $s10 += self::mul($s20, 654183, 20); $s11 -= self::mul($s20, 997805, 20); $s12 += self::mul($s20, 136657, 18); $s13 -= self::mul($s20, 683901, 20); $s7 += self::mul($s19, 666643, 20); $s8 += self::mul($s19, 470296, 19); $s9 += self::mul($s19, 654183, 20); $s10 -= self::mul($s19, 997805, 20); $s11 += self::mul($s19, 136657, 18); $s12 -= self::mul($s19, 683901, 20); $s6 += self::mul($s18, 666643, 20); $s7 += self::mul($s18, 470296, 19); $s8 += self::mul($s18, 654183, 20); $s9 -= self::mul($s18, 997805, 20); $s10 += self::mul($s18, 136657, 18); $s11 -= self::mul($s18, 683901, 20); $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; $s5 += self::mul($s17, 666643, 20); $s6 += self::mul($s17, 470296, 19); $s7 += self::mul($s17, 654183, 20); $s8 -= self::mul($s17, 997805, 20); $s9 += self::mul($s17, 136657, 18); $s10 -= self::mul($s17, 683901, 20); $s4 += self::mul($s16, 666643, 20); $s5 += self::mul($s16, 470296, 19); $s6 += self::mul($s16, 654183, 20); $s7 -= self::mul($s16, 997805, 20); $s8 += self::mul($s16, 136657, 18); $s9 -= self::mul($s16, 683901, 20); $s3 += self::mul($s15, 666643, 20); $s4 += self::mul($s15, 470296, 19); $s5 += self::mul($s15, 654183, 20); $s6 -= self::mul($s15, 997805, 20); $s7 += self::mul($s15, 136657, 18); $s8 -= self::mul($s15, 683901, 20); $s2 += self::mul($s14, 666643, 20); $s3 += self::mul($s14, 470296, 19); $s4 += self::mul($s14, 654183, 20); $s5 -= self::mul($s14, 997805, 20); $s6 += self::mul($s14, 136657, 18); $s7 -= self::mul($s14, 683901, 20); $s1 += self::mul($s13, 666643, 20); $s2 += self::mul($s13, 470296, 19); $s3 += self::mul($s13, 654183, 20); $s4 -= self::mul($s13, 997805, 20); $s5 += self::mul($s13, 136657, 18); $s6 -= self::mul($s13, 683901, 20); $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $s12 = 0; $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $s12 = 0; $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry11 = $s11 >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; /** * @var array */ $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_Core_Curve25519_Ge_P3 $A * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 */ public static function ge_mul_l(ParagonIE_Sodium_Core_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 $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); } /** * @param string $a * @param string $b * @return string */ public static function sc25519_mul($a, $b) { // int64_t a0 = 2097151 & load_3(a); // int64_t a1 = 2097151 & (load_4(a + 2) >> 5); // int64_t a2 = 2097151 & (load_3(a + 5) >> 2); // int64_t a3 = 2097151 & (load_4(a + 7) >> 7); // int64_t a4 = 2097151 & (load_4(a + 10) >> 4); // int64_t a5 = 2097151 & (load_3(a + 13) >> 1); // int64_t a6 = 2097151 & (load_4(a + 15) >> 6); // int64_t a7 = 2097151 & (load_3(a + 18) >> 3); // int64_t a8 = 2097151 & load_3(a + 21); // int64_t a9 = 2097151 & (load_4(a + 23) >> 5); // int64_t a10 = 2097151 & (load_3(a + 26) >> 2); // int64_t a11 = (load_4(a + 28) >> 7); $a0 = 2097151 & self::load_3(self::substr($a, 0, 3)); $a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5); $a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2); $a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7); $a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4); $a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1); $a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6); $a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3); $a8 = 2097151 & self::load_3(self::substr($a, 21, 3)); $a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5); $a10 = 2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2); $a11 = (self::load_4(self::substr($a, 28, 4)) >> 7); // int64_t b0 = 2097151 & load_3(b); // int64_t b1 = 2097151 & (load_4(b + 2) >> 5); // int64_t b2 = 2097151 & (load_3(b + 5) >> 2); // int64_t b3 = 2097151 & (load_4(b + 7) >> 7); // int64_t b4 = 2097151 & (load_4(b + 10) >> 4); // int64_t b5 = 2097151 & (load_3(b + 13) >> 1); // int64_t b6 = 2097151 & (load_4(b + 15) >> 6); // int64_t b7 = 2097151 & (load_3(b + 18) >> 3); // int64_t b8 = 2097151 & load_3(b + 21); // int64_t b9 = 2097151 & (load_4(b + 23) >> 5); // int64_t b10 = 2097151 & (load_3(b + 26) >> 2); // int64_t b11 = (load_4(b + 28) >> 7); $b0 = 2097151 & self::load_3(self::substr($b, 0, 3)); $b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5); $b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2); $b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7); $b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4); $b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1); $b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6); $b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3); $b8 = 2097151 & self::load_3(self::substr($b, 21, 3)); $b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5); $b10 = 2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2); $b11 = (self::load_4(self::substr($b, 28, 4)) >> 7); // s0 = a0 * b0; // s1 = a0 * b1 + a1 * b0; // s2 = a0 * b2 + a1 * b1 + a2 * b0; // s3 = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; // s4 = a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; // s5 = a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; // s6 = a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; // s7 = a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + // a6 * b1 + a7 * b0; // s8 = a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + // a6 * b2 + a7 * b1 + a8 * b0; // s9 = a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + // a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; // s10 = a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + // a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; // s11 = a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + // a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; // s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + // a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; // s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + // a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; // s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + // a9 * b5 + a10 * b4 + a11 * b3; // s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + // a10 * b5 + a11 * b4; // s16 = // a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; // s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; // s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; // s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; // s20 = a9 * b11 + a10 * b10 + a11 * b9; // s21 = a10 * b11 + a11 * b10; // s22 = a11 * b11; // s23 = 0; $s0 = self::mul($a0, $b0, 22); $s1 = self::mul($a0, $b1, 22) + self::mul($a1, $b0, 22); $s2 = self::mul($a0, $b2, 22) + self::mul($a1, $b1, 22) + self::mul($a2, $b0, 22); $s3 = self::mul($a0, $b3, 22) + self::mul($a1, $b2, 22) + self::mul($a2, $b1, 22) + self::mul($a3, $b0, 22); $s4 = self::mul($a0, $b4, 22) + self::mul($a1, $b3, 22) + self::mul($a2, $b2, 22) + self::mul($a3, $b1, 22) + self::mul($a4, $b0, 22); $s5 = self::mul($a0, $b5, 22) + self::mul($a1, $b4, 22) + self::mul($a2, $b3, 22) + self::mul($a3, $b2, 22) + self::mul($a4, $b1, 22) + self::mul($a5, $b0, 22); $s6 = self::mul($a0, $b6, 22) + self::mul($a1, $b5, 22) + self::mul($a2, $b4, 22) + self::mul($a3, $b3, 22) + self::mul($a4, $b2, 22) + self::mul($a5, $b1, 22) + self::mul($a6, $b0, 22); $s7 = self::mul($a0, $b7, 22) + self::mul($a1, $b6, 22) + self::mul($a2, $b5, 22) + self::mul($a3, $b4, 22) + self::mul($a4, $b3, 22) + self::mul($a5, $b2, 22) + self::mul($a6, $b1, 22) + self::mul($a7, $b0, 22); $s8 = self::mul($a0, $b8, 22) + self::mul($a1, $b7, 22) + self::mul($a2, $b6, 22) + self::mul($a3, $b5, 22) + self::mul($a4, $b4, 22) + self::mul($a5, $b3, 22) + self::mul($a6, $b2, 22) + self::mul($a7, $b1, 22) + self::mul($a8, $b0, 22); $s9 = self::mul($a0, $b9, 22) + self::mul($a1, $b8, 22) + self::mul($a2, $b7, 22) + self::mul($a3, $b6, 22) + self::mul($a4, $b5, 22) + self::mul($a5, $b4, 22) + self::mul($a6, $b3, 22) + self::mul($a7, $b2, 22) + self::mul($a8, $b1, 22) + self::mul($a9, $b0, 22); $s10 = self::mul($a0, $b10, 22) + self::mul($a1, $b9, 22) + self::mul($a2, $b8, 22) + self::mul($a3, $b7, 22) + self::mul($a4, $b6, 22) + self::mul($a5, $b5, 22) + self::mul($a6, $b4, 22) + self::mul($a7, $b3, 22) + self::mul($a8, $b2, 22) + self::mul($a9, $b1, 22) + self::mul($a10, $b0, 22); $s11 = self::mul($a0, $b11, 22) + self::mul($a1, $b10, 22) + self::mul($a2, $b9, 22) + self::mul($a3, $b8, 22) + self::mul($a4, $b7, 22) + self::mul($a5, $b6, 22) + self::mul($a6, $b5, 22) + self::mul($a7, $b4, 22) + self::mul($a8, $b3, 22) + self::mul($a9, $b2, 22) + self::mul($a10, $b1, 22) + self::mul($a11, $b0, 22); $s12 = self::mul($a1, $b11, 22) + self::mul($a2, $b10, 22) + self::mul($a3, $b9, 22) + self::mul($a4, $b8, 22) + self::mul($a5, $b7, 22) + self::mul($a6, $b6, 22) + self::mul($a7, $b5, 22) + self::mul($a8, $b4, 22) + self::mul($a9, $b3, 22) + self::mul($a10, $b2, 22) + self::mul($a11, $b1, 22); $s13 = self::mul($a2, $b11, 22) + self::mul($a3, $b10, 22) + self::mul($a4, $b9, 22) + self::mul($a5, $b8, 22) + self::mul($a6, $b7, 22) + self::mul($a7, $b6, 22) + self::mul($a8, $b5, 22) + self::mul($a9, $b4, 22) + self::mul($a10, $b3, 22) + self::mul($a11, $b2, 22); $s14 = self::mul($a3, $b11, 22) + self::mul($a4, $b10, 22) + self::mul($a5, $b9, 22) + self::mul($a6, $b8, 22) + self::mul($a7, $b7, 22) + self::mul($a8, $b6, 22) + self::mul($a9, $b5, 22) + self::mul($a10, $b4, 22) + self::mul($a11, $b3, 22); $s15 = self::mul($a4, $b11, 22) + self::mul($a5, $b10, 22) + self::mul($a6, $b9, 22) + self::mul($a7, $b8, 22) + self::mul($a8, $b7, 22) + self::mul($a9, $b6, 22) + self::mul($a10, $b5, 22) + self::mul($a11, $b4, 22); $s16 = self::mul($a5, $b11, 22) + self::mul($a6, $b10, 22) + self::mul($a7, $b9, 22) + self::mul($a8, $b8, 22) + self::mul($a9, $b7, 22) + self::mul($a10, $b6, 22) + self::mul($a11, $b5, 22); $s17 = self::mul($a6, $b11, 22) + self::mul($a7, $b10, 22) + self::mul($a8, $b9, 22) + self::mul($a9, $b8, 22) + self::mul($a10, $b7, 22) + self::mul($a11, $b6, 22); $s18 = self::mul($a7, $b11, 22) + self::mul($a8, $b10, 22) + self::mul($a9, $b9, 22) + self::mul($a10, $b8, 22) + self::mul($a11, $b7, 22); $s19 = self::mul($a8, $b11, 22) + self::mul($a9, $b10, 22) + self::mul($a10, $b9, 22) + self::mul($a11, $b8, 22); $s20 = self::mul($a9, $b11, 22) + self::mul($a10, $b10, 22) + self::mul($a11, $b9, 22); $s21 = self::mul($a10, $b11, 22) + self::mul($a11, $b10, 22); $s22 = self::mul($a11, $b11, 22); $s23 = 0; // carry0 = (s0 + (int64_t) (1L << 20)) >> 21; // s1 += carry0; // s0 -= carry0 * ((uint64_t) 1L << 21); $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; // carry2 = (s2 + (int64_t) (1L << 20)) >> 21; // s3 += carry2; // s2 -= carry2 * ((uint64_t) 1L << 21); $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; // carry4 = (s4 + (int64_t) (1L << 20)) >> 21; // s5 += carry4; // s4 -= carry4 * ((uint64_t) 1L << 21); $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; // carry6 = (s6 + (int64_t) (1L << 20)) >> 21; // s7 += carry6; // s6 -= carry6 * ((uint64_t) 1L << 21); $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; // carry8 = (s8 + (int64_t) (1L << 20)) >> 21; // s9 += carry8; // s8 -= carry8 * ((uint64_t) 1L << 21); $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; // carry10 = (s10 + (int64_t) (1L << 20)) >> 21; // s11 += carry10; // s10 -= carry10 * ((uint64_t) 1L << 21); $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; // carry12 = (s12 + (int64_t) (1L << 20)) >> 21; // s13 += carry12; // s12 -= carry12 * ((uint64_t) 1L << 21); $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; // carry14 = (s14 + (int64_t) (1L << 20)) >> 21; // s15 += carry14; // s14 -= carry14 * ((uint64_t) 1L << 21); $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; // carry16 = (s16 + (int64_t) (1L << 20)) >> 21; // s17 += carry16; // s16 -= carry16 * ((uint64_t) 1L << 21); $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; // carry18 = (s18 + (int64_t) (1L << 20)) >> 21; // s19 += carry18; // s18 -= carry18 * ((uint64_t) 1L << 21); $carry18 = ($s18 + (1 << 20)) >> 21; $s19 += $carry18; $s18 -= $carry18 << 21; // carry20 = (s20 + (int64_t) (1L << 20)) >> 21; // s21 += carry20; // s20 -= carry20 * ((uint64_t) 1L << 21); $carry20 = ($s20 + (1 << 20)) >> 21; $s21 += $carry20; $s20 -= $carry20 << 21; // carry22 = (s22 + (int64_t) (1L << 20)) >> 21; // s23 += carry22; // s22 -= carry22 * ((uint64_t) 1L << 21); $carry22 = ($s22 + (1 << 20)) >> 21; $s23 += $carry22; $s22 -= $carry22 << 21; // carry1 = (s1 + (int64_t) (1L << 20)) >> 21; // s2 += carry1; // s1 -= carry1 * ((uint64_t) 1L << 21); $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; // carry3 = (s3 + (int64_t) (1L << 20)) >> 21; // s4 += carry3; // s3 -= carry3 * ((uint64_t) 1L << 21); $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; // carry5 = (s5 + (int64_t) (1L << 20)) >> 21; // s6 += carry5; // s5 -= carry5 * ((uint64_t) 1L << 21); $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; // carry7 = (s7 + (int64_t) (1L << 20)) >> 21; // s8 += carry7; // s7 -= carry7 * ((uint64_t) 1L << 21); $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; // carry9 = (s9 + (int64_t) (1L << 20)) >> 21; // s10 += carry9; // s9 -= carry9 * ((uint64_t) 1L << 21); $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; // carry11 = (s11 + (int64_t) (1L << 20)) >> 21; // s12 += carry11; // s11 -= carry11 * ((uint64_t) 1L << 21); $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; // carry13 = (s13 + (int64_t) (1L << 20)) >> 21; // s14 += carry13; // s13 -= carry13 * ((uint64_t) 1L << 21); $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; // carry15 = (s15 + (int64_t) (1L << 20)) >> 21; // s16 += carry15; // s15 -= carry15 * ((uint64_t) 1L << 21); $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; // carry17 = (s17 + (int64_t) (1L << 20)) >> 21; // s18 += carry17; // s17 -= carry17 * ((uint64_t) 1L << 21); $carry17 = ($s17 + (1 << 20)) >> 21; $s18 += $carry17; $s17 -= $carry17 << 21; // carry19 = (s19 + (int64_t) (1L << 20)) >> 21; // s20 += carry19; // s19 -= carry19 * ((uint64_t) 1L << 21); $carry19 = ($s19 + (1 << 20)) >> 21; $s20 += $carry19; $s19 -= $carry19 << 21; // carry21 = (s21 + (int64_t) (1L << 20)) >> 21; // s22 += carry21; // s21 -= carry21 * ((uint64_t) 1L << 21); $carry21 = ($s21 + (1 << 20)) >> 21; $s22 += $carry21; $s21 -= $carry21 << 21; // s11 += s23 * 666643; // s12 += s23 * 470296; // s13 += s23 * 654183; // s14 -= s23 * 997805; // s15 += s23 * 136657; // s16 -= s23 * 683901; $s11 += self::mul($s23, 666643, 20); $s12 += self::mul($s23, 470296, 19); $s13 += self::mul($s23, 654183, 20); $s14 -= self::mul($s23, 997805, 20); $s15 += self::mul($s23, 136657, 18); $s16 -= self::mul($s23, 683901, 20); // s10 += s22 * 666643; // s11 += s22 * 470296; // s12 += s22 * 654183; // s13 -= s22 * 997805; // s14 += s22 * 136657; // s15 -= s22 * 683901; $s10 += self::mul($s22, 666643, 20); $s11 += self::mul($s22, 470296, 19); $s12 += self::mul($s22, 654183, 20); $s13 -= self::mul($s22, 997805, 20); $s14 += self::mul($s22, 136657, 18); $s15 -= self::mul($s22, 683901, 20); // s9 += s21 * 666643; // s10 += s21 * 470296; // s11 += s21 * 654183; // s12 -= s21 * 997805; // s13 += s21 * 136657; // s14 -= s21 * 683901; $s9 += self::mul($s21, 666643, 20); $s10 += self::mul($s21, 470296, 19); $s11 += self::mul($s21, 654183, 20); $s12 -= self::mul($s21, 997805, 20); $s13 += self::mul($s21, 136657, 18); $s14 -= self::mul($s21, 683901, 20); // s8 += s20 * 666643; // s9 += s20 * 470296; // s10 += s20 * 654183; // s11 -= s20 * 997805; // s12 += s20 * 136657; // s13 -= s20 * 683901; $s8 += self::mul($s20, 666643, 20); $s9 += self::mul($s20, 470296, 19); $s10 += self::mul($s20, 654183, 20); $s11 -= self::mul($s20, 997805, 20); $s12 += self::mul($s20, 136657, 18); $s13 -= self::mul($s20, 683901, 20); // s7 += s19 * 666643; // s8 += s19 * 470296; // s9 += s19 * 654183; // s10 -= s19 * 997805; // s11 += s19 * 136657; // s12 -= s19 * 683901; $s7 += self::mul($s19, 666643, 20); $s8 += self::mul($s19, 470296, 19); $s9 += self::mul($s19, 654183, 20); $s10 -= self::mul($s19, 997805, 20); $s11 += self::mul($s19, 136657, 18); $s12 -= self::mul($s19, 683901, 20); // s6 += s18 * 666643; // s7 += s18 * 470296; // s8 += s18 * 654183; // s9 -= s18 * 997805; // s10 += s18 * 136657; // s11 -= s18 * 683901; $s6 += self::mul($s18, 666643, 20); $s7 += self::mul($s18, 470296, 19); $s8 += self::mul($s18, 654183, 20); $s9 -= self::mul($s18, 997805, 20); $s10 += self::mul($s18, 136657, 18); $s11 -= self::mul($s18, 683901, 20); // carry6 = (s6 + (int64_t) (1L << 20)) >> 21; // s7 += carry6; // s6 -= carry6 * ((uint64_t) 1L << 21); $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; // carry8 = (s8 + (int64_t) (1L << 20)) >> 21; // s9 += carry8; // s8 -= carry8 * ((uint64_t) 1L << 21); $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; // carry10 = (s10 + (int64_t) (1L << 20)) >> 21; // s11 += carry10; // s10 -= carry10 * ((uint64_t) 1L << 21); $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; // carry12 = (s12 + (int64_t) (1L << 20)) >> 21; // s13 += carry12; // s12 -= carry12 * ((uint64_t) 1L << 21); $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; // carry14 = (s14 + (int64_t) (1L << 20)) >> 21; // s15 += carry14; // s14 -= carry14 * ((uint64_t) 1L << 21); $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; // carry16 = (s16 + (int64_t) (1L << 20)) >> 21; // s17 += carry16; // s16 -= carry16 * ((uint64_t) 1L << 21); $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; // carry7 = (s7 + (int64_t) (1L << 20)) >> 21; // s8 += carry7; // s7 -= carry7 * ((uint64_t) 1L << 21); $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; // carry9 = (s9 + (int64_t) (1L << 20)) >> 21; // s10 += carry9; // s9 -= carry9 * ((uint64_t) 1L << 21); $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; // carry11 = (s11 + (int64_t) (1L << 20)) >> 21; // s12 += carry11; // s11 -= carry11 * ((uint64_t) 1L << 21); $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; // carry13 = (s13 + (int64_t) (1L << 20)) >> 21; // s14 += carry13; // s13 -= carry13 * ((uint64_t) 1L << 21); $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; // carry15 = (s15 + (int64_t) (1L << 20)) >> 21; // s16 += carry15; // s15 -= carry15 * ((uint64_t) 1L << 21); $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; // s5 += s17 * 666643; // s6 += s17 * 470296; // s7 += s17 * 654183; // s8 -= s17 * 997805; // s9 += s17 * 136657; // s10 -= s17 * 683901; $s5 += self::mul($s17, 666643, 20); $s6 += self::mul($s17, 470296, 19); $s7 += self::mul($s17, 654183, 20); $s8 -= self::mul($s17, 997805, 20); $s9 += self::mul($s17, 136657, 18); $s10 -= self::mul($s17, 683901, 20); // s4 += s16 * 666643; // s5 += s16 * 470296; // s6 += s16 * 654183; // s7 -= s16 * 997805; // s8 += s16 * 136657; // s9 -= s16 * 683901; $s4 += self::mul($s16, 666643, 20); $s5 += self::mul($s16, 470296, 19); $s6 += self::mul($s16, 654183, 20); $s7 -= self::mul($s16, 997805, 20); $s8 += self::mul($s16, 136657, 18); $s9 -= self::mul($s16, 683901, 20); // s3 += s15 * 666643; // s4 += s15 * 470296; // s5 += s15 * 654183; // s6 -= s15 * 997805; // s7 += s15 * 136657; // s8 -= s15 * 683901; $s3 += self::mul($s15, 666643, 20); $s4 += self::mul($s15, 470296, 19); $s5 += self::mul($s15, 654183, 20); $s6 -= self::mul($s15, 997805, 20); $s7 += self::mul($s15, 136657, 18); $s8 -= self::mul($s15, 683901, 20); // s2 += s14 * 666643; // s3 += s14 * 470296; // s4 += s14 * 654183; // s5 -= s14 * 997805; // s6 += s14 * 136657; // s7 -= s14 * 683901; $s2 += self::mul($s14, 666643, 20); $s3 += self::mul($s14, 470296, 19); $s4 += self::mul($s14, 654183, 20); $s5 -= self::mul($s14, 997805, 20); $s6 += self::mul($s14, 136657, 18); $s7 -= self::mul($s14, 683901, 20); // s1 += s13 * 666643; // s2 += s13 * 470296; // s3 += s13 * 654183; // s4 -= s13 * 997805; // s5 += s13 * 136657; // s6 -= s13 * 683901; $s1 += self::mul($s13, 666643, 20); $s2 += self::mul($s13, 470296, 19); $s3 += self::mul($s13, 654183, 20); $s4 -= self::mul($s13, 997805, 20); $s5 += self::mul($s13, 136657, 18); $s6 -= self::mul($s13, 683901, 20); // s0 += s12 * 666643; // s1 += s12 * 470296; // s2 += s12 * 654183; // s3 -= s12 * 997805; // s4 += s12 * 136657; // s5 -= s12 * 683901; // s12 = 0; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $s12 = 0; // carry0 = (s0 + (int64_t) (1L << 20)) >> 21; // s1 += carry0; // s0 -= carry0 * ((uint64_t) 1L << 21); $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; // carry2 = (s2 + (int64_t) (1L << 20)) >> 21; // s3 += carry2; // s2 -= carry2 * ((uint64_t) 1L << 21); $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; // carry4 = (s4 + (int64_t) (1L << 20)) >> 21; // s5 += carry4; // s4 -= carry4 * ((uint64_t) 1L << 21); $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; // carry6 = (s6 + (int64_t) (1L << 20)) >> 21; // s7 += carry6; // s6 -= carry6 * ((uint64_t) 1L << 21); $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; // carry8 = (s8 + (int64_t) (1L << 20)) >> 21; // s9 += carry8; // s8 -= carry8 * ((uint64_t) 1L << 21); $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; // carry10 = (s10 + (int64_t) (1L << 20)) >> 21; // s11 += carry10; // s10 -= carry10 * ((uint64_t) 1L << 21); $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; // carry1 = (s1 + (int64_t) (1L << 20)) >> 21; // s2 += carry1; // s1 -= carry1 * ((uint64_t) 1L << 21); $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; // carry3 = (s3 + (int64_t) (1L << 20)) >> 21; // s4 += carry3; // s3 -= carry3 * ((uint64_t) 1L << 21); $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; // carry5 = (s5 + (int64_t) (1L << 20)) >> 21; // s6 += carry5; // s5 -= carry5 * ((uint64_t) 1L << 21); $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; // carry7 = (s7 + (int64_t) (1L << 20)) >> 21; // s8 += carry7; // s7 -= carry7 * ((uint64_t) 1L << 21); $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; // carry9 = (s9 + (int64_t) (1L << 20)) >> 21; // s10 += carry9; // s9 -= carry9 * ((uint64_t) 1L << 21); $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; // carry11 = (s11 + (int64_t) (1L << 20)) >> 21; // s12 += carry11; // s11 -= carry11 * ((uint64_t) 1L << 21); $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; // s0 += s12 * 666643; // s1 += s12 * 470296; // s2 += s12 * 654183; // s3 -= s12 * 997805; // s4 += s12 * 136657; // s5 -= s12 * 683901; // s12 = 0; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $s12 = 0; // carry0 = s0 >> 21; // s1 += carry0; // s0 -= carry0 * ((uint64_t) 1L << 21); $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; // carry1 = s1 >> 21; // s2 += carry1; // s1 -= carry1 * ((uint64_t) 1L << 21); $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; // carry2 = s2 >> 21; // s3 += carry2; // s2 -= carry2 * ((uint64_t) 1L << 21); $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; // carry3 = s3 >> 21; // s4 += carry3; // s3 -= carry3 * ((uint64_t) 1L << 21); $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; // carry4 = s4 >> 21; // s5 += carry4; // s4 -= carry4 * ((uint64_t) 1L << 21); $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; // carry5 = s5 >> 21; // s6 += carry5; // s5 -= carry5 * ((uint64_t) 1L << 21); $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; // carry6 = s6 >> 21; // s7 += carry6; // s6 -= carry6 * ((uint64_t) 1L << 21); $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; // carry7 = s7 >> 21; // s8 += carry7; // s7 -= carry7 * ((uint64_t) 1L << 21); $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; // carry8 = s8 >> 21; // s9 += carry8; // s8 -= carry8 * ((uint64_t) 1L << 21); $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; // carry9 = s9 >> 21; // s10 += carry9; // s9 -= carry9 * ((uint64_t) 1L << 21); $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; // carry10 = s10 >> 21; // s11 += carry10; // s10 -= carry10 * ((uint64_t) 1L << 21); $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; // carry11 = s11 >> 21; // s12 += carry11; // s11 -= carry11 * ((uint64_t) 1L << 21); $carry11 = $s11 >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; // s0 += s12 * 666643; // s1 += s12 * 470296; // s2 += s12 * 654183; // s3 -= s12 * 997805; // s4 += s12 * 136657; // s5 -= s12 * 683901; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); // carry0 = s0 >> 21; // s1 += carry0; // s0 -= carry0 * ((uint64_t) 1L << 21); $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; // carry1 = s1 >> 21; // s2 += carry1; // s1 -= carry1 * ((uint64_t) 1L << 21); $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; // carry2 = s2 >> 21; // s3 += carry2; // s2 -= carry2 * ((uint64_t) 1L << 21); $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; // carry3 = s3 >> 21; // s4 += carry3; // s3 -= carry3 * ((uint64_t) 1L << 21); $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; // carry4 = s4 >> 21; // s5 += carry4; // s4 -= carry4 * ((uint64_t) 1L << 21); $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; // carry5 = s5 >> 21; // s6 += carry5; // s5 -= carry5 * ((uint64_t) 1L << 21); $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; // carry6 = s6 >> 21; // s7 += carry6; // s6 -= carry6 * ((uint64_t) 1L << 21); $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; // carry7 = s7 >> 21; // s8 += carry7; // s7 -= carry7 * ((uint64_t) 1L << 21); $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; // carry8 = s8 >> 21; // s9 += carry8; // s8 -= carry8 * ((uint64_t) 1L << 21); $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; // carry9 = s9 >> 21; // s10 += carry9; // s9 -= carry9 * ((uint64_t) 1L << 21); $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; // carry10 = s10 >> 21; // s11 += carry10; // s10 -= carry10 * ((uint64_t) 1L << 21); $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $s = array_fill(0, 32, 0); // s[0] = s0 >> 0; $s[0] = $s0 >> 0; // s[1] = s0 >> 8; $s[1] = $s0 >> 8; // s[2] = (s0 >> 16) | (s1 * ((uint64_t) 1 << 5)); $s[2] = ($s0 >> 16) | ($s1 << 5); // s[3] = s1 >> 3; $s[3] = $s1 >> 3; // s[4] = s1 >> 11; $s[4] = $s1 >> 11; // s[5] = (s1 >> 19) | (s2 * ((uint64_t) 1 << 2)); $s[5] = ($s1 >> 19) | ($s2 << 2); // s[6] = s2 >> 6; $s[6] = $s2 >> 6; // s[7] = (s2 >> 14) | (s3 * ((uint64_t) 1 << 7)); $s[7] = ($s2 >> 14) | ($s3 << 7); // s[8] = s3 >> 1; $s[8] = $s3 >> 1; // s[9] = s3 >> 9; $s[9] = $s3 >> 9; // s[10] = (s3 >> 17) | (s4 * ((uint64_t) 1 << 4)); $s[10] = ($s3 >> 17) | ($s4 << 4); // s[11] = s4 >> 4; $s[11] = $s4 >> 4; // s[12] = s4 >> 12; $s[12] = $s4 >> 12; // s[13] = (s4 >> 20) | (s5 * ((uint64_t) 1 << 1)); $s[13] = ($s4 >> 20) | ($s5 << 1); // s[14] = s5 >> 7; $s[14] = $s5 >> 7; // s[15] = (s5 >> 15) | (s6 * ((uint64_t) 1 << 6)); $s[15] = ($s5 >> 15) | ($s6 << 6); // s[16] = s6 >> 2; $s[16] = $s6 >> 2; // s[17] = s6 >> 10; $s[17] = $s6 >> 10; // s[18] = (s6 >> 18) | (s7 * ((uint64_t) 1 << 3)); $s[18] = ($s6 >> 18) | ($s7 << 3); // s[19] = s7 >> 5; $s[19] = $s7 >> 5; // s[20] = s7 >> 13; $s[20] = $s7 >> 13; // s[21] = s8 >> 0; $s[21] = $s8 >> 0; // s[22] = s8 >> 8; $s[22] = $s8 >> 8; // s[23] = (s8 >> 16) | (s9 * ((uint64_t) 1 << 5)); $s[23] = ($s8 >> 16) | ($s9 << 5); // s[24] = s9 >> 3; $s[24] = $s9 >> 3; // s[25] = s9 >> 11; $s[25] = $s9 >> 11; // s[26] = (s9 >> 19) | (s10 * ((uint64_t) 1 << 2)); $s[26] = ($s9 >> 19) | ($s10 << 2); // s[27] = s10 >> 6; $s[27] = $s10 >> 6; // s[28] = (s10 >> 14) | (s11 * ((uint64_t) 1 << 7)); $s[28] = ($s10 >> 14) | ($s11 << 7); // s[29] = s11 >> 1; $s[29] = $s11 >> 1; // s[30] = s11 >> 9; $s[30] = $s11 >> 9; // s[31] = s11 >> 17; $s[31] = $s11 >> 17; return self::intArrayToString($s); } /** * @param string $s * @return string */ public static function sc25519_sq($s) { return self::sc25519_mul($s, $s); } /** * @param string $s * @param int $n * @param string $a * @return string */ public static function sc25519_sqmul($s, $n, $a) { for ($i = 0; $i < $n; ++$i) { $s = self::sc25519_sq($s); } return self::sc25519_mul($s, $a); } /** * @param string $s * @return string */ public static function sc25519_invert($s) { $_10 = self::sc25519_sq($s); $_11 = self::sc25519_mul($s, $_10); $_100 = self::sc25519_mul($s, $_11); $_1000 = self::sc25519_sq($_100); $_1010 = self::sc25519_mul($_10, $_1000); $_1011 = self::sc25519_mul($s, $_1010); $_10000 = self::sc25519_sq($_1000); $_10110 = self::sc25519_sq($_1011); $_100000 = self::sc25519_mul($_1010, $_10110); $_100110 = self::sc25519_mul($_10000, $_10110); $_1000000 = self::sc25519_sq($_100000); $_1010000 = self::sc25519_mul($_10000, $_1000000); $_1010011 = self::sc25519_mul($_11, $_1010000); $_1100011 = self::sc25519_mul($_10000, $_1010011); $_1100111 = self::sc25519_mul($_100, $_1100011); $_1101011 = self::sc25519_mul($_100, $_1100111); $_10010011 = self::sc25519_mul($_1000000, $_1010011); $_10010111 = self::sc25519_mul($_100, $_10010011); $_10111101 = self::sc25519_mul($_100110, $_10010111); $_11010011 = self::sc25519_mul($_10110, $_10111101); $_11100111 = self::sc25519_mul($_1010000, $_10010111); $_11101011 = self::sc25519_mul($_100, $_11100111); $_11110101 = self::sc25519_mul($_1010, $_11101011); $recip = self::sc25519_mul($_1011, $_11110101); $recip = self::sc25519_sqmul($recip, 126, $_1010011); $recip = self::sc25519_sqmul($recip, 9, $_10); $recip = self::sc25519_mul($recip, $_11110101); $recip = self::sc25519_sqmul($recip, 7, $_1100111); $recip = self::sc25519_sqmul($recip, 9, $_11110101); $recip = self::sc25519_sqmul($recip, 11, $_10111101); $recip = self::sc25519_sqmul($recip, 8, $_11100111); $recip = self::sc25519_sqmul($recip, 9, $_1101011); $recip = self::sc25519_sqmul($recip, 6, $_1011); $recip = self::sc25519_sqmul($recip, 14, $_10010011); $recip = self::sc25519_sqmul($recip, 10, $_1100011); $recip = self::sc25519_sqmul($recip, 9, $_10010111); $recip = self::sc25519_sqmul($recip, 10, $_11110101); $recip = self::sc25519_sqmul($recip, 8, $_11010011); return self::sc25519_sqmul($recip, 8, $_11101011); } /** * @param string $s * @return string */ public static function clamp($s) { $s_ = self::stringToIntArray($s); $s_[0] &= 248; $s_[31] |= 64; $s_[31] &= 128; return self::intArrayToString($s_); } /** * Ensure limbs are less than 28 bits long to prevent float promotion. * * This uses a constant-time conditional swap under the hood. * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_normalize(ParagonIE_Sodium_Core_Curve25519_Fe $f) { $x = (PHP_INT_SIZE << 3) - 1; // 31 or 63 $g = self::fe_copy($f); for ($i = 0; $i < 10; ++$i) { $mask = -(($g[$i] >> $x) & 1); /* * Get two candidate normalized values for $g[$i], depending on the sign of $g[$i]: */ $a = $g[$i] & 0x7ffffff; $b = -((-$g[$i]) & 0x7ffffff); /* * Return the appropriate candidate value, based on the sign of the original input: * * The following is equivalent to this ternary: * * $g[$i] = (($g[$i] >> $x) & 1) ? $a : $b; * * Except what's written doesn't contain timing leaks. */ $g[$i] = ($a ^ (($a ^ $b) & $mask)); } return $g; } } PK!"MCore/Curve25519/Ge/P3.phpnu[X = $x; if ($y === null) { $y = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($y instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 2 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Y = $y; if ($z === null) { $z = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($z instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 3 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Z = $z; if ($t === null) { $t = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($t instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 4 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->T = $t; } } PK!Core/Curve25519/Ge/P2.phpnu[X = $x; if ($y === null) { $y = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($y instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 2 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Y = $y; if ($z === null) { $z = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($z instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 3 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Z = $z; } } PK!Core/Curve25519/Ge/P1p1.phpnu[X = $x; if ($y === null) { $y = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($y instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 2 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Y = $y; if ($z === null) { $z = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($z instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 3 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Z = $z; if ($t === null) { $t = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($t instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 4 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->T = $t; } } PK!rrCore/Curve25519/Ge/Precomp.phpnu[yplusx = $yplusx; if ($yminusx === null) { $yminusx = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($yminusx instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 2 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->yminusx = $yminusx; if ($xy2d === null) { $xy2d = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($xy2d instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 3 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->xy2d = $xy2d; } } PK!rB B Core/Curve25519/Ge/Cached.phpnu[YplusX = $YplusX; if ($YminusX === null) { $YminusX = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($YminusX instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 2 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->YminusX = $YminusX; if ($Z === null) { $Z = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($Z instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 3 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Z = $Z; if ($T2d === null) { $T2d = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($T2d instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 4 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->T2d = $T2d; } } PK!CUg  Core/Curve25519/Fe.phpnu[ */ protected $container = array(); /** * @var int */ protected $size = 10; /** * @internal You should not use this directly from another application * * @param array $array * @param bool $save_indexes * @return self */ public static function fromArray($array, $save_indexes = null) { $count = count($array); if ($save_indexes) { $keys = array_keys($array); } else { $keys = range(0, $count - 1); } $array = array_values($array); /** @var array $keys */ $obj = new ParagonIE_Sodium_Core_Curve25519_Fe(); if ($save_indexes) { for ($i = 0; $i < $count; ++$i) { $obj->offsetSet($keys[$i], $array[$i]); } } else { for ($i = 0; $i < $count; ++$i) { $obj->offsetSet($i, $array[$i]); } } return $obj; } /** * @internal You should not use this directly from another application * * @param int|null $offset * @param int $value * @return void * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!is_int($value)) { throw new InvalidArgumentException('Expected an integer'); } if (is_null($offset)) { $this->container[] = $value; } else { $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 int * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetGet($offset) { if (!isset($this->container[$offset])) { $this->container[$offset] = 0; } return (int) ($this->container[$offset]); } /** * @internal You should not use this directly from another application * * @return array */ public function __debugInfo() { return array(implode(', ', $this->container)); } } PK!珉Core/Curve25519/README.mdnu[# Curve25519 Data Structures These are PHP implementation of the [structs used in the ref10 curve25519 code](https://github.com/jedisct1/libsodium/blob/master/src/libsodium/include/sodium/private/curve25519_ref10.h). PK!}ڢTyyCore/Curve25519/H.phpnu[>>> Basically, int[32][8][3][10] */ protected static $base = array( array( array( array(25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605), array(-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378), array(-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546), ), array( array(-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303), array(-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081), array(26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697), ), array( array(15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024), array(16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574), array(30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357), ), array( array(-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540), array(23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397), array(7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325), ), array( array(10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380), array(4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306), array(19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942), ), array( array(-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777), array(-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737), array(-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652), ), array( array(5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766), array(-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701), array(28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300), ), array( array(14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726), array(-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955), array(27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425), ), ), array( array( array(-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171), array(27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510), array(17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660), ), array( array(-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639), array(29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963), array(5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950), ), array( array(-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568), array(12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335), array(25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628), ), array( array(-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007), array(-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772), array(-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653), ), array( array(2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567), array(13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686), array(21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372), ), array( array(-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887), array(-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954), array(-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953), ), array( array(24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833), array(-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532), array(-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876), ), array( array(2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268), array(33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214), array(1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038), ), ), array( array( array(6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800), array(4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645), array(-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664), ), array( array(1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933), array(-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182), array(-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222), ), array( array(-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991), array(20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880), array(9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092), ), array( array(-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295), array(19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788), array(8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553), ), array( array(-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026), array(11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347), array(-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033), ), array( array(-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395), array(-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278), array(1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890), ), array( array(32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995), array(-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596), array(-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891), ), array( array(31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060), array(11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608), array(-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606), ), ), array( array( array(7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389), array(-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016), array(-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341), ), array( array(-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505), array(14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553), array(-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655), ), array( array(15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220), array(12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631), array(-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099), ), array( array(26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556), array(14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749), array(236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930), ), array( array(1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391), array(5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253), array(20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066), ), array( array(24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958), array(-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082), array(-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383), ), array( array(-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521), array(-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807), array(23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948), ), array( array(9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134), array(-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455), array(27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629), ), ), array( array( array(-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069), array(-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746), array(24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919), ), array( array(11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837), array(8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906), array(-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771), ), array( array(-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817), array(10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098), array(10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409), ), array( array(-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504), array(-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727), array(28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420), ), array( array(-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003), array(-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605), array(-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384), ), array( array(-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701), array(-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683), array(29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708), ), array( array(-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563), array(-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260), array(-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387), ), array( array(-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672), array(23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686), array(-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665), ), ), array( array( array(11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182), array(-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277), array(14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628), ), array( array(-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474), array(-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539), array(-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822), ), array( array(-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970), array(19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756), array(-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508), ), array( array(-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683), array(-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655), array(-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158), ), array( array(-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125), array(-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839), array(-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664), ), array( array(27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294), array(-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899), array(-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070), ), array( array(3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294), array(-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949), array(-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083), ), array( array(31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420), array(-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940), array(29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396), ), ), array( array( array(-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567), array(20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127), array(-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294), ), array( array(-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887), array(22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964), array(16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195), ), array( array(9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244), array(24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999), array(-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762), ), array( array(-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274), array(-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236), array(-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605), ), array( array(-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761), array(-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884), array(-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482), ), array( array(-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638), array(-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490), array(-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170), ), array( array(5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736), array(10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124), array(-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392), ), array( array(8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029), array(6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048), array(28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958), ), ), array( array( array(24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593), array(26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071), array(-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692), ), array( array(11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687), array(-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441), array(-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001), ), array( array(-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460), array(-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007), array(-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762), ), array( array(15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005), array(-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674), array(4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035), ), array( array(7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590), array(-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957), array(-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812), ), array( array(33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740), array(-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122), array(-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158), ), array( array(8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885), array(26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140), array(19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857), ), array( array(801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155), array(19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260), array(19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483), ), ), array( array( array(-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677), array(32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815), array(22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751), ), array( array(-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203), array(-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208), array(1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230), ), array( array(16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850), array(-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389), array(-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968), ), array( array(-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689), array(14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880), array(5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304), ), array( array(30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632), array(-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412), array(20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566), ), array( array(-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038), array(-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232), array(-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943), ), array( array(17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856), array(23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738), array(15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971), ), array( array(-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718), array(-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697), array(-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883), ), ), array( array( array(5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912), array(-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358), array(3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849), ), array( array(29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307), array(-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977), array(-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335), ), array( array(-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644), array(-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616), array(-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735), ), array( array(-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099), array(29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341), array(-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336), ), array( array(-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646), array(31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425), array(-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388), ), array( array(-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743), array(-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822), array(-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462), ), array( array(18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985), array(9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702), array(-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797), ), array( array(21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293), array(27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100), array(19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688), ), ), array( array( array(12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186), array(2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610), array(-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707), ), array( array(7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220), array(915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025), array(32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044), ), array( array(32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992), array(-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027), array(21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197), ), array( array(8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901), array(31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952), array(19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878), ), array( array(-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390), array(32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730), array(2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730), ), array( array(-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180), array(-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272), array(-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715), ), array( array(-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970), array(-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772), array(-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865), ), array( array(15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750), array(20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373), array(32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348), ), ), array( array( array(9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144), array(-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195), array(5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086), ), array( array(-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684), array(-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518), array(-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233), ), array( array(-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793), array(-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794), array(580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435), ), array( array(23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921), array(13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518), array(2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563), ), array( array(14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278), array(-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024), array(4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030), ), array( array(10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783), array(27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717), array(6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844), ), array( array(14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333), array(16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048), array(22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760), ), array( array(-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760), array(-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757), array(-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112), ), ), array( array( array(-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468), array(3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184), array(10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289), ), array( array(15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066), array(24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882), array(13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226), ), array( array(16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101), array(29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279), array(-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811), ), array( array(27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709), array(20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714), array(-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121), ), array( array(9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464), array(12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847), array(13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400), ), array( array(4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414), array(-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158), array(17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045), ), array( array(-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415), array(-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459), array(-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079), ), array( array(21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412), array(-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743), array(-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836), ), ), array( array( array(12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022), array(18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429), array(-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065), ), array( array(30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861), array(10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000), array(-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101), ), array( array(32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815), array(29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642), array(10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966), ), array( array(25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574), array(-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742), array(-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689), ), array( array(12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020), array(-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772), array(3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982), ), array( array(-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953), array(-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218), array(-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265), ), array( array(29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073), array(-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325), array(-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798), ), array( array(-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870), array(-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863), array(-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927), ), ), array( array( array(-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267), array(-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663), array(22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862), ), array( array(-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673), array(15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943), array(15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020), ), array( array(-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238), array(11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064), array(14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795), ), array( array(15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052), array(-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904), array(29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531), ), array( array(-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979), array(-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841), array(10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431), ), array( array(10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324), array(-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940), array(10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320), ), array( array(-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184), array(14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114), array(30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878), ), array( array(12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784), array(-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091), array(-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585), ), ), array( array( array(-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208), array(10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864), array(17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661), ), array( array(7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233), array(26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212), array(-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525), ), array( array(-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068), array(9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397), array(-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988), ), array( array(5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889), array(32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038), array(14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697), ), array( array(20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875), array(-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905), array(-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656), ), array( array(11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818), array(27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714), array(10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203), ), array( array(20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931), array(-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024), array(-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084), ), array( array(-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204), array(20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817), array(27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667), ), ), array( array( array(11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504), array(-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768), array(-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255), ), array( array(6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790), array(1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438), array(-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333), ), array( array(17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971), array(31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905), array(29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409), ), array( array(12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409), array(6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499), array(-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363), ), array( array(28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664), array(-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324), array(-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940), ), array( array(13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990), array(-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914), array(-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290), ), array( array(24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257), array(-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433), array(-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236), ), array( array(-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045), array(11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093), array(-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347), ), ), array( array( array(-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191), array(-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507), array(-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906), ), array( array(3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018), array(-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109), array(-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926), ), array( array(-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528), array(8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625), array(-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286), ), array( array(2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033), array(27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866), array(21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896), ), array( array(30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075), array(26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347), array(-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437), ), array( array(-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165), array(-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588), array(-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193), ), array( array(-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017), array(-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883), array(21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961), ), array( array(8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043), array(29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663), array(-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362), ), ), array( array( array(-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860), array(2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466), array(-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063), ), array( array(-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997), array(-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295), array(-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369), ), array( array(9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385), array(18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109), array(2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906), ), array( array(4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424), array(-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185), array(7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962), ), array( array(-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325), array(10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593), array(696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404), ), array( array(-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644), array(17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801), array(26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804), ), array( array(-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884), array(-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577), array(-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849), ), array( array(32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473), array(-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644), array(-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319), ), ), array( array( array(-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599), array(-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768), array(-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084), ), array( array(-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328), array(-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369), array(20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920), ), array( array(12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815), array(-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025), array(-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397), ), array( array(-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448), array(6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981), array(30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165), ), array( array(32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501), array(17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073), array(-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861), ), array( array(14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845), array(-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211), array(18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870), ), array( array(10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096), array(33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803), array(-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168), ), array( array(30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965), array(-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505), array(18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598), ), ), array( array( array(5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782), array(5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900), array(-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479), ), array( array(-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208), array(8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232), array(17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719), ), array( array(16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271), array(-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326), array(-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132), ), array( array(14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300), array(8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570), array(15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670), ), array( array(-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994), array(-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913), array(31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317), ), array( array(-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730), array(842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096), array(-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078), ), array( array(-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411), array(-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905), array(-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654), ), array( array(-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870), array(-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498), array(12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579), ), ), array( array( array(14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677), array(10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647), array(-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743), ), array( array(-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468), array(21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375), array(-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155), ), array( array(6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725), array(-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612), array(-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943), ), array( array(-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944), array(30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928), array(9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406), ), array( array(22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139), array(-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963), array(-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693), ), array( array(1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734), array(-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680), array(-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410), ), array( array(-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931), array(-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654), array(22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710), ), array( array(29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180), array(-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684), array(-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895), ), ), array( array( array(22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501), array(-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413), array(6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880), ), array( array(-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874), array(22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962), array(-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899), ), array( array(21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152), array(9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063), array(7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080), ), array( array(-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146), array(-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183), array(-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133), ), array( array(-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421), array(-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622), array(-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197), ), array( array(2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663), array(31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753), array(4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755), ), array( array(-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862), array(-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118), array(26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171), ), array( array(15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380), array(16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824), array(28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270), ), ), array( array( array(-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438), array(-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584), array(-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562), ), array( array(30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471), array(18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610), array(19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269), ), array( array(-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650), array(14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369), array(19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461), ), array( array(30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462), array(-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793), array(-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218), ), array( array(-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226), array(18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019), array(-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037), ), array( array(31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171), array(-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132), array(-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841), ), array( array(21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181), array(-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210), array(-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040), ), array( array(3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935), array(24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105), array(-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814), ), ), array( array( array(793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852), array(5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581), array(-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646), ), array( array(10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844), array(10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025), array(27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453), ), array( array(-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068), array(4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192), array(-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921), ), array( array(-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259), array(-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426), array(-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072), ), array( array(-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305), array(13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832), array(28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943), ), array( array(-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011), array(24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447), array(17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494), ), array( array(-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245), array(-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859), array(28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915), ), array( array(16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707), array(10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848), array(-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224), ), ), array( array( array(-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391), array(15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215), array(-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101), ), array( array(23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713), array(21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849), array(-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930), ), array( array(-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940), array(-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031), array(-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404), ), array( array(-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243), array(-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116), array(-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525), ), array( array(-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509), array(-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883), array(15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865), ), array( array(-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660), array(4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273), array(-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138), ), array( array(-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560), array(-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135), array(2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941), ), array( array(-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739), array(18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756), array(-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819), ), ), array( array( array(-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347), array(-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028), array(21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075), ), array( array(16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799), array(-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609), array(-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817), ), array( array(-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989), array(-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523), array(4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278), ), array( array(31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045), array(19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377), array(24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480), ), array( array(17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016), array(510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426), array(18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525), ), array( array(13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396), array(9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080), array(12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892), ), array( array(15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275), array(11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074), array(20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140), ), array( array(-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717), array(-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101), array(24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127), ), ), array( array( array(-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632), array(-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415), array(-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160), ), array( array(31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876), array(22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625), array(-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478), ), array( array(27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164), array(26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595), array(-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248), ), array( array(-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858), array(15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193), array(8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184), ), array( array(-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942), array(-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635), array(21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948), ), array( array(11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935), array(-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415), array(-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416), ), array( array(-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018), array(4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778), array(366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659), ), array( array(-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385), array(18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503), array(476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329), ), ), array( array( array(20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056), array(-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838), array(24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948), ), array( array(-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691), array(-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118), array(-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517), ), array( array(-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269), array(-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904), array(-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589), ), array( array(-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193), array(-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910), array(-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930), ), array( array(-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667), array(25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481), array(-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876), ), array( array(22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640), array(-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278), array(-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112), ), array( array(26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272), array(17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012), array(-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221), ), array( array(30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046), array(13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345), array(-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310), ), ), array( array( array(19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937), array(31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636), array(-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008), ), array( array(-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429), array(-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576), array(31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066), ), array( array(-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490), array(-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104), array(33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053), ), array( array(31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275), array(-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511), array(22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095), ), array( array(-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439), array(23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939), array(-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424), ), array( array(2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310), array(3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608), array(-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079), ), array( array(-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101), array(21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418), array(18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576), ), array( array(30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356), array(9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996), array(-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099), ), ), array( array( array(-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728), array(-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658), array(-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242), ), array( array(-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001), array(-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766), array(18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373), ), array( array(26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458), array(-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628), array(-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657), ), array( array(-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062), array(25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616), array(31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014), ), array( array(24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383), array(-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814), array(-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718), ), array( array(30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417), array(2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222), array(33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444), ), array( array(-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597), array(23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970), array(1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799), ), array( array(-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647), array(13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511), array(-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032), ), ), array( array( array(9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834), array(-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461), array(29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062), ), array( array(-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516), array(-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547), array(-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240), ), array( array(-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038), array(-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741), array(16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103), ), array( array(-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747), array(-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323), array(31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016), ), array( array(-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373), array(15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228), array(-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141), ), array( array(16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399), array(11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831), array(-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376), ), array( array(-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313), array(-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958), array(-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577), ), array( array(-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743), array(29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684), array(-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476), ), ) ); /** * See: libsodium's crypto_core/curve25519/ref10/base2.h * * @var array basically int[8][3] */ protected static $base2 = array( array( array(25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605), array(-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378), array(-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546), ), array( array(15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024), array(16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574), array(30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357), ), array( array(10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380), array(4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306), array(19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942), ), array( array(5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766), array(-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701), array(28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300), ), array( array(-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877), array(-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951), array(4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784), ), array( array(-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436), array(25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918), array(23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877), ), array( array(-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800), array(-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305), array(-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300), ), array( array(-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876), array(-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619), array(-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683), ) ); /** * 37095705934669439343138083508754565189542113879843219016388785533085940283555 * * @var array */ protected static $d = array( -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116 ); /** * 2 * d = 16295367250680780974490674513165176452449235426866156013048779062215315747161 * * @var array */ protected static $d2 = array( -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 ); /** * sqrt(-1) * * @var array */ protected static $sqrtm1 = array( -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482 ); /** * 1 / sqrt(a - d) * * @var array */ protected static $invsqrtamd = array( 6111485, 4156064, -27798727, 12243468, -25904040, 120897, 20826367, -7060776, 6093568, -1986012 ); /** * sqrt(ad - 1) with a = -1 (mod p) * * @var array */ protected static $sqrtadm1 = array( 24849947, -153582, -23613485, 6347715, -21072328, -667138, -25271143, -15367704, -870347, 14525639 ); /** * 1 - d ^ 2 * * @var array */ protected static $onemsqd = array( 6275446, -16617371, -22938544, -3773710, 11667077, 7397348, -27922721, 1766195, -24433858, 672203 ); /** * (d - 1) ^ 2 * @var array */ protected static $sqdmone = array( 15551795, -11097455, -13425098, -10125071, -11896535, 10178284, -26634327, 4729244, -5282110, -10116402 ); /* * 2^252+27742317777372353535851937790883648493 static const unsigned char L[] = { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }; */ const L = "\xed\xd3\xf5\x5c\x1a\x63\x12\x58\xd6\x9c\xf7\xa2\xde\xf9\xde\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10"; } PK!YYCore/HSalsa20.phpnu[ 0; $i -= 2) { $x4 ^= self::rotate($x0 + $x12, 7); $x8 ^= self::rotate($x4 + $x0, 9); $x12 ^= self::rotate($x8 + $x4, 13); $x0 ^= self::rotate($x12 + $x8, 18); $x9 ^= self::rotate($x5 + $x1, 7); $x13 ^= self::rotate($x9 + $x5, 9); $x1 ^= self::rotate($x13 + $x9, 13); $x5 ^= self::rotate($x1 + $x13, 18); $x14 ^= self::rotate($x10 + $x6, 7); $x2 ^= self::rotate($x14 + $x10, 9); $x6 ^= self::rotate($x2 + $x14, 13); $x10 ^= self::rotate($x6 + $x2, 18); $x3 ^= self::rotate($x15 + $x11, 7); $x7 ^= self::rotate($x3 + $x15, 9); $x11 ^= self::rotate($x7 + $x3, 13); $x15 ^= self::rotate($x11 + $x7, 18); $x1 ^= self::rotate($x0 + $x3, 7); $x2 ^= self::rotate($x1 + $x0, 9); $x3 ^= self::rotate($x2 + $x1, 13); $x0 ^= self::rotate($x3 + $x2, 18); $x6 ^= self::rotate($x5 + $x4, 7); $x7 ^= self::rotate($x6 + $x5, 9); $x4 ^= self::rotate($x7 + $x6, 13); $x5 ^= self::rotate($x4 + $x7, 18); $x11 ^= self::rotate($x10 + $x9, 7); $x8 ^= self::rotate($x11 + $x10, 9); $x9 ^= self::rotate($x8 + $x11, 13); $x10 ^= self::rotate($x9 + $x8, 18); $x12 ^= self::rotate($x15 + $x14, 7); $x13 ^= self::rotate($x12 + $x15, 9); $x14 ^= self::rotate($x13 + $x12, 13); $x15 ^= self::rotate($x14 + $x13, 18); } return self::store32_le($x0) . self::store32_le($x5) . self::store32_le($x10) . self::store32_le($x15) . self::store32_le($x6) . self::store32_le($x7) . self::store32_le($x8) . self::store32_le($x9); } } PK!f( > > Core/AES.phpnu[orthogonalize(); self::sbox($q); $q->orthogonalize(); return $q[0] & self::U32_MAX; } /** * Calculate the key schedule from a given random key * * @param string $key * @return ParagonIE_Sodium_Core_AES_KeySchedule * @throws SodiumException */ public static function keySchedule($key) { $key_len = self::strlen($key); switch ($key_len) { case 16: $num_rounds = 10; break; case 24: $num_rounds = 12; break; case 32: $num_rounds = 14; break; default: throw new SodiumException('Invalid key length: ' . $key_len); } $skey = array(); $comp_skey = array(); $nk = $key_len >> 2; $nkf = ($num_rounds + 1) << 2; $tmp = 0; for ($i = 0; $i < $nk; ++$i) { $tmp = self::load_4(self::substr($key, $i << 2, 4)); $skey[($i << 1)] = $tmp; $skey[($i << 1) + 1] = $tmp; } for ($i = $nk, $j = 0, $k = 0; $i < $nkf; ++$i) { if ($j === 0) { $tmp = (($tmp & 0xff) << 24) | ($tmp >> 8); $tmp = (self::subWord($tmp) ^ self::$Rcon[$k]) & self::U32_MAX; } elseif ($nk > 6 && $j === 4) { $tmp = self::subWord($tmp); } $tmp ^= $skey[($i - $nk) << 1]; $skey[($i << 1)] = $tmp & self::U32_MAX; $skey[($i << 1) + 1] = $tmp & self::U32_MAX; if (++$j === $nk) { /** @psalm-suppress LoopInvalidation */ $j = 0; ++$k; } } for ($i = 0; $i < $nkf; $i += 4) { $q = ParagonIE_Sodium_Core_AES_Block::fromArray( array_slice($skey, $i << 1, 8) ); $q->orthogonalize(); // We have to overwrite $skey since we're not using C pointers like BearSSL did for ($j = 0; $j < 8; ++$j) { $skey[($i << 1) + $j] = $q[$j]; } } for ($i = 0, $j = 0; $i < $nkf; ++$i, $j += 2) { $comp_skey[$i] = ($skey[$j] & 0x55555555) | ($skey[$j + 1] & 0xAAAAAAAA); } return new ParagonIE_Sodium_Core_AES_KeySchedule($comp_skey, $num_rounds); } /** * Mutates $q * * @param ParagonIE_Sodium_Core_AES_KeySchedule $skey * @param ParagonIE_Sodium_Core_AES_Block $q * @param int $offset * @return void */ public static function addRoundKey( ParagonIE_Sodium_Core_AES_Block $q, ParagonIE_Sodium_Core_AES_KeySchedule $skey, $offset = 0 ) { $block = $skey->getRoundKey($offset); for ($j = 0; $j < 8; ++$j) { $q[$j] = ($q[$j] ^ $block[$j]) & ParagonIE_Sodium_Core_Util::U32_MAX; } } /** * This mainly exists for testing, as we need the round key features for AEGIS. * * @param string $message * @param string $key * @return string * @throws SodiumException */ public static function decryptBlockECB($message, $key) { if (self::strlen($message) !== 16) { throw new SodiumException('decryptBlockECB() expects a 16 byte message'); } $skey = self::keySchedule($key)->expand(); $q = ParagonIE_Sodium_Core_AES_Block::init(); $q[0] = self::load_4(self::substr($message, 0, 4)); $q[2] = self::load_4(self::substr($message, 4, 4)); $q[4] = self::load_4(self::substr($message, 8, 4)); $q[6] = self::load_4(self::substr($message, 12, 4)); $q->orthogonalize(); self::bitsliceDecryptBlock($skey, $q); $q->orthogonalize(); return self::store32_le($q[0]) . self::store32_le($q[2]) . self::store32_le($q[4]) . self::store32_le($q[6]); } /** * This mainly exists for testing, as we need the round key features for AEGIS. * * @param string $message * @param string $key * @return string * @throws SodiumException */ public static function encryptBlockECB($message, $key) { if (self::strlen($message) !== 16) { throw new SodiumException('encryptBlockECB() expects a 16 byte message'); } $comp_skey = self::keySchedule($key); $skey = $comp_skey->expand(); $q = ParagonIE_Sodium_Core_AES_Block::init(); $q[0] = self::load_4(self::substr($message, 0, 4)); $q[2] = self::load_4(self::substr($message, 4, 4)); $q[4] = self::load_4(self::substr($message, 8, 4)); $q[6] = self::load_4(self::substr($message, 12, 4)); $q->orthogonalize(); self::bitsliceEncryptBlock($skey, $q); $q->orthogonalize(); return self::store32_le($q[0]) . self::store32_le($q[2]) . self::store32_le($q[4]) . self::store32_le($q[6]); } /** * Mutates $q * * @param ParagonIE_Sodium_Core_AES_Expanded $skey * @param ParagonIE_Sodium_Core_AES_Block $q * @return void */ public static function bitsliceEncryptBlock( ParagonIE_Sodium_Core_AES_Expanded $skey, ParagonIE_Sodium_Core_AES_Block $q ) { self::addRoundKey($q, $skey); for ($u = 1; $u < $skey->getNumRounds(); ++$u) { self::sbox($q); $q->shiftRows(); $q->mixColumns(); self::addRoundKey($q, $skey, ($u << 3)); } self::sbox($q); $q->shiftRows(); self::addRoundKey($q, $skey, ($skey->getNumRounds() << 3)); } /** * @param string $x * @param string $y * @return string */ public static function aesRound($x, $y) { $q = ParagonIE_Sodium_Core_AES_Block::init(); $q[0] = self::load_4(self::substr($x, 0, 4)); $q[2] = self::load_4(self::substr($x, 4, 4)); $q[4] = self::load_4(self::substr($x, 8, 4)); $q[6] = self::load_4(self::substr($x, 12, 4)); $rk = ParagonIE_Sodium_Core_AES_Block::init(); $rk[0] = $rk[1] = self::load_4(self::substr($y, 0, 4)); $rk[2] = $rk[3] = self::load_4(self::substr($y, 4, 4)); $rk[4] = $rk[5] = self::load_4(self::substr($y, 8, 4)); $rk[6] = $rk[7] = self::load_4(self::substr($y, 12, 4)); $q->orthogonalize(); self::sbox($q); $q->shiftRows(); $q->mixColumns(); $q->orthogonalize(); // add round key without key schedule: for ($i = 0; $i < 8; ++$i) { $q[$i] ^= $rk[$i]; } return self::store32_le($q[0]) . self::store32_le($q[2]) . self::store32_le($q[4]) . self::store32_le($q[6]); } /** * Process two AES blocks in one shot. * * @param string $b0 First AES block * @param string $rk0 First round key * @param string $b1 Second AES block * @param string $rk1 Second round key * @return string[] */ public static function doubleRound($b0, $rk0, $b1, $rk1) { $q = ParagonIE_Sodium_Core_AES_Block::init(); // First block $q[0] = self::load_4(self::substr($b0, 0, 4)); $q[2] = self::load_4(self::substr($b0, 4, 4)); $q[4] = self::load_4(self::substr($b0, 8, 4)); $q[6] = self::load_4(self::substr($b0, 12, 4)); // Second block $q[1] = self::load_4(self::substr($b1, 0, 4)); $q[3] = self::load_4(self::substr($b1, 4, 4)); $q[5] = self::load_4(self::substr($b1, 8, 4)); $q[7] = self::load_4(self::substr($b1, 12, 4));; $rk = ParagonIE_Sodium_Core_AES_Block::init(); // First round key $rk[0] = self::load_4(self::substr($rk0, 0, 4)); $rk[2] = self::load_4(self::substr($rk0, 4, 4)); $rk[4] = self::load_4(self::substr($rk0, 8, 4)); $rk[6] = self::load_4(self::substr($rk0, 12, 4)); // Second round key $rk[1] = self::load_4(self::substr($rk1, 0, 4)); $rk[3] = self::load_4(self::substr($rk1, 4, 4)); $rk[5] = self::load_4(self::substr($rk1, 8, 4)); $rk[7] = self::load_4(self::substr($rk1, 12, 4)); $q->orthogonalize(); self::sbox($q); $q->shiftRows(); $q->mixColumns(); $q->orthogonalize(); // add round key without key schedule: for ($i = 0; $i < 8; ++$i) { $q[$i] ^= $rk[$i]; } return array( self::store32_le($q[0]) . self::store32_le($q[2]) . self::store32_le($q[4]) . self::store32_le($q[6]), self::store32_le($q[1]) . self::store32_le($q[3]) . self::store32_le($q[5]) . self::store32_le($q[7]), ); } /** * @param ParagonIE_Sodium_Core_AES_Expanded $skey * @param ParagonIE_Sodium_Core_AES_Block $q * @return void */ public static function bitsliceDecryptBlock( ParagonIE_Sodium_Core_AES_Expanded $skey, ParagonIE_Sodium_Core_AES_Block $q ) { self::addRoundKey($q, $skey, ($skey->getNumRounds() << 3)); for ($u = $skey->getNumRounds() - 1; $u > 0; --$u) { $q->inverseShiftRows(); self::invSbox($q); self::addRoundKey($q, $skey, ($u << 3)); $q->inverseMixColumns(); } $q->inverseShiftRows(); self::invSbox($q); self::addRoundKey($q, $skey, ($u << 3)); } } PK!Ӂ&&Core/Poly1305.phpnu[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_Core_Poly1305_State( self::substr($key, 0, 32) ); $calc = $state ->update($m) ->finish(); return self::verify_16($calc, $mac); } } PK!rS((Core/AES/Block.phpnu[ */ protected $values = array(); /** * @var int */ protected $size; /** * @param int $size */ public function __construct($size = 8) { parent::__construct($size); $this->size = $size; $this->values = array_fill(0, $size, 0); } /** * @return self */ public static function init() { return new self(8); } /** * @internal You should not use this directly from another application * * @param array $array * @param bool $save_indexes * @return self * * @psalm-suppress MethodSignatureMismatch */ #[ReturnTypeWillChange] public static function fromArray($array, $save_indexes = null) { $count = count($array); if ($save_indexes) { $keys = array_keys($array); } else { $keys = range(0, $count - 1); } $array = array_values($array); /** @var array $keys */ $obj = new ParagonIE_Sodium_Core_AES_Block(); if ($save_indexes) { for ($i = 0; $i < $count; ++$i) { $obj->offsetSet($keys[$i], $array[$i]); } } else { for ($i = 0; $i < $count; ++$i) { $obj->offsetSet($i, $array[$i]); } } return $obj; } /** * @internal You should not use this directly from another application * * @param int|null $offset * @param int $value * @return void * * @psalm-suppress MethodSignatureMismatch * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!is_int($value)) { throw new InvalidArgumentException('Expected an integer'); } if (is_null($offset)) { $this->values[] = $value; } else { $this->values[$offset] = $value; } } /** * @internal You should not use this directly from another application * * @param int $offset * @return bool * * @psalm-suppress MethodSignatureMismatch * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->values[$offset]); } /** * @internal You should not use this directly from another application * * @param int $offset * @return void * * @psalm-suppress MethodSignatureMismatch * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->values[$offset]); } /** * @internal You should not use this directly from another application * * @param int $offset * @return int * * @psalm-suppress MethodSignatureMismatch * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetGet($offset) { if (!isset($this->values[$offset])) { $this->values[$offset] = 0; } return (int) ($this->values[$offset]); } /** * @internal You should not use this directly from another application * * @return array */ public function __debugInfo() { $out = array(); foreach ($this->values as $v) { $out[] = str_pad(dechex($v), 8, '0', STR_PAD_LEFT); } return array(implode(', ', $out)); /* return array(implode(', ', $this->values)); */ } /** * @param int $cl low bit mask * @param int $ch high bit mask * @param int $s shift * @param int $x index 1 * @param int $y index 2 * @return self */ public function swapN($cl, $ch, $s, $x, $y) { static $u32mask = ParagonIE_Sodium_Core_Util::U32_MAX; $a = $this->values[$x] & $u32mask; $b = $this->values[$y] & $u32mask; // (x) = (a & cl) | ((b & cl) << (s)); $this->values[$x] = ($a & $cl) | ((($b & $cl) << $s) & $u32mask); // (y) = ((a & ch) >> (s)) | (b & ch); $this->values[$y] = ((($a & $ch) & $u32mask) >> $s) | ($b & $ch); return $this; } /** * @param int $x index 1 * @param int $y index 2 * @return self */ public function swap2($x, $y) { return $this->swapN(0x55555555, 0xAAAAAAAA, 1, $x, $y); } /** * @param int $x index 1 * @param int $y index 2 * @return self */ public function swap4($x, $y) { return $this->swapN(0x33333333, 0xCCCCCCCC, 2, $x, $y); } /** * @param int $x index 1 * @param int $y index 2 * @return self */ public function swap8($x, $y) { return $this->swapN(0x0F0F0F0F, 0xF0F0F0F0, 4, $x, $y); } /** * @return self */ public function orthogonalize() { return $this ->swap2(0, 1) ->swap2(2, 3) ->swap2(4, 5) ->swap2(6, 7) ->swap4(0, 2) ->swap4(1, 3) ->swap4(4, 6) ->swap4(5, 7) ->swap8(0, 4) ->swap8(1, 5) ->swap8(2, 6) ->swap8(3, 7); } /** * @return self */ public function shiftRows() { for ($i = 0; $i < 8; ++$i) { $x = $this->values[$i] & ParagonIE_Sodium_Core_Util::U32_MAX; $this->values[$i] = ( ($x & 0x000000FF) | (($x & 0x0000FC00) >> 2) | (($x & 0x00000300) << 6) | (($x & 0x00F00000) >> 4) | (($x & 0x000F0000) << 4) | (($x & 0xC0000000) >> 6) | (($x & 0x3F000000) << 2) ) & ParagonIE_Sodium_Core_Util::U32_MAX; } return $this; } /** * @param int $x * @return int */ public static function rotr16($x) { return (($x << 16) & ParagonIE_Sodium_Core_Util::U32_MAX) | ($x >> 16); } /** * @return self */ public function mixColumns() { $q0 = $this->values[0]; $q1 = $this->values[1]; $q2 = $this->values[2]; $q3 = $this->values[3]; $q4 = $this->values[4]; $q5 = $this->values[5]; $q6 = $this->values[6]; $q7 = $this->values[7]; $r0 = (($q0 >> 8) | ($q0 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r1 = (($q1 >> 8) | ($q1 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r2 = (($q2 >> 8) | ($q2 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r3 = (($q3 >> 8) | ($q3 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r4 = (($q4 >> 8) | ($q4 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r5 = (($q5 >> 8) | ($q5 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r6 = (($q6 >> 8) | ($q6 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r7 = (($q7 >> 8) | ($q7 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $this->values[0] = $q7 ^ $r7 ^ $r0 ^ self::rotr16($q0 ^ $r0); $this->values[1] = $q0 ^ $r0 ^ $q7 ^ $r7 ^ $r1 ^ self::rotr16($q1 ^ $r1); $this->values[2] = $q1 ^ $r1 ^ $r2 ^ self::rotr16($q2 ^ $r2); $this->values[3] = $q2 ^ $r2 ^ $q7 ^ $r7 ^ $r3 ^ self::rotr16($q3 ^ $r3); $this->values[4] = $q3 ^ $r3 ^ $q7 ^ $r7 ^ $r4 ^ self::rotr16($q4 ^ $r4); $this->values[5] = $q4 ^ $r4 ^ $r5 ^ self::rotr16($q5 ^ $r5); $this->values[6] = $q5 ^ $r5 ^ $r6 ^ self::rotr16($q6 ^ $r6); $this->values[7] = $q6 ^ $r6 ^ $r7 ^ self::rotr16($q7 ^ $r7); return $this; } /** * @return self */ public function inverseMixColumns() { $q0 = $this->values[0]; $q1 = $this->values[1]; $q2 = $this->values[2]; $q3 = $this->values[3]; $q4 = $this->values[4]; $q5 = $this->values[5]; $q6 = $this->values[6]; $q7 = $this->values[7]; $r0 = (($q0 >> 8) | ($q0 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r1 = (($q1 >> 8) | ($q1 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r2 = (($q2 >> 8) | ($q2 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r3 = (($q3 >> 8) | ($q3 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r4 = (($q4 >> 8) | ($q4 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r5 = (($q5 >> 8) | ($q5 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r6 = (($q6 >> 8) | ($q6 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r7 = (($q7 >> 8) | ($q7 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $this->values[0] = $q5 ^ $q6 ^ $q7 ^ $r0 ^ $r5 ^ $r7 ^ self::rotr16($q0 ^ $q5 ^ $q6 ^ $r0 ^ $r5); $this->values[1] = $q0 ^ $q5 ^ $r0 ^ $r1 ^ $r5 ^ $r6 ^ $r7 ^ self::rotr16($q1 ^ $q5 ^ $q7 ^ $r1 ^ $r5 ^ $r6); $this->values[2] = $q0 ^ $q1 ^ $q6 ^ $r1 ^ $r2 ^ $r6 ^ $r7 ^ self::rotr16($q0 ^ $q2 ^ $q6 ^ $r2 ^ $r6 ^ $r7); $this->values[3] = $q0 ^ $q1 ^ $q2 ^ $q5 ^ $q6 ^ $r0 ^ $r2 ^ $r3 ^ $r5 ^ self::rotr16($q0 ^ $q1 ^ $q3 ^ $q5 ^ $q6 ^ $q7 ^ $r0 ^ $r3 ^ $r5 ^ $r7); $this->values[4] = $q1 ^ $q2 ^ $q3 ^ $q5 ^ $r1 ^ $r3 ^ $r4 ^ $r5 ^ $r6 ^ $r7 ^ self::rotr16($q1 ^ $q2 ^ $q4 ^ $q5 ^ $q7 ^ $r1 ^ $r4 ^ $r5 ^ $r6); $this->values[5] = $q2 ^ $q3 ^ $q4 ^ $q6 ^ $r2 ^ $r4 ^ $r5 ^ $r6 ^ $r7 ^ self::rotr16($q2 ^ $q3 ^ $q5 ^ $q6 ^ $r2 ^ $r5 ^ $r6 ^ $r7); $this->values[6] = $q3 ^ $q4 ^ $q5 ^ $q7 ^ $r3 ^ $r5 ^ $r6 ^ $r7 ^ self::rotr16($q3 ^ $q4 ^ $q6 ^ $q7 ^ $r3 ^ $r6 ^ $r7); $this->values[7] = $q4 ^ $q5 ^ $q6 ^ $r4 ^ $r6 ^ $r7 ^ self::rotr16($q4 ^ $q5 ^ $q7 ^ $r4 ^ $r7); return $this; } /** * @return self */ public function inverseShiftRows() { for ($i = 0; $i < 8; ++$i) { $x = $this->values[$i]; $this->values[$i] = ParagonIE_Sodium_Core_Util::U32_MAX & ( ($x & 0x000000FF) | (($x & 0x00003F00) << 2) | (($x & 0x0000C000) >> 6) | (($x & 0x000F0000) << 4) | (($x & 0x00F00000) >> 4) | (($x & 0x03000000) << 6) | (($x & 0xFC000000) >> 2) ); } return $this; } } PK!00Core/AES/Expanded.phpnu[ $skey -- has size 120 */ protected $skey; /** @var bool $expanded */ protected $expanded = false; /** @var int $numRounds */ private $numRounds; /** * @param array $skey * @param int $numRounds */ public function __construct(array $skey, $numRounds = 10) { $this->skey = $skey; $this->numRounds = $numRounds; } /** * Get a value at an arbitrary index. Mostly used for unit testing. * * @param int $i * @return int */ public function get($i) { return $this->skey[$i]; } /** * @return int */ public function getNumRounds() { return $this->numRounds; } /** * @param int $offset * @return ParagonIE_Sodium_Core_AES_Block */ public function getRoundKey($offset) { return ParagonIE_Sodium_Core_AES_Block::fromArray( array_slice($this->skey, $offset, 8) ); } /** * Return an expanded key schedule * * @return ParagonIE_Sodium_Core_AES_Expanded */ public function expand() { $exp = new ParagonIE_Sodium_Core_AES_Expanded( array_fill(0, 120, 0), $this->numRounds ); $n = ($exp->numRounds + 1) << 2; for ($u = 0, $v = 0; $u < $n; ++$u, $v += 2) { $x = $y = $this->skey[$u]; $x &= 0x55555555; $exp->skey[$v] = ($x | ($x << 1)) & ParagonIE_Sodium_Core_Util::U32_MAX; $y &= 0xAAAAAAAA; $exp->skey[$v + 1] = ($y | ($y >> 1)) & ParagonIE_Sodium_Core_Util::U32_MAX; } return $exp; } } PK!umLDLDCore/Ed25519.phpnu[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 */ 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'); hash_update($hs, self::substr($az, 32, 32)); 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'); hash_update($hs, self::substr($sig, 0, 32)); hash_update($hs, self::substr($pk, 0, 32)); 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) && self::check_S_lt_L(self::substr($sig, 32, 32))) { throw new SodiumException('S < L - Invalid signature'); } if (self::small_order($sig)) { throw new SodiumException('Signature is on too small of an order'); } if ((self::chrToInt($sig[63]) & 224) !== 0) { throw new SodiumException('Invalid signature'); } $d = 0; for ($i = 0; $i < 32; ++$i) { $d |= self::chrToInt($pk[$i]); } if ($d === 0) { throw new SodiumException('All zero public key'); } /** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */ $orig = ParagonIE_Sodium_Compat::$fastMult; // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification. ParagonIE_Sodium_Compat::$fastMult = true; /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A */ $A = self::ge_frombytes_negate_vartime($pk); /** @var string $hDigest */ $hDigest = hash( 'sha512', self::substr($sig, 0, 32) . self::substr($pk, 0, 32) . $message, true ); /** @var string $h */ $h = self::sc_reduce($hDigest) . self::substr($hDigest, 32); /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P2 $R */ $R = self::ge_double_scalarmult_vartime( $h, $A, self::substr($sig, 32) ); /** @var string $rcheck */ $rcheck = self::ge_tobytes($R); // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before. ParagonIE_Sodium_Compat::$fastMult = $orig; return self::verify_32($rcheck, self::substr($sig, 0, 32)); } /** * @internal You should not use this directly from another application * * @param string $S * @return bool * @throws SodiumException * @throws TypeError */ public static function check_S_lt_L($S) { if (self::strlen($S) < 32) { throw new SodiumException('Signature must be 32 bytes'); } $L = array( 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 ); $c = 0; $n = 1; $i = 32; /** @var array $L */ do { --$i; $x = self::chrToInt($S[$i]); $c |= ( (($x - $L[$i]) >> 8) & $n ); $n &= ( (($x ^ $L[$i]) - 1) >> 8 ); } while ($i !== 0); return $c === 0; } /** * @param string $R * @return bool * @throws SodiumException * @throws TypeError */ public static function small_order($R) { /** @var array> $blocklist */ $blocklist = array( /* 0 (order 4) */ array( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), /* 1 (order 1) */ array( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), /* 2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */ array( 0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05 ), /* 55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */ array( 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a ), /* p-1 (order 2) */ array( 0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85 ), /* p (order 4) */ array( 0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa ), /* p+1 (order 1) */ array( 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f ), /* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */ array( 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f ), /* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */ array( 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f ), /* 2p-1 (order 2) */ array( 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ), /* 2p (order 4) */ array( 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ), /* 2p+1 (order 1) */ array( 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ) ); /** @var int $countBlocklist */ $countBlocklist = count($blocklist); for ($i = 0; $i < $countBlocklist; ++$i) { $c = 0; for ($j = 0; $j < 32; ++$j) { $c |= self::chrToInt($R[$j]) ^ (int) $blocklist[$i][$j]; } if ($c === 0) { return true; } } return false; } /** * @param string $s * @return string * @throws SodiumException */ public static function scalar_complement($s) { $t_ = self::L . str_repeat("\x00", 32); sodium_increment($t_); $s_ = $s . str_repeat("\x00", 32); ParagonIE_Sodium_Compat::sub($t_, $s_); return self::sc_reduce($t_); } /** * @return string * @throws SodiumException */ public static function scalar_random() { do { $r = ParagonIE_Sodium_Compat::randombytes_buf(self::SCALAR_BYTES); $r[self::SCALAR_BYTES - 1] = self::intToChr( self::chrToInt($r[self::SCALAR_BYTES - 1]) & 0x1f ); } while ( !self::check_S_lt_L($r) || ParagonIE_Sodium_Compat::is_zero($r) ); return $r; } /** * @param string $s * @return string * @throws SodiumException */ public static function scalar_negate($s) { $t_ = self::L . str_repeat("\x00", 32) ; $s_ = $s . str_repeat("\x00", 32) ; ParagonIE_Sodium_Compat::sub($t_, $s_); return self::sc_reduce($t_); } /** * @param string $a * @param string $b * @return string * @throws SodiumException */ public static function scalar_add($a, $b) { $a_ = $a . str_repeat("\x00", 32); $b_ = $b . str_repeat("\x00", 32); ParagonIE_Sodium_Compat::add($a_, $b_); return self::sc_reduce($a_); } /** * @param string $x * @param string $y * @return string * @throws SodiumException */ public static function scalar_sub($x, $y) { $yn = self::scalar_negate($y); return self::scalar_add($x, $yn); } } PK!LW33Core/Base64/UrlSafe.phpnu[ $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3)); $b0 = $chunk[1]; $b1 = $chunk[2]; $b2 = $chunk[3]; $dest .= self::encode6Bits( $b0 >> 2 ) . self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) . self::encode6Bits( $b2 & 63); } // The last chunk, which may have padding: if ($i < $srcLen) { /** @var array $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); $b0 = $chunk[1]; if ($i + 1 < $srcLen) { $b1 = $chunk[2]; $dest .= self::encode6Bits($b0 >> 2) . self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . self::encode6Bits(($b1 << 2) & 63); if ($pad) { $dest .= '='; } } else { $dest .= self::encode6Bits( $b0 >> 2) . self::encode6Bits(($b0 << 4) & 63); if ($pad) { $dest .= '=='; } } } return $dest; } /** * decode from base64 into binary * * Base64 character set "./[A-Z][a-z][0-9]" * * @param string $src * @param bool $strictPadding * @return string * @throws RangeException * @throws TypeError * @psalm-suppress RedundantCondition */ public static function decode($src, $strictPadding = false) { // Remove padding $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); if ($srcLen === 0) { return ''; } if ($strictPadding) { if (($srcLen & 3) === 0) { if ($src[$srcLen - 1] === '=') { $srcLen--; if ($src[$srcLen - 1] === '=') { $srcLen--; } } } if (($srcLen & 3) === 1) { throw new RangeException( 'Incorrect padding' ); } if ($src[$srcLen - 1] === '=') { throw new RangeException( 'Incorrect padding' ); } } else { $src = rtrim($src, '='); $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); } $err = 0; $dest = ''; // Main loop (no padding): for ($i = 0; $i + 4 <= $srcLen; $i += 4) { /** @var array $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4)); $c0 = self::decode6Bits($chunk[1]); $c1 = self::decode6Bits($chunk[2]); $c2 = self::decode6Bits($chunk[3]); $c3 = self::decode6Bits($chunk[4]); $dest .= pack( 'CCC', ((($c0 << 2) | ($c1 >> 4)) & 0xff), ((($c1 << 4) | ($c2 >> 2)) & 0xff), ((($c2 << 6) | $c3) & 0xff) ); $err |= ($c0 | $c1 | $c2 | $c3) >> 8; } // The last chunk, which may have padding: if ($i < $srcLen) { /** @var array $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); $c0 = self::decode6Bits($chunk[1]); if ($i + 2 < $srcLen) { $c1 = self::decode6Bits($chunk[2]); $c2 = self::decode6Bits($chunk[3]); $dest .= pack( 'CC', ((($c0 << 2) | ($c1 >> 4)) & 0xff), ((($c1 << 4) | ($c2 >> 2)) & 0xff) ); $err |= ($c0 | $c1 | $c2) >> 8; } elseif ($i + 1 < $srcLen) { $c1 = self::decode6Bits($chunk[2]); $dest .= pack( 'C', ((($c0 << 2) | ($c1 >> 4)) & 0xff) ); $err |= ($c0 | $c1) >> 8; } elseif ($i < $srcLen && $strictPadding) { $err |= 1; } } /** @var bool $check */ $check = ($err === 0); if (!$check) { throw new RangeException( 'Base64::decode() only expects characters in the correct base64 alphabet' ); } return $dest; } // COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE /** * Uses bitwise operators instead of table-lookups to turn 6-bit integers * into 8-bit integers. * * Base64 character set: * [A-Z] [a-z] [0-9] + / * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f * * @param int $src * @return int */ protected static function decode6Bits($src) { $ret = -1; // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64 $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70 $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70); // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5 $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5); // if ($src == 0x2c) $ret += 62 + 1; $ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63; // if ($src == 0x5f) ret += 63 + 1; $ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64; return $ret; } /** * Uses bitwise operators instead of table-lookups to turn 8-bit integers * into 6-bit integers. * * @param int $src * @return string */ protected static function encode6Bits($src) { $diff = 0x41; // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6 $diff += ((25 - $src) >> 8) & 6; // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75 $diff -= ((51 - $src) >> 8) & 75; // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13 $diff -= ((61 - $src) >> 8) & 13; // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3 $diff += ((62 - $src) >> 8) & 49; return pack('C', $src + $diff); } } PK!$T--Core/Base64/Original.phpnu[ $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3)); $b0 = $chunk[1]; $b1 = $chunk[2]; $b2 = $chunk[3]; $dest .= self::encode6Bits( $b0 >> 2 ) . self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) . self::encode6Bits( $b2 & 63); } // The last chunk, which may have padding: if ($i < $srcLen) { /** @var array $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); $b0 = $chunk[1]; if ($i + 1 < $srcLen) { $b1 = $chunk[2]; $dest .= self::encode6Bits($b0 >> 2) . self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . self::encode6Bits(($b1 << 2) & 63); if ($pad) { $dest .= '='; } } else { $dest .= self::encode6Bits( $b0 >> 2) . self::encode6Bits(($b0 << 4) & 63); if ($pad) { $dest .= '=='; } } } return $dest; } /** * decode from base64 into binary * * Base64 character set "./[A-Z][a-z][0-9]" * * @param string $src * @param bool $strictPadding * @return string * @throws RangeException * @throws TypeError * @psalm-suppress RedundantCondition */ public static function decode($src, $strictPadding = false) { // Remove padding $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); if ($srcLen === 0) { return ''; } if ($strictPadding) { if (($srcLen & 3) === 0) { if ($src[$srcLen - 1] === '=') { $srcLen--; if ($src[$srcLen - 1] === '=') { $srcLen--; } } } if (($srcLen & 3) === 1) { throw new RangeException( 'Incorrect padding' ); } if ($src[$srcLen - 1] === '=') { throw new RangeException( 'Incorrect padding' ); } } else { $src = rtrim($src, '='); $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); } $err = 0; $dest = ''; // Main loop (no padding): for ($i = 0; $i + 4 <= $srcLen; $i += 4) { /** @var array $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4)); $c0 = self::decode6Bits($chunk[1]); $c1 = self::decode6Bits($chunk[2]); $c2 = self::decode6Bits($chunk[3]); $c3 = self::decode6Bits($chunk[4]); $dest .= pack( 'CCC', ((($c0 << 2) | ($c1 >> 4)) & 0xff), ((($c1 << 4) | ($c2 >> 2)) & 0xff), ((($c2 << 6) | $c3) & 0xff) ); $err |= ($c0 | $c1 | $c2 | $c3) >> 8; } // The last chunk, which may have padding: if ($i < $srcLen) { /** @var array $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); $c0 = self::decode6Bits($chunk[1]); if ($i + 2 < $srcLen) { $c1 = self::decode6Bits($chunk[2]); $c2 = self::decode6Bits($chunk[3]); $dest .= pack( 'CC', ((($c0 << 2) | ($c1 >> 4)) & 0xff), ((($c1 << 4) | ($c2 >> 2)) & 0xff) ); $err |= ($c0 | $c1 | $c2) >> 8; } elseif ($i + 1 < $srcLen) { $c1 = self::decode6Bits($chunk[2]); $dest .= pack( 'C', ((($c0 << 2) | ($c1 >> 4)) & 0xff) ); $err |= ($c0 | $c1) >> 8; } elseif ($i < $srcLen && $strictPadding) { $err |= 1; } } /** @var bool $check */ $check = ($err === 0); if (!$check) { throw new RangeException( 'Base64::decode() only expects characters in the correct base64 alphabet' ); } return $dest; } // COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE /** * Uses bitwise operators instead of table-lookups to turn 6-bit integers * into 8-bit integers. * * Base64 character set: * [A-Z] [a-z] [0-9] + / * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f * * @param int $src * @return int */ protected static function decode6Bits($src) { $ret = -1; // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64 $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70 $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70); // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5 $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5); // if ($src == 0x2b) $ret += 62 + 1; $ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63; // if ($src == 0x2f) ret += 63 + 1; $ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64; return $ret; } /** * Uses bitwise operators instead of table-lookups to turn 8-bit integers * into 6-bit integers. * * @param int $src * @return string */ protected static function encode6Bits($src) { $diff = 0x41; // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6 $diff += ((25 - $src) >> 8) & 6; // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75 $diff -= ((51 - $src) >> 8) & 75; // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15 $diff -= ((61 - $src) >> 8) & 15; // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3 $diff += ((62 - $src) >> 8) & 3; return pack('C', $src + $diff); } } PK!0) ) Core/Salsa20.phpnu[ 0; $i -= 2) { $x4 ^= self::rotate($x0 + $x12, 7); $x8 ^= self::rotate($x4 + $x0, 9); $x12 ^= self::rotate($x8 + $x4, 13); $x0 ^= self::rotate($x12 + $x8, 18); $x9 ^= self::rotate($x5 + $x1, 7); $x13 ^= self::rotate($x9 + $x5, 9); $x1 ^= self::rotate($x13 + $x9, 13); $x5 ^= self::rotate($x1 + $x13, 18); $x14 ^= self::rotate($x10 + $x6, 7); $x2 ^= self::rotate($x14 + $x10, 9); $x6 ^= self::rotate($x2 + $x14, 13); $x10 ^= self::rotate($x6 + $x2, 18); $x3 ^= self::rotate($x15 + $x11, 7); $x7 ^= self::rotate($x3 + $x15, 9); $x11 ^= self::rotate($x7 + $x3, 13); $x15 ^= self::rotate($x11 + $x7, 18); $x1 ^= self::rotate($x0 + $x3, 7); $x2 ^= self::rotate($x1 + $x0, 9); $x3 ^= self::rotate($x2 + $x1, 13); $x0 ^= self::rotate($x3 + $x2, 18); $x6 ^= self::rotate($x5 + $x4, 7); $x7 ^= self::rotate($x6 + $x5, 9); $x4 ^= self::rotate($x7 + $x6, 13); $x5 ^= self::rotate($x4 + $x7, 18); $x11 ^= self::rotate($x10 + $x9, 7); $x8 ^= self::rotate($x11 + $x10, 9); $x9 ^= self::rotate($x8 + $x11, 13); $x10 ^= self::rotate($x9 + $x8, 18); $x12 ^= self::rotate($x15 + $x14, 7); $x13 ^= self::rotate($x12 + $x15, 9); $x14 ^= self::rotate($x13 + $x12, 13); $x15 ^= self::rotate($x14 + $x13, 18); } $x0 += $j0; $x1 += $j1; $x2 += $j2; $x3 += $j3; $x4 += $j4; $x5 += $j5; $x6 += $j6; $x7 += $j7; $x8 += $j8; $x9 += $j9; $x10 += $j10; $x11 += $j11; $x12 += $j12; $x13 += $j13; $x14 += $j14; $x15 += $j15; return self::store32_le($x0) . self::store32_le($x1) . self::store32_le($x2) . self::store32_le($x3) . self::store32_le($x4) . self::store32_le($x5) . self::store32_le($x6) . self::store32_le($x7) . self::store32_le($x8) . self::store32_le($x9) . self::store32_le($x10) . self::store32_le($x11) . self::store32_le($x12) . self::store32_le($x13) . self::store32_le($x14) . self::store32_le($x15); } /** * @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_Core_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 ) ); } /** * @internal You should not use this directly from another application * * @param int $u * @param int $c * @return int */ public static function rotate($u, $c) { $u &= 0xffffffff; $c %= 32; return (int) (0xffffffff & ( ($u << $c) | ($u >> (32 - $c)) ) ); } } PK!{[[Core/XSalsa20.phpnu[> 31) & 1; } /** * @param ParagonIE_Sodium_Core_Curve25519_Fe $u * @param ParagonIE_Sodium_Core_Curve25519_Fe $v * @return array{x: ParagonIE_Sodium_Core_Curve25519_Fe, nonsquare: int} * * @throws SodiumException */ public static function ristretto255_sqrt_ratio_m1( ParagonIE_Sodium_Core_Curve25519_Fe $u, ParagonIE_Sodium_Core_Curve25519_Fe $v ) { $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1); $v3 = self::fe_mul( self::fe_sq($v), $v ); /* v3 = v^3 */ $x = self::fe_mul( self::fe_mul( self::fe_sq($v3), $u ), $v ); /* x = uv^7 */ $x = self::fe_mul( self::fe_mul( self::fe_pow22523($x), /* x = (uv^7)^((q-5)/8) */ $v3 ), $u ); /* x = uv^3(uv^7)^((q-5)/8) */ $vxx = self::fe_mul( self::fe_sq($x), $v ); /* vx^2 */ $m_root_check = self::fe_sub($vxx, $u); /* vx^2-u */ $p_root_check = self::fe_add($vxx, $u); /* vx^2+u */ $f_root_check = self::fe_mul($u, $sqrtm1); /* u*sqrt(-1) */ $f_root_check = self::fe_add($vxx, $f_root_check); /* vx^2+u*sqrt(-1) */ $has_m_root = self::fe_iszero($m_root_check); $has_p_root = self::fe_iszero($p_root_check); $has_f_root = self::fe_iszero($f_root_check); $x_sqrtm1 = self::fe_mul($x, $sqrtm1); /* x*sqrt(-1) */ $x = self::fe_abs( self::fe_cmov($x, $x_sqrtm1, $has_p_root | $has_f_root) ); return array( 'x' => $x, 'nonsquare' => $has_m_root | $has_p_root ); } /** * @param string $s * @return int * @throws SodiumException */ public static function ristretto255_point_is_canonical($s) { $c = (self::chrToInt($s[31]) & 0x7f) ^ 0x7f; for ($i = 30; $i > 0; --$i) { $c |= self::chrToInt($s[$i]) ^ 0xff; } $c = ($c - 1) >> 8; $d = (0xed - 1 - self::chrToInt($s[0])) >> 8; $e = self::chrToInt($s[31]) >> 7; return 1 - ((($c & $d) | $e | self::chrToInt($s[0])) & 1); } /** * @param string $s * @param bool $skipCanonicalCheck * @return array{h: ParagonIE_Sodium_Core_Curve25519_Ge_P3, res: int} * @throws SodiumException */ public static function ristretto255_frombytes($s, $skipCanonicalCheck = false) { if (!$skipCanonicalCheck) { if (!self::ristretto255_point_is_canonical($s)) { throw new SodiumException('S is not canonical'); } } $s_ = self::fe_frombytes($s); $ss = self::fe_sq($s_); /* ss = s^2 */ $u1 = self::fe_sub(self::fe_1(), $ss); /* u1 = 1-ss */ $u1u1 = self::fe_sq($u1); /* u1u1 = u1^2 */ $u2 = self::fe_add(self::fe_1(), $ss); /* u2 = 1+ss */ $u2u2 = self::fe_sq($u2); /* u2u2 = u2^2 */ $v = self::fe_mul( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d), $u1u1 ); /* v = d*u1^2 */ $v = self::fe_neg($v); /* v = -d*u1^2 */ $v = self::fe_sub($v, $u2u2); /* v = -(d*u1^2)-u2^2 */ $v_u2u2 = self::fe_mul($v, $u2u2); /* v_u2u2 = v*u2^2 */ // fe25519_1(one); // notsquare = ristretto255_sqrt_ratio_m1(inv_sqrt, one, v_u2u2); $one = self::fe_1(); $result = self::ristretto255_sqrt_ratio_m1($one, $v_u2u2); $inv_sqrt = $result['x']; $notsquare = $result['nonsquare']; $h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(); $h->X = self::fe_mul($inv_sqrt, $u2); $h->Y = self::fe_mul(self::fe_mul($inv_sqrt, $h->X), $v); $h->X = self::fe_mul($h->X, $s_); $h->X = self::fe_abs( self::fe_add($h->X, $h->X) ); $h->Y = self::fe_mul($u1, $h->Y); $h->Z = self::fe_1(); $h->T = self::fe_mul($h->X, $h->Y); $res = - ((1 - $notsquare) | self::fe_isnegative($h->T) | self::fe_iszero($h->Y)); return array('h' => $h, 'res' => $res); } /** * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h * @return string * @throws SodiumException */ public static function ristretto255_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h) { $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1); $invsqrtamd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$invsqrtamd); $u1 = self::fe_add($h->Z, $h->Y); /* u1 = Z+Y */ $zmy = self::fe_sub($h->Z, $h->Y); /* zmy = Z-Y */ $u1 = self::fe_mul($u1, $zmy); /* u1 = (Z+Y)*(Z-Y) */ $u2 = self::fe_mul($h->X, $h->Y); /* u2 = X*Y */ $u1_u2u2 = self::fe_mul(self::fe_sq($u2), $u1); /* u1_u2u2 = u1*u2^2 */ $one = self::fe_1(); // fe25519_1(one); // (void) ristretto255_sqrt_ratio_m1(inv_sqrt, one, u1_u2u2); $result = self::ristretto255_sqrt_ratio_m1($one, $u1_u2u2); $inv_sqrt = $result['x']; $den1 = self::fe_mul($inv_sqrt, $u1); /* den1 = inv_sqrt*u1 */ $den2 = self::fe_mul($inv_sqrt, $u2); /* den2 = inv_sqrt*u2 */ $z_inv = self::fe_mul($h->T, self::fe_mul($den1, $den2)); /* z_inv = den1*den2*T */ $ix = self::fe_mul($h->X, $sqrtm1); /* ix = X*sqrt(-1) */ $iy = self::fe_mul($h->Y, $sqrtm1); /* iy = Y*sqrt(-1) */ $eden = self::fe_mul($den1, $invsqrtamd); $t_z_inv = self::fe_mul($h->T, $z_inv); /* t_z_inv = T*z_inv */ $rotate = self::fe_isnegative($t_z_inv); $x_ = self::fe_copy($h->X); $y_ = self::fe_copy($h->Y); $den_inv = self::fe_copy($den2); $x_ = self::fe_cmov($x_, $iy, $rotate); $y_ = self::fe_cmov($y_, $ix, $rotate); $den_inv = self::fe_cmov($den_inv, $eden, $rotate); $x_z_inv = self::fe_mul($x_, $z_inv); $y_ = self::fe_cneg($y_, self::fe_isnegative($x_z_inv)); // fe25519_sub(s_, h->Z, y_); // fe25519_mul(s_, den_inv, s_); // fe25519_abs(s_, s_); // fe25519_tobytes(s, s_); return self::fe_tobytes( self::fe_abs( self::fe_mul( $den_inv, self::fe_sub($h->Z, $y_) ) ) ); } /** * @param ParagonIE_Sodium_Core_Curve25519_Fe $t * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 * * @throws SodiumException */ public static function ristretto255_elligator(ParagonIE_Sodium_Core_Curve25519_Fe $t) { $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1); $onemsqd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$onemsqd); $d = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d); $sqdmone = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqdmone); $sqrtadm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtadm1); $one = self::fe_1(); $r = self::fe_mul($sqrtm1, self::fe_sq($t)); /* r = sqrt(-1)*t^2 */ $u = self::fe_mul(self::fe_add($r, $one), $onemsqd); /* u = (r+1)*(1-d^2) */ $c = self::fe_neg(self::fe_1()); /* c = -1 */ $rpd = self::fe_add($r, $d); /* rpd = r+d */ $v = self::fe_mul( self::fe_sub( $c, self::fe_mul($r, $d) ), $rpd ); /* v = (c-r*d)*(r+d) */ $result = self::ristretto255_sqrt_ratio_m1($u, $v); $s = $result['x']; $wasnt_square = 1 - $result['nonsquare']; $s_prime = self::fe_neg( self::fe_abs( self::fe_mul($s, $t) ) ); /* s_prime = -|s*t| */ $s = self::fe_cmov($s, $s_prime, $wasnt_square); $c = self::fe_cmov($c, $r, $wasnt_square); // fe25519_sub(n, r, one); /* n = r-1 */ // fe25519_mul(n, n, c); /* n = c*(r-1) */ // fe25519_mul(n, n, ed25519_sqdmone); /* n = c*(r-1)*(d-1)^2 */ // fe25519_sub(n, n, v); /* n = c*(r-1)*(d-1)^2-v */ $n = self::fe_sub( self::fe_mul( self::fe_mul( self::fe_sub($r, $one), $c ), $sqdmone ), $v ); /* n = c*(r-1)*(d-1)^2-v */ $w0 = self::fe_mul( self::fe_add($s, $s), $v ); /* w0 = 2s*v */ $w1 = self::fe_mul($n, $sqrtadm1); /* w1 = n*sqrt(ad-1) */ $ss = self::fe_sq($s); /* ss = s^2 */ $w2 = self::fe_sub($one, $ss); /* w2 = 1-s^2 */ $w3 = self::fe_add($one, $ss); /* w3 = 1+s^2 */ return new ParagonIE_Sodium_Core_Curve25519_Ge_P3( self::fe_mul($w0, $w3), self::fe_mul($w2, $w1), self::fe_mul($w1, $w3), self::fe_mul($w0, $w2) ); } /** * @param string $h * @return string * @throws SodiumException */ public static function ristretto255_from_hash($h) { if (self::strlen($h) !== 64) { throw new SodiumException('Hash must be 64 bytes'); } //fe25519_frombytes(r0, h); //fe25519_frombytes(r1, h + 32); $r0 = self::fe_frombytes(self::substr($h, 0, 32)); $r1 = self::fe_frombytes(self::substr($h, 32, 32)); //ristretto255_elligator(&p0, r0); //ristretto255_elligator(&p1, r1); $p0 = self::ristretto255_elligator($r0); $p1 = self::ristretto255_elligator($r1); //ge25519_p3_to_cached(&p1_cached, &p1); //ge25519_add_cached(&p_p1p1, &p0, &p1_cached); $p_p1p1 = self::ge_add( $p0, self::ge_p3_to_cached($p1) ); //ge25519_p1p1_to_p3(&p, &p_p1p1); //ristretto255_p3_tobytes(s, &p); return self::ristretto255_p3_tobytes( self::ge_p1p1_to_p3($p_p1p1) ); } /** * @param string $p * @return int * @throws SodiumException */ public static function is_valid_point($p) { $result = self::ristretto255_frombytes($p); if ($result['res'] !== 0) { return 0; } return 1; } /** * @param string $p * @param string $q * @return string * @throws SodiumException */ public static function ristretto255_add($p, $q) { $p_res = self::ristretto255_frombytes($p); $q_res = self::ristretto255_frombytes($q); if ($p_res['res'] !== 0 || $q_res['res'] !== 0) { throw new SodiumException('Could not add points'); } $p_p3 = $p_res['h']; $q_p3 = $q_res['h']; $q_cached = self::ge_p3_to_cached($q_p3); $r_p1p1 = self::ge_add($p_p3, $q_cached); $r_p3 = self::ge_p1p1_to_p3($r_p1p1); return self::ristretto255_p3_tobytes($r_p3); } /** * @param string $p * @param string $q * @return string * @throws SodiumException */ public static function ristretto255_sub($p, $q) { $p_res = self::ristretto255_frombytes($p); $q_res = self::ristretto255_frombytes($q); if ($p_res['res'] !== 0 || $q_res['res'] !== 0) { throw new SodiumException('Could not add points'); } $p_p3 = $p_res['h']; $q_p3 = $q_res['h']; $q_cached = self::ge_p3_to_cached($q_p3); $r_p1p1 = self::ge_sub($p_p3, $q_cached); $r_p3 = self::ge_p1p1_to_p3($r_p1p1); return self::ristretto255_p3_tobytes($r_p3); } /** * @param int $hLen * @param ?string $ctx * @param string $msg * @return string * @throws SodiumException * @psalm-suppress PossiblyInvalidArgument hash API */ protected static function h2c_string_to_hash_sha256($hLen, $ctx, $msg) { $h = array_fill(0, $hLen, 0); $ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0; if ($hLen > 0xff) { throw new SodiumException('Hash must be less than 256 bytes'); } if ($ctx_len > 0xff) { $st = hash_init('sha256'); self::hash_update($st, "H2C-OVERSIZE-DST-"); self::hash_update($st, $ctx); $ctx = hash_final($st, true); $ctx_len = 32; } $t = array(0, $hLen, 0); $ux = str_repeat("\0", 64); $st = hash_init('sha256'); self::hash_update($st, $ux); self::hash_update($st, $msg); self::hash_update($st, self::intArrayToString($t)); self::hash_update($st, $ctx); self::hash_update($st, self::intToChr($ctx_len)); $u0 = hash_final($st, true); for ($i = 0; $i < $hLen; $i += 64) { $ux = self::xorStrings($ux, $u0); ++$t[2]; $st = hash_init('sha256'); self::hash_update($st, $ux); self::hash_update($st, self::intToChr($t[2])); self::hash_update($st, $ctx); self::hash_update($st, self::intToChr($ctx_len)); $ux = hash_final($st, true); $amount = min($hLen - $i, 64); for ($j = 0; $j < $amount; ++$j) { $h[$i + $j] = self::chrToInt($ux[$i]); } } return self::intArrayToString(array_slice($h, 0, $hLen)); } /** * @param int $hLen * @param ?string $ctx * @param string $msg * @return string * @throws SodiumException * @psalm-suppress PossiblyInvalidArgument hash API */ protected static function h2c_string_to_hash_sha512($hLen, $ctx, $msg) { $h = array_fill(0, $hLen, 0); $ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0; if ($hLen > 0xff) { throw new SodiumException('Hash must be less than 256 bytes'); } if ($ctx_len > 0xff) { $st = hash_init('sha256'); self::hash_update($st, "H2C-OVERSIZE-DST-"); self::hash_update($st, $ctx); $ctx = hash_final($st, true); $ctx_len = 32; } $t = array(0, $hLen, 0); $ux = str_repeat("\0", 128); $st = hash_init('sha512'); self::hash_update($st, $ux); self::hash_update($st, $msg); self::hash_update($st, self::intArrayToString($t)); self::hash_update($st, $ctx); self::hash_update($st, self::intToChr($ctx_len)); $u0 = hash_final($st, true); for ($i = 0; $i < $hLen; $i += 128) { $ux = self::xorStrings($ux, $u0); ++$t[2]; $st = hash_init('sha512'); self::hash_update($st, $ux); self::hash_update($st, self::intToChr($t[2])); self::hash_update($st, $ctx); self::hash_update($st, self::intToChr($ctx_len)); $ux = hash_final($st, true); $amount = min($hLen - $i, 128); for ($j = 0; $j < $amount; ++$j) { $h[$i + $j] = self::chrToInt($ux[$i]); } } return self::intArrayToString(array_slice($h, 0, $hLen)); } /** * @param int $hLen * @param ?string $ctx * @param string $msg * @param int $hash_alg * @return string * @throws SodiumException */ public static function h2c_string_to_hash($hLen, $ctx, $msg, $hash_alg) { switch ($hash_alg) { case self::CORE_H2C_SHA256: return self::h2c_string_to_hash_sha256($hLen, $ctx, $msg); case self::CORE_H2C_SHA512: return self::h2c_string_to_hash_sha512($hLen, $ctx, $msg); default: throw new SodiumException('Invalid H2C hash algorithm'); } } /** * @param ?string $ctx * @param string $msg * @param int $hash_alg * @return string * @throws SodiumException */ protected static function _string_to_element($ctx, $msg, $hash_alg) { return self::ristretto255_from_hash( self::h2c_string_to_hash(self::crypto_core_ristretto255_HASHBYTES, $ctx, $msg, $hash_alg) ); } /** * @return string * @throws SodiumException * @throws Exception */ public static function ristretto255_random() { return self::ristretto255_from_hash( ParagonIE_Sodium_Compat::randombytes_buf(self::crypto_core_ristretto255_HASHBYTES) ); } /** * @return string * @throws SodiumException */ public static function ristretto255_scalar_random() { return self::scalar_random(); } /** * @param string $s * @return string * @throws SodiumException */ public static function ristretto255_scalar_complement($s) { return self::scalar_complement($s); } /** * @param string $s * @return string */ public static function ristretto255_scalar_invert($s) { return self::sc25519_invert($s); } /** * @param string $s * @return string * @throws SodiumException */ public static function ristretto255_scalar_negate($s) { return self::scalar_negate($s); } /** * @param string $x * @param string $y * @return string */ public static function ristretto255_scalar_add($x, $y) { return self::scalar_add($x, $y); } /** * @param string $x * @param string $y * @return string */ public static function ristretto255_scalar_sub($x, $y) { return self::scalar_sub($x, $y); } /** * @param string $x * @param string $y * @return string */ public static function ristretto255_scalar_mul($x, $y) { return self::sc25519_mul($x, $y); } /** * @param string $ctx * @param string $msg * @param int $hash_alg * @return string * @throws SodiumException */ public static function ristretto255_scalar_from_string($ctx, $msg, $hash_alg) { $h = array_fill(0, 64, 0); $h_be = self::stringToIntArray( self::h2c_string_to_hash( self::HASH_SC_L, $ctx, $msg, $hash_alg ) ); for ($i = 0; $i < self::HASH_SC_L; ++$i) { $h[$i] = $h_be[self::HASH_SC_L - 1 - $i]; } return self::ristretto255_scalar_reduce(self::intArrayToString($h)); } /** * @param string $s * @return string */ public static function ristretto255_scalar_reduce($s) { return self::sc_reduce($s); } /** * @param string $n * @param string $p * @return string * @throws SodiumException */ public static function scalarmult_ristretto255($n, $p) { if (self::strlen($n) !== 32) { throw new SodiumException('Scalar must be 32 bytes, ' . self::strlen($p) . ' given.'); } if (self::strlen($p) !== 32) { throw new SodiumException('Point must be 32 bytes, ' . self::strlen($p) . ' given.'); } $result = self::ristretto255_frombytes($p); if ($result['res'] !== 0) { throw new SodiumException('Could not multiply points'); } $P = $result['h']; $t = self::stringToIntArray($n); $t[31] &= 0x7f; $Q = self::ge_scalarmult(self::intArrayToString($t), $P); $q = self::ristretto255_p3_tobytes($Q); if (ParagonIE_Sodium_Compat::is_zero($q)) { throw new SodiumException('An unknown error has occurred'); } return $q; } /** * @param string $n * @return string * @throws SodiumException */ public static function scalarmult_ristretto255_base($n) { $t = self::stringToIntArray($n); $t[31] &= 0x7f; $Q = self::ge_scalarmult_base(self::intArrayToString($t)); $q = self::ristretto255_p3_tobytes($Q); if (ParagonIE_Sodium_Compat::is_zero($q)) { throw new SodiumException('An unknown error has occurred'); } return $q; } } PK!e^^Core/BLAKE2b.phpnu[> */ protected 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 SplFixedArray * @psalm-suppress MixedAssignment */ public static function new64($high, $low) { if (PHP_INT_SIZE === 4) { throw new SodiumException("Error, use 32-bit"); } $i64 = new SplFixedArray(2); $i64[0] = $high & 0xffffffff; $i64[1] = $low & 0xffffffff; return $i64; } /** * 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 SplFixedArray */ 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 SplFixedArray $x * @param SplFixedArray $y * @return SplFixedArray * @psalm-suppress MixedArgument * @psalm-suppress MixedAssignment * @psalm-suppress MixedOperand */ protected static function add64($x, $y) { if (PHP_INT_SIZE === 4) { throw new SodiumException("Error, use 32-bit"); } $l = ($x[1] + $y[1]) & 0xffffffff; return self::new64( (int) ($x[0] + $y[0] + ( ($l < $x[1]) ? 1 : 0 )), (int) $l ); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @param SplFixedArray $y * @param SplFixedArray $z * @return SplFixedArray */ protected static function add364($x, $y, $z) { return self::add64($x, self::add64($y, $z)); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @param SplFixedArray $y * @return SplFixedArray * @throws SodiumException * @throws TypeError */ protected static function xor64(SplFixedArray $x, SplFixedArray $y) { if (PHP_INT_SIZE === 4) { throw new SodiumException("Error, use 32-bit"); } if (!is_numeric($x[0])) { throw new SodiumException('x[0] is not an integer'); } if (!is_numeric($x[1])) { throw new SodiumException('x[1] is not an integer'); } if (!is_numeric($y[0])) { throw new SodiumException('y[0] is not an integer'); } if (!is_numeric($y[1])) { throw new SodiumException('y[1] is not an integer'); } return self::new64( (int) (($x[0] ^ $y[0]) & 0xffffffff), (int) (($x[1] ^ $y[1]) & 0xffffffff) ); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @param int $c * @return SplFixedArray * @psalm-suppress MixedAssignment */ public static function rotr64($x, $c) { if (PHP_INT_SIZE === 4) { throw new SodiumException("Error, use 32-bit"); } if ($c >= 64) { $c %= 64; } if ($c >= 32) { /** @var int $tmp */ $tmp = $x[0]; $x[0] = $x[1]; $x[1] = $tmp; $c -= 32; } if ($c === 0) { return $x; } $l0 = 0; $c = 64 - $c; /** @var int $c */ if ($c < 32) { $h0 = ((int) ($x[0]) << $c) | ( ( (int) ($x[1]) & ((1 << $c) - 1) << (32 - $c) ) >> (32 - $c) ); $l0 = (int) ($x[1]) << $c; } else { $h0 = (int) ($x[1]) << ($c - 32); } $h1 = 0; $c1 = 64 - $c; if ($c1 < 32) { $h1 = (int) ($x[0]) >> $c1; $l1 = ((int) ($x[1]) >> $c1) | ((int) ($x[0]) & ((1 << $c1) - 1)) << (32 - $c1); } else { $l1 = (int) ($x[0]) >> ($c1 - 32); } return self::new64($h0 | $h1, $l0 | $l1); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @return int * @psalm-suppress MixedOperand */ protected static function flatten64($x) { return (int) ($x[0] * 4294967296 + $x[1]); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @param int $i * @return SplFixedArray * @psalm-suppress MixedArgument * @psalm-suppress MixedArrayOffset */ protected static function load64(SplFixedArray $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 SplFixedArray $u * @return void * @psalm-suppress MixedAssignment */ protected static function store64(SplFixedArray $x, $i, SplFixedArray $u) { $maxLength = $x->getSize() - 1; for ($j = 0; $j < 8; ++$j) { /* [0, 1, 2, 3, 4, 5, 6, 7] ... becomes ... [0, 0, 0, 0, 1, 1, 1, 1] */ /** @var int $uIdx */ $uIdx = ((7 - $j) & 4) >> 2; $x[$i] = ((int) ($u[$uIdx]) & 0xff); if (++$i > $maxLength) { return; } /** @psalm-suppress MixedOperand */ $u[$uIdx] >>= 8; } } /** * This just sets the $iv static variable. * * @internal You should not use this directly from another application * * @return void */ 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 * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment */ 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 MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedArrayOffset */ 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 * @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 (self::flatten64($ctx[1][0]) < $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 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 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--;) { $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 MixedArrayOffset */ 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 * @throws TypeError */ public static function SplFixedArrayToString(SplFixedArray $a) { /** * @var array $arr */ $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 MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedArrayOffset * @psalm-suppress MixedMethodCall */ public static function contextToString(SplFixedArray $ctx) { $str = ''; /** @var array> $ctxA */ $ctxA = $ctx[0]->toArray(); # uint64_t h[8]; for ($i = 0; $i < 8; ++$i) { $str .= self::store32_le($ctxA[$i][1]); $str .= self::store32_le($ctxA[$i][0]); } # uint64_t t[2]; # uint64_t f[2]; for ($i = 1; $i < 3; ++$i) { $ctxA = $ctx[$i]->toArray(); $str .= self::store32_le($ctxA[0][1]); $str .= self::store32_le($ctxA[0][0]); $str .= self::store32_le($ctxA[1][1]); $str .= self::store32_le($ctxA[1][0]); } # uint8_t buf[2 * 128]; $str .= self::SplFixedArrayToString($ctx[3]); /** @var int $ctx4 */ $ctx4 = (int) $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), 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 MixedArrayAssignment */ public static function stringToContext($string) { $ctx = self::context(); # uint64_t h[8]; for ($i = 0; $i < 8; ++$i) { $ctx[0][$i] = SplFixedArray::fromArray( array( self::load_4( self::substr($string, (($i << 3) + 4), 4) ), self::load_4( self::substr($string, (($i << 3) + 0), 4) ) ) ); } # uint64_t t[2]; # uint64_t f[2]; for ($i = 1; $i < 3; ++$i) { $ctx[$i][1] = SplFixedArray::fromArray( array( self::load_4(self::substr($string, 76 + (($i - 1) << 4), 4)), self::load_4(self::substr($string, 72 + (($i - 1) << 4), 4)) ) ); $ctx[$i][0] = SplFixedArray::fromArray( array( self::load_4(self::substr($string, 68 + (($i - 1) << 4), 4)), self::load_4(self::substr($string, 64 + (($i - 1) << 4), 4)) ) ); } # 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; } } PK!.}}Core/AEGIS/State256.phpnu[ $state */ protected $state; public function __construct() { $this->state = array_fill(0, 6, ''); } /** * @internal Only use this for unit tests! * @return string[] */ public function getState() { return array_values($this->state); } /** * @param array $input * @return self * @throws SodiumException * * @internal Only for unit tests */ public static function initForUnitTests(array $input) { if (count($input) < 6) { throw new SodiumException('invalid input'); } $state = new self(); for ($i = 0; $i < 6; ++$i) { $state->state[$i] = $input[$i]; } return $state; } /** * @param string $key * @param string $nonce * @return self */ public static function init($key, $nonce) { $state = new self(); $k0 = ParagonIE_Sodium_Core_Util::substr($key, 0, 16); $k1 = ParagonIE_Sodium_Core_Util::substr($key, 16, 16); $n0 = ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16); $n1 = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 16); // S0 = k0 ^ n0 // S1 = k1 ^ n1 // S2 = C1 // S3 = C0 // S4 = k0 ^ C0 // S5 = k1 ^ C1 $k0_n0 = $k0 ^ $n0; $k1_n1 = $k1 ^ $n1; $state->state[0] = $k0_n0; $state->state[1] = $k1_n1; $state->state[2] = SODIUM_COMPAT_AEGIS_C1; $state->state[3] = SODIUM_COMPAT_AEGIS_C0; $state->state[4] = $k0 ^ SODIUM_COMPAT_AEGIS_C0; $state->state[5] = $k1 ^ SODIUM_COMPAT_AEGIS_C1; // Repeat(4, // Update(k0) // Update(k1) // Update(k0 ^ n0) // Update(k1 ^ n1) // ) for ($i = 0; $i < 4; ++$i) { $state->update($k0); $state->update($k1); $state->update($k0 ^ $n0); $state->update($k1 ^ $n1); } return $state; } /** * @param string $ai * @return self * @throws SodiumException */ public function absorb($ai) { if (ParagonIE_Sodium_Core_Util::strlen($ai) !== 16) { throw new SodiumException('Input must be an AES block in size'); } return $this->update($ai); } /** * @param string $ci * @return string * @throws SodiumException */ public function dec($ci) { if (ParagonIE_Sodium_Core_Util::strlen($ci) !== 16) { throw new SodiumException('Input must be an AES block in size'); } // z = S1 ^ S4 ^ S5 ^ (S2 & S3) $z = $this->state[1] ^ $this->state[4] ^ $this->state[5] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]); $xi = $ci ^ $z; $this->update($xi); return $xi; } /** * @param string $cn * @return string */ public function decPartial($cn) { $len = ParagonIE_Sodium_Core_Util::strlen($cn); // z = S1 ^ S4 ^ S5 ^ (S2 & S3) $z = $this->state[1] ^ $this->state[4] ^ $this->state[5] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]); // t = ZeroPad(cn, 128) $t = str_pad($cn, 16, "\0", STR_PAD_RIGHT); // out = t ^ z $out = $t ^ $z; // xn = Truncate(out, |cn|) $xn = ParagonIE_Sodium_Core_Util::substr($out, 0, $len); // v = ZeroPad(xn, 128) $v = str_pad($xn, 16, "\0", STR_PAD_RIGHT); // Update(v) $this->update($v); // return xn return $xn; } /** * @param string $xi * @return string * @throws SodiumException */ public function enc($xi) { if (ParagonIE_Sodium_Core_Util::strlen($xi) !== 16) { throw new SodiumException('Input must be an AES block in size'); } // z = S1 ^ S4 ^ S5 ^ (S2 & S3) $z = $this->state[1] ^ $this->state[4] ^ $this->state[5] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]); $this->update($xi); return $xi ^ $z; } /** * @param int $ad_len_bits * @param int $msg_len_bits * @return string */ public function finalize($ad_len_bits, $msg_len_bits) { $encoded = ParagonIE_Sodium_Core_Util::store64_le($ad_len_bits) . ParagonIE_Sodium_Core_Util::store64_le($msg_len_bits); $t = $this->state[3] ^ $encoded; for ($i = 0; $i < 7; ++$i) { $this->update($t); } return ($this->state[0] ^ $this->state[1] ^ $this->state[2]) . ($this->state[3] ^ $this->state[4] ^ $this->state[5]); } /** * @param string $m * @return self */ public function update($m) { /* S'0 = AESRound(S5, S0 ^ M) S'1 = AESRound(S0, S1) S'2 = AESRound(S1, S2) S'3 = AESRound(S2, S3) S'4 = AESRound(S3, S4) S'5 = AESRound(S4, S5) */ list($s_0, $s_1) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[5],$this->state[0] ^ $m, $this->state[0], $this->state[1] ); list($s_2, $s_3) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[1], $this->state[2], $this->state[2], $this->state[3] ); list($s_4, $s_5) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[3], $this->state[4], $this->state[4], $this->state[5] ); /* S0 = S'0 S1 = S'1 S2 = S'2 S3 = S'3 S4 = S'4 S5 = S'5 */ $this->state[0] = $s_0; $this->state[1] = $s_1; $this->state[2] = $s_2; $this->state[3] = $s_3; $this->state[4] = $s_4; $this->state[5] = $s_5; return $this; } } PK!.]L* * Core/AEGIS/State128L.phpnu[ $state */ protected $state; public function __construct() { $this->state = array_fill(0, 8, ''); } /** * @internal Only use this for unit tests! * @return string[] */ public function getState() { return array_values($this->state); } /** * @param array $input * @return self * @throws SodiumException * * @internal Only for unit tests */ public static function initForUnitTests(array $input) { if (count($input) < 8) { throw new SodiumException('invalid input'); } $state = new self(); for ($i = 0; $i < 8; ++$i) { $state->state[$i] = $input[$i]; } return $state; } /** * @param string $key * @param string $nonce * @return self */ public static function init($key, $nonce) { $state = new self(); // S0 = key ^ nonce $state->state[0] = $key ^ $nonce; // S1 = C1 $state->state[1] = SODIUM_COMPAT_AEGIS_C1; // S2 = C0 $state->state[2] = SODIUM_COMPAT_AEGIS_C0; // S3 = C1 $state->state[3] = SODIUM_COMPAT_AEGIS_C1; // S4 = key ^ nonce $state->state[4] = $key ^ $nonce; // S5 = key ^ C0 $state->state[5] = $key ^ SODIUM_COMPAT_AEGIS_C0; // S6 = key ^ C1 $state->state[6] = $key ^ SODIUM_COMPAT_AEGIS_C1; // S7 = key ^ C0 $state->state[7] = $key ^ SODIUM_COMPAT_AEGIS_C0; // Repeat(10, Update(nonce, key)) for ($i = 0; $i < 10; ++$i) { $state->update($nonce, $key); } return $state; } /** * @param string $ai * @return self */ public function absorb($ai) { if (ParagonIE_Sodium_Core_Util::strlen($ai) !== 32) { throw new SodiumException('Input must be two AES blocks in size'); } $t0 = ParagonIE_Sodium_Core_Util::substr($ai, 0, 16); $t1 = ParagonIE_Sodium_Core_Util::substr($ai, 16, 16); return $this->update($t0, $t1); } /** * @param string $ci * @return string * @throws SodiumException */ public function dec($ci) { if (ParagonIE_Sodium_Core_Util::strlen($ci) !== 32) { throw new SodiumException('Input must be two AES blocks in size'); } // z0 = S6 ^ S1 ^ (S2 & S3) $z0 = $this->state[6] ^ $this->state[1] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]); // z1 = S2 ^ S5 ^ (S6 & S7) $z1 = $this->state[2] ^ $this->state[5] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[6], $this->state[7]); // t0, t1 = Split(xi, 128) $t0 = ParagonIE_Sodium_Core_Util::substr($ci, 0, 16); $t1 = ParagonIE_Sodium_Core_Util::substr($ci, 16, 16); // out0 = t0 ^ z0 // out1 = t1 ^ z1 $out0 = $t0 ^ $z0; $out1 = $t1 ^ $z1; // Update(out0, out1) // xi = out0 || out1 $this->update($out0, $out1); return $out0 . $out1; } /** * @param string $cn * @return string */ public function decPartial($cn) { $len = ParagonIE_Sodium_Core_Util::strlen($cn); // z0 = S6 ^ S1 ^ (S2 & S3) $z0 = $this->state[6] ^ $this->state[1] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]); // z1 = S2 ^ S5 ^ (S6 & S7) $z1 = $this->state[2] ^ $this->state[5] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[6], $this->state[7]); // t0, t1 = Split(ZeroPad(cn, 256), 128) $cn = str_pad($cn, 32, "\0", STR_PAD_RIGHT); $t0 = ParagonIE_Sodium_Core_Util::substr($cn, 0, 16); $t1 = ParagonIE_Sodium_Core_Util::substr($cn, 16, 16); // out0 = t0 ^ z0 // out1 = t1 ^ z1 $out0 = $t0 ^ $z0; $out1 = $t1 ^ $z1; // xn = Truncate(out0 || out1, |cn|) $xn = ParagonIE_Sodium_Core_Util::substr($out0 . $out1, 0, $len); // v0, v1 = Split(ZeroPad(xn, 256), 128) $padded = str_pad($xn, 32, "\0", STR_PAD_RIGHT); $v0 = ParagonIE_Sodium_Core_Util::substr($padded, 0, 16); $v1 = ParagonIE_Sodium_Core_Util::substr($padded, 16, 16); // Update(v0, v1) $this->update($v0, $v1); // return xn return $xn; } /** * @param string $xi * @return string * @throws SodiumException */ public function enc($xi) { if (ParagonIE_Sodium_Core_Util::strlen($xi) !== 32) { throw new SodiumException('Input must be two AES blocks in size'); } // z0 = S6 ^ S1 ^ (S2 & S3) $z0 = $this->state[6] ^ $this->state[1] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]); // z1 = S2 ^ S5 ^ (S6 & S7) $z1 = $this->state[2] ^ $this->state[5] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[6], $this->state[7]); // t0, t1 = Split(xi, 128) $t0 = ParagonIE_Sodium_Core_Util::substr($xi, 0, 16); $t1 = ParagonIE_Sodium_Core_Util::substr($xi, 16, 16); // out0 = t0 ^ z0 // out1 = t1 ^ z1 $out0 = $t0 ^ $z0; $out1 = $t1 ^ $z1; // Update(t0, t1) // ci = out0 || out1 $this->update($t0, $t1); // return ci return $out0 . $out1; } /** * @param int $ad_len_bits * @param int $msg_len_bits * @return string */ public function finalize($ad_len_bits, $msg_len_bits) { $encoded = ParagonIE_Sodium_Core_Util::store64_le($ad_len_bits) . ParagonIE_Sodium_Core_Util::store64_le($msg_len_bits); $t = $this->state[2] ^ $encoded; for ($i = 0; $i < 7; ++$i) { $this->update($t, $t); } return ($this->state[0] ^ $this->state[1] ^ $this->state[2] ^ $this->state[3]) . ($this->state[4] ^ $this->state[5] ^ $this->state[6] ^ $this->state[7]); } /** * @param string $m0 * @param string $m1 * @return self */ public function update($m0, $m1) { /* S'0 = AESRound(S7, S0 ^ M0) S'1 = AESRound(S0, S1) S'2 = AESRound(S1, S2) S'3 = AESRound(S2, S3) S'4 = AESRound(S3, S4 ^ M1) S'5 = AESRound(S4, S5) S'6 = AESRound(S5, S6) S'7 = AESRound(S6, S7) */ list($s_0, $s_1) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[7], $this->state[0] ^ $m0, $this->state[0], $this->state[1] ); list($s_2, $s_3) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[1], $this->state[2], $this->state[2], $this->state[3] ); list($s_4, $s_5) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[3], $this->state[4] ^ $m1, $this->state[4], $this->state[5] ); list($s_6, $s_7) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[5], $this->state[6], $this->state[6], $this->state[7] ); /* S0 = S'0 S1 = S'1 S2 = S'2 S3 = S'3 S4 = S'4 S5 = S'5 S6 = S'6 S7 = S'7 */ $this->state[0] = $s_0; $this->state[1] = $s_1; $this->state[2] = $s_2; $this->state[3] = $s_3; $this->state[4] = $s_4; $this->state[5] = $s_5; $this->state[6] = $s_6; $this->state[7] = $s_7; return $this; } }PK!CDffCore/ChaCha20/Ctx.phpnu[ */ 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 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] = 0x61707865; $this->container[1] = 0x3320646e; $this->container[2] = 0x79622d32; $this->container[3] = 0x6b206574; $this->container[4] = self::load_4(self::substr($key, 0, 4)); $this->container[5] = self::load_4(self::substr($key, 4, 4)); $this->container[6] = self::load_4(self::substr($key, 8, 4)); $this->container[7] = self::load_4(self::substr($key, 12, 4)); $this->container[8] = self::load_4(self::substr($key, 16, 4)); $this->container[9] = self::load_4(self::substr($key, 20, 4)); $this->container[10] = self::load_4(self::substr($key, 24, 4)); $this->container[11] = self::load_4(self::substr($key, 28, 4)); if (empty($counter)) { $this->container[12] = 0; $this->container[13] = 0; } else { $this->container[12] = self::load_4(self::substr($counter, 0, 4)); $this->container[13] = self::load_4(self::substr($counter, 4, 4)); } $this->container[14] = self::load_4(self::substr($iv, 0, 4)); $this->container[15] = self::load_4(self::substr($iv, 4, 4)); } /** * @internal You should not use this directly from another application * * @param int $offset * @param int $value * @return void * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!is_int($offset)) { throw new InvalidArgumentException('Expected an integer'); } if (!is_int($value)) { 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 */ #[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; } } PK!Ә**Core/ChaCha20/IetfCtx.phpnu[container[12] = self::load_4(self::substr($counter, 0, 4)); } $this->container[13] = self::load_4(self::substr($iv, 0, 4)); $this->container[14] = self::load_4(self::substr($iv, 4, 4)); $this->container[15] = self::load_4(self::substr($iv, 8, 4)); } } PK!7ACore/AEGIS256.phpnu[> 4; // for ai in ad_blocks: // Absorb(ai) for ($i = 0; $i < $ad_blocks; ++$i) { $ai = self::substr($ad, $i << 4, 16); if (self::strlen($ai) < 16) { $ai = str_pad($ai, 16, "\0", STR_PAD_RIGHT); } $state->absorb($ai); } $msg = ''; $cn = self::strlen($ct) & 15; $ct_blocks = self::strlen($ct) >> 4; // ct_blocks = Split(ZeroPad(ct, 128), 128) // cn = Tail(ct, |ct| mod 128) for ($i = 0; $i < $ct_blocks; ++$i) { $msg .= $state->dec(self::substr($ct, $i << 4, 16)); } // if cn is not empty: // msg = msg || DecPartial(cn) if ($cn) { $start = $ct_blocks << 4; $msg .= $state->decPartial(self::substr($ct, $start, $cn)); } $expected_tag = $state->finalize( self::strlen($ad) << 3, self::strlen($msg) << 3 ); if (!self::hashEquals($expected_tag, $tag)) { try { // The RFC says to erase msg, so we shall try: ParagonIE_Sodium_Compat::memzero($msg); } catch (SodiumException $ex) { // Do nothing if we cannot memzero } throw new SodiumException('verification failed'); } return $msg; } /** * @param string $msg * @param string $ad * @param string $key * @param string $nonce * @return array * @throws SodiumException */ public static function encrypt($msg, $ad, $key, $nonce) { $state = self::init($key, $nonce); $ad_len = self::strlen($ad); $msg_len = self::strlen($msg); $ad_blocks = ($ad_len + 15) >> 4; for ($i = 0; $i < $ad_blocks; ++$i) { $ai = self::substr($ad, $i << 4, 16); if (self::strlen($ai) < 16) { $ai = str_pad($ai, 16, "\0", STR_PAD_RIGHT); } $state->absorb($ai); } $ct = ''; $msg_blocks = ($msg_len + 15) >> 4; for ($i = 0; $i < $msg_blocks; ++$i) { $xi = self::substr($msg, $i << 4, 16); if (self::strlen($xi) < 16) { $xi = str_pad($xi, 16, "\0", STR_PAD_RIGHT); } $ct .= $state->enc($xi); } $tag = $state->finalize( $ad_len << 3, $msg_len << 3 ); return array( self::substr($ct, 0, $msg_len), $tag ); } /** * @param string $key * @param string $nonce * @return ParagonIE_Sodium_Core_AEGIS_State256 */ public static function init($key, $nonce) { return ParagonIE_Sodium_Core_AEGIS_State256::init($key, $nonce); } } PK!* * Core/XChaCha20.phpnu[> 25; $h[0] += self::mul($carry9, 19, 5); $h[9] -= $carry9 << 25; /** @var int $carry1 */ $carry1 = ($h[1] + (1 << 24)) >> 25; $h[2] += $carry1; $h[1] -= $carry1 << 25; /** @var int $carry3 */ $carry3 = ($h[3] + (1 << 24)) >> 25; $h[4] += $carry3; $h[3] -= $carry3 << 25; /** @var int $carry5 */ $carry5 = ($h[5] + (1 << 24)) >> 25; $h[6] += $carry5; $h[5] -= $carry5 << 25; /** @var int $carry7 */ $carry7 = ($h[7] + (1 << 24)) >> 25; $h[8] += $carry7; $h[7] -= $carry7 << 25; /** @var int $carry0 */ $carry0 = ($h[0] + (1 << 25)) >> 26; $h[1] += $carry0; $h[0] -= $carry0 << 26; /** @var int $carry2 */ $carry2 = ($h[2] + (1 << 25)) >> 26; $h[3] += $carry2; $h[2] -= $carry2 << 26; /** @var int $carry4 */ $carry4 = ($h[4] + (1 << 25)) >> 26; $h[5] += $carry4; $h[4] -= $carry4 << 26; /** @var int $carry6 */ $carry6 = ($h[6] + (1 << 25)) >> 26; $h[7] += $carry6; $h[6] -= $carry6 << 26; /** @var int $carry8 */ $carry8 = ($h[8] + (1 << 25)) >> 26; $h[9] += $carry8; $h[8] -= $carry8 << 26; foreach ($h as $i => $value) { $h[$i] = (int) $value; } return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h); } /** * @internal You should not use this directly from another application * * Inline comments preceded by # are from libsodium's ref10 code. * * @param string $n * @param string $p * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_scalarmult_curve25519_ref10($n, $p) { # for (i = 0;i < 32;++i) e[i] = n[i]; $e = '' . $n; # e[0] &= 248; $e[0] = self::intToChr( self::chrToInt($e[0]) & 248 ); # e[31] &= 127; # e[31] |= 64; $e[31] = self::intToChr( (self::chrToInt($e[31]) & 127) | 64 ); # fe_frombytes(x1,p); $x1 = self::fe_frombytes($p); # fe_1(x2); $x2 = self::fe_1(); # fe_0(z2); $z2 = self::fe_0(); # fe_copy(x3,x1); $x3 = self::fe_copy($x1); # fe_1(z3); $z3 = self::fe_1(); # swap = 0; /** @var int $swap */ $swap = 0; # for (pos = 254;pos >= 0;--pos) { for ($pos = 254; $pos >= 0; --$pos) { # b = e[pos / 8] >> (pos & 7); /** @var int $b */ $b = self::chrToInt( $e[(int) floor($pos / 8)] ) >> ($pos & 7); # b &= 1; $b &= 1; # swap ^= b; $swap ^= $b; # fe_cswap(x2,x3,swap); self::fe_cswap($x2, $x3, $swap); # fe_cswap(z2,z3,swap); self::fe_cswap($z2, $z3, $swap); # swap = b; $swap = $b; # fe_sub(tmp0,x3,z3); $tmp0 = self::fe_sub($x3, $z3); # fe_sub(tmp1,x2,z2); $tmp1 = self::fe_sub($x2, $z2); # fe_add(x2,x2,z2); $x2 = self::fe_add($x2, $z2); # fe_add(z2,x3,z3); $z2 = self::fe_add($x3, $z3); # fe_mul(z3,tmp0,x2); $z3 = self::fe_mul($tmp0, $x2); # fe_mul(z2,z2,tmp1); $z2 = self::fe_mul($z2, $tmp1); # fe_sq(tmp0,tmp1); $tmp0 = self::fe_sq($tmp1); # fe_sq(tmp1,x2); $tmp1 = self::fe_sq($x2); # fe_add(x3,z3,z2); $x3 = self::fe_add($z3, $z2); # fe_sub(z2,z3,z2); $z2 = self::fe_sub($z3, $z2); # fe_mul(x2,tmp1,tmp0); $x2 = self::fe_mul($tmp1, $tmp0); # fe_sub(tmp1,tmp1,tmp0); $tmp1 = self::fe_sub($tmp1, $tmp0); # fe_sq(z2,z2); $z2 = self::fe_sq($z2); # fe_mul121666(z3,tmp1); $z3 = self::fe_mul121666($tmp1); # fe_sq(x3,x3); $x3 = self::fe_sq($x3); # fe_add(tmp0,tmp0,z3); $tmp0 = self::fe_add($tmp0, $z3); # fe_mul(z3,x1,z2); $z3 = self::fe_mul($x1, $z2); # fe_mul(z2,tmp1,tmp0); $z2 = self::fe_mul($tmp1, $tmp0); } # fe_cswap(x2,x3,swap); self::fe_cswap($x2, $x3, $swap); # fe_cswap(z2,z3,swap); self::fe_cswap($z2, $z3, $swap); # fe_invert(z2,z2); $z2 = self::fe_invert($z2); # fe_mul(x2,x2,z2); $x2 = self::fe_mul($x2, $z2); # fe_tobytes(q,x2); return self::fe_tobytes($x2); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $edwardsY * @param ParagonIE_Sodium_Core_Curve25519_Fe $edwardsZ * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function edwards_to_montgomery( ParagonIE_Sodium_Core_Curve25519_Fe $edwardsY, ParagonIE_Sodium_Core_Curve25519_Fe $edwardsZ ) { $tempX = self::fe_add($edwardsZ, $edwardsY); $tempZ = self::fe_sub($edwardsZ, $edwardsY); $tempZ = self::fe_invert($tempZ); return self::fe_mul($tempX, $tempZ); } /** * @internal You should not use this directly from another application * * @param string $n * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_scalarmult_curve25519_ref10_base($n) { # for (i = 0;i < 32;++i) e[i] = n[i]; $e = '' . $n; # e[0] &= 248; $e[0] = self::intToChr( self::chrToInt($e[0]) & 248 ); # e[31] &= 127; # e[31] |= 64; $e[31] = self::intToChr( (self::chrToInt($e[31]) & 127) | 64 ); $A = self::ge_scalarmult_base($e); if ( !($A->Y instanceof ParagonIE_Sodium_Core_Curve25519_Fe) || !($A->Z instanceof ParagonIE_Sodium_Core_Curve25519_Fe) ) { throw new TypeError('Null points encountered'); } $pk = self::edwards_to_montgomery($A->Y, $A->Z); return self::fe_tobytes($pk); } } PK!R>pp Core/Util.phpnu[> $size) & 1); return (int) ( ($integer ^ $negative) + (($negative >> $realSize) & 1) ); } /** * @param string $a * @param string $b * @return string * @throws SodiumException */ public static function andStrings($a, $b) { /* Type checks: */ if (!is_string($a)) { throw new TypeError('Argument 1 must be a string'); } if (!is_string($b)) { throw new TypeError('Argument 2 must be a string'); } $len = self::strlen($a); if (self::strlen($b) !== $len) { throw new SodiumException('Both strings must be of equal length to combine with bitwise AND'); } return $a & $b; } /** * Convert a binary string into a hexadecimal string without cache-timing * leaks * * @internal You should not use this directly from another application * * @param string $binaryString (raw binary) * @return string * @throws TypeError */ public static function bin2hex($binaryString) { /* Type checks: */ if (!is_string($binaryString)) { throw new TypeError('Argument 1 must be a string, ' . gettype($binaryString) . ' given.'); } $hex = ''; $len = self::strlen($binaryString); for ($i = 0; $i < $len; ++$i) { /** @var array $chunk */ $chunk = unpack('C', $binaryString[$i]); /** @var int $c */ $c = $chunk[1] & 0xf; /** @var int $b */ $b = $chunk[1] >> 4; $hex .= pack( 'CC', (87 + $b + ((($b - 10) >> 8) & ~38)), (87 + $c + ((($c - 10) >> 8) & ~38)) ); } return $hex; } /** * Convert a binary string into a hexadecimal string without cache-timing * leaks, returning uppercase letters (as per RFC 4648) * * @internal You should not use this directly from another application * * @param string $bin_string (raw binary) * @return string * @throws TypeError */ public static function bin2hexUpper($bin_string) { $hex = ''; $len = self::strlen($bin_string); for ($i = 0; $i < $len; ++$i) { /** @var array $chunk */ $chunk = unpack('C', $bin_string[$i]); /** * Lower 16 bits * * @var int $c */ $c = $chunk[1] & 0xf; /** * Upper 16 bits * @var int $b */ $b = $chunk[1] >> 4; /** * Use pack() and binary operators to turn the two integers * into hexadecimal characters. We don't use chr() here, because * it uses a lookup table internally and we want to avoid * cache-timing side-channels. */ $hex .= pack( 'CC', (55 + $b + ((($b - 10) >> 8) & ~6)), (55 + $c + ((($c - 10) >> 8) & ~6)) ); } return $hex; } /** * Cache-timing-safe variant of ord() * * @internal You should not use this directly from another application * * @param string $chr * @return int * @throws SodiumException * @throws TypeError */ public static function chrToInt($chr) { /* Type checks: */ if (!is_string($chr)) { throw new TypeError('Argument 1 must be a string, ' . gettype($chr) . ' given.'); } if (self::strlen($chr) !== 1) { throw new SodiumException('chrToInt() expects a string that is exactly 1 character long'); } /** @var array $chunk */ $chunk = unpack('C', $chr); return (int) ($chunk[1]); } /** * Compares two strings. * * @internal You should not use this directly from another application * * @param string $left * @param string $right * @param int $len * @return int * @throws SodiumException * @throws TypeError */ public static function compare($left, $right, $len = null) { $leftLen = self::strlen($left); $rightLen = self::strlen($right); if ($len === null) { $len = max($leftLen, $rightLen); $left = str_pad($left, $len, "\x00", STR_PAD_RIGHT); $right = str_pad($right, $len, "\x00", STR_PAD_RIGHT); } $gt = 0; $eq = 1; $i = $len; while ($i !== 0) { --$i; $gt |= ((self::chrToInt($right[$i]) - self::chrToInt($left[$i])) >> 8) & $eq; $eq &= ((self::chrToInt($right[$i]) ^ self::chrToInt($left[$i])) - 1) >> 8; } return ($gt + $gt + $eq) - 1; } /** * If a variable does not match a given type, throw a TypeError. * * @param mixed $mixedVar * @param string $type * @param int $argumentIndex * @throws TypeError * @throws SodiumException * @return void */ public static function declareScalarType(&$mixedVar = null, $type = 'void', $argumentIndex = 0) { if (func_num_args() === 0) { /* Tautology, by default */ return; } if (func_num_args() === 1) { throw new TypeError('Declared void, but passed a variable'); } $realType = strtolower(gettype($mixedVar)); $type = strtolower($type); switch ($type) { case 'null': if ($mixedVar !== null) { throw new TypeError('Argument ' . $argumentIndex . ' must be null, ' . $realType . ' given.'); } break; case 'integer': case 'int': $allow = array('int', 'integer'); if (!in_array($type, $allow)) { throw new TypeError('Argument ' . $argumentIndex . ' must be an integer, ' . $realType . ' given.'); } $mixedVar = (int) $mixedVar; break; case 'boolean': case 'bool': $allow = array('bool', 'boolean'); if (!in_array($type, $allow)) { throw new TypeError('Argument ' . $argumentIndex . ' must be a boolean, ' . $realType . ' given.'); } $mixedVar = (bool) $mixedVar; break; case 'string': if (!is_string($mixedVar)) { throw new TypeError('Argument ' . $argumentIndex . ' must be a string, ' . $realType . ' given.'); } $mixedVar = (string) $mixedVar; break; case 'decimal': case 'double': case 'float': $allow = array('decimal', 'double', 'float'); if (!in_array($type, $allow)) { throw new TypeError('Argument ' . $argumentIndex . ' must be a float, ' . $realType . ' given.'); } $mixedVar = (float) $mixedVar; break; case 'object': if (!is_object($mixedVar)) { throw new TypeError('Argument ' . $argumentIndex . ' must be an object, ' . $realType . ' given.'); } break; case 'array': if (!is_array($mixedVar)) { if (is_object($mixedVar)) { if ($mixedVar instanceof ArrayAccess) { return; } } throw new TypeError('Argument ' . $argumentIndex . ' must be an array, ' . $realType . ' given.'); } break; default: throw new SodiumException('Unknown type (' . $realType .') does not match expect type (' . $type . ')'); } } /** * Evaluate whether or not two strings are equal (in constant-time) * * @param string $left * @param string $right * @return bool * @throws SodiumException * @throws TypeError */ public static function hashEquals($left, $right) { /* Type checks: */ if (!is_string($left)) { throw new TypeError('Argument 1 must be a string, ' . gettype($left) . ' given.'); } if (!is_string($right)) { throw new TypeError('Argument 2 must be a string, ' . gettype($right) . ' given.'); } if (is_callable('hash_equals')) { return hash_equals($left, $right); } $d = 0; /** @var int $len */ $len = self::strlen($left); if ($len !== self::strlen($right)) { return false; } for ($i = 0; $i < $len; ++$i) { $d |= self::chrToInt($left[$i]) ^ self::chrToInt($right[$i]); } if ($d !== 0) { return false; } return $left === $right; } /** * Catch hash_update() failures and throw instead of silently proceeding * * @param HashContext|resource &$hs * @param string $data * @return void * @throws SodiumException * @psalm-suppress PossiblyInvalidArgument */ protected static function hash_update(&$hs, $data) { if (!hash_update($hs, $data)) { throw new SodiumException('hash_update() failed'); } } /** * Convert a hexadecimal string into a binary string without cache-timing * leaks * * @internal You should not use this directly from another application * * @param string $hexString * @param string $ignore * @param bool $strictPadding * @return string (raw binary) * @throws RangeException * @throws TypeError */ public static function hex2bin($hexString, $ignore = '', $strictPadding = false) { /* Type checks: */ if (!is_string($hexString)) { throw new TypeError('Argument 1 must be a string, ' . gettype($hexString) . ' given.'); } if (!is_string($ignore)) { throw new TypeError('Argument 2 must be a string, ' . gettype($hexString) . ' given.'); } $hex_pos = 0; $bin = ''; $c_acc = 0; $hex_len = self::strlen($hexString); $state = 0; if (($hex_len & 1) !== 0) { if ($strictPadding) { throw new RangeException( 'Expected an even number of hexadecimal characters' ); } else { $hexString = '0' . $hexString; ++$hex_len; } } $chunk = unpack('C*', $hexString); while ($hex_pos < $hex_len) { ++$hex_pos; /** @var int $c */ $c = $chunk[$hex_pos]; $c_num = $c ^ 48; $c_num0 = ($c_num - 10) >> 8; $c_alpha = ($c & ~32) - 55; $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8; if (($c_num0 | $c_alpha0) === 0) { if ($ignore && $state === 0 && strpos($ignore, self::intToChr($c)) !== false) { continue; } throw new RangeException( 'hex2bin() only expects hexadecimal characters' ); } $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0); if ($state === 0) { $c_acc = $c_val * 16; } else { $bin .= pack('C', $c_acc | $c_val); } $state ^= 1; } return $bin; } /** * Turn an array of integers into a string * * @internal You should not use this directly from another application * * @param array $ints * @return string */ public static function intArrayToString(array $ints) { $args = $ints; foreach ($args as $i => $v) { $args[$i] = (int) ($v & 0xff); } array_unshift($args, str_repeat('C', count($ints))); return (string) (call_user_func_array('pack', $args)); } /** * Cache-timing-safe variant of ord() * * @internal You should not use this directly from another application * * @param int $int * @return string * @throws TypeError */ public static function intToChr($int) { return pack('C', $int); } /** * Load a 3 character substring into an integer * * @internal You should not use this directly from another application * * @param string $string * @return int * @throws RangeException * @throws TypeError */ public static function load_3($string) { /* Type checks: */ if (!is_string($string)) { throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.'); } /* Input validation: */ if (self::strlen($string) < 3) { throw new RangeException( 'String must be 3 bytes or more; ' . self::strlen($string) . ' given.' ); } /** @var array $unpacked */ $unpacked = unpack('V', $string . "\0"); return (int) ($unpacked[1] & 0xffffff); } /** * Load a 4 character substring into an integer * * @internal You should not use this directly from another application * * @param string $string * @return int * @throws RangeException * @throws TypeError */ public static function load_4($string) { /* Type checks: */ if (!is_string($string)) { throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.'); } /* Input validation: */ if (self::strlen($string) < 4) { throw new RangeException( 'String must be 4 bytes or more; ' . self::strlen($string) . ' given.' ); } /** @var array $unpacked */ $unpacked = unpack('V', $string); return (int) $unpacked[1]; } /** * Load a 8 character substring into an integer * * @internal You should not use this directly from another application * * @param string $string * @return int * @throws RangeException * @throws SodiumException * @throws TypeError */ public static function load64_le($string) { /* Type checks: */ if (!is_string($string)) { throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.'); } /* Input validation: */ if (self::strlen($string) < 4) { throw new RangeException( 'String must be 4 bytes or more; ' . self::strlen($string) . ' given.' ); } if (PHP_VERSION_ID >= 50603 && PHP_INT_SIZE === 8) { /** @var array $unpacked */ $unpacked = unpack('P', $string); return (int) $unpacked[1]; } /** @var int $result */ $result = (self::chrToInt($string[0]) & 0xff); $result |= (self::chrToInt($string[1]) & 0xff) << 8; $result |= (self::chrToInt($string[2]) & 0xff) << 16; $result |= (self::chrToInt($string[3]) & 0xff) << 24; $result |= (self::chrToInt($string[4]) & 0xff) << 32; $result |= (self::chrToInt($string[5]) & 0xff) << 40; $result |= (self::chrToInt($string[6]) & 0xff) << 48; $result |= (self::chrToInt($string[7]) & 0xff) << 56; return (int) $result; } /** * @internal You should not use this directly from another application * * @param string $left * @param string $right * @return int * @throws SodiumException * @throws TypeError */ public static function memcmp($left, $right) { if (self::hashEquals($left, $right)) { return 0; } return -1; } /** * Multiply two integers in constant-time * * Micro-architecture timing side-channels caused by how your CPU * implements multiplication are best prevented by never using the * multiplication operators and ensuring that our code always takes * the same number of operations to complete, regardless of the values * of $a and $b. * * @internal You should not use this directly from another application * * @param int $a * @param int $b * @param int $size Limits the number of operations (useful for small, * constant operands) * @return int */ public static function mul($a, $b, $size = 0) { if (ParagonIE_Sodium_Compat::$fastMult) { return (int) ($a * $b); } static $defaultSize = null; /** @var int $defaultSize */ if (!$defaultSize) { /** @var int $defaultSize */ $defaultSize = (PHP_INT_SIZE << 3) - 1; } if ($size < 1) { /** @var int $size */ $size = $defaultSize; } /** @var int $size */ $c = 0; /** * Mask is either -1 or 0. * * -1 in binary looks like 0x1111 ... 1111 * 0 in binary looks like 0x0000 ... 0000 * * @var int */ $mask = -(($b >> ((int) $defaultSize)) & 1); /** * Ensure $b is a positive integer, without creating * a branching side-channel * * @var int $b */ $b = ($b & ~$mask) | ($mask & -$b); /** * Unless $size is provided: * * This loop always runs 32 times when PHP_INT_SIZE is 4. * This loop always runs 64 times when PHP_INT_SIZE is 8. */ for ($i = $size; $i >= 0; --$i) { $c += (int) ($a & -($b & 1)); $a <<= 1; $b >>= 1; } $c = (int) @($c & -1); /** * If $b was negative, we then apply the same value to $c here. * It doesn't matter much if $a was negative; the $c += above would * have produced a negative integer to begin with. But a negative $b * makes $b >>= 1 never return 0, so we would end up with incorrect * results. * * The end result is what we'd expect from integer multiplication. */ return (int) (($c & ~$mask) | ($mask & -$c)); } /** * Convert any arbitrary numbers into two 32-bit integers that represent * a 64-bit integer. * * @internal You should not use this directly from another application * * @param int|float $num * @return array */ public static function numericTo64BitInteger($num) { $high = 0; /** @var int $low */ if (PHP_INT_SIZE === 4) { $low = (int) $num; } else { $low = $num & 0xffffffff; } if ((+(abs($num))) >= 1) { if ($num > 0) { /** @var int $high */ $high = min((+(floor($num/4294967296))), 4294967295); } else { /** @var int $high */ $high = ~~((+(ceil(($num - (+((~~($num)))))/4294967296)))); } } return array((int) $high, (int) $low); } /** * Store a 24-bit integer into a string, treating it as big-endian. * * @internal You should not use this directly from another application * * @param int $int * @return string * @throws TypeError */ public static function store_3($int) { /* Type checks: */ if (!is_int($int)) { if (is_numeric($int)) { $int = (int) $int; } else { throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); } } /** @var string $packed */ $packed = pack('N', $int); return self::substr($packed, 1, 3); } /** * Store a 32-bit integer into a string, treating it as little-endian. * * @internal You should not use this directly from another application * * @param int $int * @return string * @throws TypeError */ public static function store32_le($int) { /* Type checks: */ if (!is_int($int)) { if (is_numeric($int)) { $int = (int) $int; } else { throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); } } /** @var string $packed */ $packed = pack('V', $int); return $packed; } /** * Store a 32-bit integer into a string, treating it as big-endian. * * @internal You should not use this directly from another application * * @param int $int * @return string * @throws TypeError */ public static function store_4($int) { /* Type checks: */ if (!is_int($int)) { if (is_numeric($int)) { $int = (int) $int; } else { throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); } } /** @var string $packed */ $packed = pack('N', $int); return $packed; } /** * Stores a 64-bit integer as an string, treating it as little-endian. * * @internal You should not use this directly from another application * * @param int $int * @return string * @throws TypeError */ public static function store64_le($int) { /* Type checks: */ if (!is_int($int)) { if (is_numeric($int)) { $int = (int) $int; } else { throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); } } if (PHP_INT_SIZE === 8) { if (PHP_VERSION_ID >= 50603) { /** @var string $packed */ $packed = pack('P', $int); return $packed; } return self::intToChr($int & 0xff) . self::intToChr(($int >> 8) & 0xff) . self::intToChr(($int >> 16) & 0xff) . self::intToChr(($int >> 24) & 0xff) . self::intToChr(($int >> 32) & 0xff) . self::intToChr(($int >> 40) & 0xff) . self::intToChr(($int >> 48) & 0xff) . self::intToChr(($int >> 56) & 0xff); } if ($int > PHP_INT_MAX) { list($hiB, $int) = self::numericTo64BitInteger($int); } else { $hiB = 0; } return self::intToChr(($int ) & 0xff) . self::intToChr(($int >> 8) & 0xff) . self::intToChr(($int >> 16) & 0xff) . self::intToChr(($int >> 24) & 0xff) . self::intToChr($hiB & 0xff) . self::intToChr(($hiB >> 8) & 0xff) . self::intToChr(($hiB >> 16) & 0xff) . self::intToChr(($hiB >> 24) & 0xff); } /** * Safe string length * * @internal You should not use this directly from another application * * @ref mbstring.func_overload * * @param string $str * @return int * @throws TypeError */ public static function strlen($str) { /* Type checks: */ if (!is_string($str)) { throw new TypeError('String expected'); } return (int) ( self::isMbStringOverride() ? mb_strlen($str, '8bit') : strlen($str) ); } /** * Turn a string into an array of integers * * @internal You should not use this directly from another application * * @param string $string * @return array * @throws TypeError */ public static function stringToIntArray($string) { if (!is_string($string)) { throw new TypeError('String expected'); } /** * @var array */ $values = array_values( unpack('C*', $string) ); return $values; } /** * Safe substring * * @internal You should not use this directly from another application * * @ref mbstring.func_overload * * @param string $str * @param int $start * @param int $length * @return string * @throws TypeError */ public static function substr($str, $start = 0, $length = null) { /* Type checks: */ if (!is_string($str)) { throw new TypeError('String expected'); } if ($length === 0) { return ''; } if (self::isMbStringOverride()) { if (PHP_VERSION_ID < 50400 && $length === null) { $length = self::strlen($str); } $sub = (string) mb_substr($str, $start, $length, '8bit'); } elseif ($length === null) { $sub = (string) substr($str, $start); } else { $sub = (string) substr($str, $start, $length); } if ($sub !== '') { return $sub; } return ''; } /** * Compare a 16-character byte string in constant time. * * @internal You should not use this directly from another application * * @param string $a * @param string $b * @return bool * @throws SodiumException * @throws TypeError */ public static function verify_16($a, $b) { /* Type checks: */ if (!is_string($a)) { throw new TypeError('String expected'); } if (!is_string($b)) { throw new TypeError('String expected'); } return self::hashEquals( self::substr($a, 0, 16), self::substr($b, 0, 16) ); } /** * Compare a 32-character byte string in constant time. * * @internal You should not use this directly from another application * * @param string $a * @param string $b * @return bool * @throws SodiumException * @throws TypeError */ public static function verify_32($a, $b) { /* Type checks: */ if (!is_string($a)) { throw new TypeError('String expected'); } if (!is_string($b)) { throw new TypeError('String expected'); } return self::hashEquals( self::substr($a, 0, 32), self::substr($b, 0, 32) ); } /** * Calculate $a ^ $b for two strings. * * @internal You should not use this directly from another application * * @param string $a * @param string $b * @return string * @throws TypeError */ public static function xorStrings($a, $b) { /* Type checks: */ if (!is_string($a)) { throw new TypeError('Argument 1 must be a string'); } if (!is_string($b)) { throw new TypeError('Argument 2 must be a string'); } return (string) ($a ^ $b); } /** * Returns whether or not mbstring.func_overload is in effect. * * @internal You should not use this directly from another application * * Note: MB_OVERLOAD_STRING === 2, but we don't reference the constant * (for nuisance-free PHP 8 support) * * @return bool */ protected static function isMbStringOverride() { static $mbstring = null; if ($mbstring === null) { if (!defined('MB_OVERLOAD_STRING')) { $mbstring = false; return $mbstring; } $mbstring = extension_loaded('mbstring') && defined('MB_OVERLOAD_STRING') && ((int) (ini_get('mbstring.func_overload')) & 2); // MB_OVERLOAD_STRING === 2 } /** @var bool $mbstring */ return $mbstring; } } PK!z-y9TTCore/AEGIS128L.phpnu[> 5; for ($i = 0; $i < $ad_blocks; ++$i) { $ai = self::substr($ad, $i << 5, 32); if (self::strlen($ai) < 32) { $ai = str_pad($ai, 32, "\0", STR_PAD_RIGHT); } $state->absorb($ai); } $msg = ''; $cn = self::strlen($ct) & 31; $ct_blocks = self::strlen($ct) >> 5; for ($i = 0; $i < $ct_blocks; ++$i) { $msg .= $state->dec(self::substr($ct, $i << 5, 32)); } if ($cn) { $start = $ct_blocks << 5; $msg .= $state->decPartial(self::substr($ct, $start, $cn)); } $expected_tag = $state->finalize( self::strlen($ad) << 3, self::strlen($msg) << 3 ); if (!self::hashEquals($expected_tag, $tag)) { try { // The RFC says to erase msg, so we shall try: ParagonIE_Sodium_Compat::memzero($msg); } catch (SodiumException $ex) { // Do nothing if we cannot memzero } throw new SodiumException('verification failed'); } return $msg; } /** * @param string $msg * @param string $ad * @param string $key * @param string $nonce * @return array * * @throws SodiumException */ public static function encrypt($msg, $ad, $key, $nonce) { $state = self::init($key, $nonce); // ad_blocks = Split(ZeroPad(ad, 256), 256) // for ai in ad_blocks: // Absorb(ai) $ad_len = self::strlen($ad); $msg_len = self::strlen($msg); $ad_blocks = ($ad_len + 31) >> 5; for ($i = 0; $i < $ad_blocks; ++$i) { $ai = self::substr($ad, $i << 5, 32); if (self::strlen($ai) < 32) { $ai = str_pad($ai, 32, "\0", STR_PAD_RIGHT); } $state->absorb($ai); } // msg_blocks = Split(ZeroPad(msg, 256), 256) // for xi in msg_blocks: // ct = ct || Enc(xi) $ct = ''; $msg_blocks = ($msg_len + 31) >> 5; for ($i = 0; $i < $msg_blocks; ++$i) { $xi = self::substr($msg, $i << 5, 32); if (self::strlen($xi) < 32) { $xi = str_pad($xi, 32, "\0", STR_PAD_RIGHT); } $ct .= $state->enc($xi); } // tag = Finalize(|ad|, |msg|) // ct = Truncate(ct, |msg|) $tag = $state->finalize( $ad_len << 3, $msg_len << 3 ); // return ct and tag return array( self::substr($ct, 0, $msg_len), $tag ); } /** * @param string $key * @param string $nonce * @return ParagonIE_Sodium_Core_AEGIS_State128L */ public static function init($key, $nonce) { return ParagonIE_Sodium_Core_AEGIS_State128L::init($key, $nonce); } } PK!I22Core/ChaCha20.phpnu[> (32 - $n)) ) ); } /** * The ChaCha20 quarter round function. Works on four 32-bit integers. * * @internal You should not use this directly from another application * * @param int $a * @param int $b * @param int $c * @param int $d * @return array */ protected static function quarterRound($a, $b, $c, $d) { # a = PLUS(a,b); d = ROTATE(XOR(d,a),16); /** @var int $a */ $a = ($a + $b) & 0xffffffff; $d = self::rotate($d ^ $a, 16); # c = PLUS(c,d); b = ROTATE(XOR(b,c),12); /** @var int $c */ $c = ($c + $d) & 0xffffffff; $b = self::rotate($b ^ $c, 12); # a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); /** @var int $a */ $a = ($a + $b) & 0xffffffff; $d = self::rotate($d ^ $a, 8); # c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); /** @var int $c */ $c = ($c + $d) & 0xffffffff; $b = self::rotate($b ^ $c, 7); return array((int) $a, (int) $b, (int) $c, (int) $d); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_ChaCha20_Ctx $ctx * @param string $message * * @return string * @throws TypeError * @throws SodiumException */ public static function encryptBytes( ParagonIE_Sodium_Core_ChaCha20_Ctx $ctx, $message = '' ) { $bytes = self::strlen($message); /* j0 = ctx->input[0]; j1 = ctx->input[1]; j2 = ctx->input[2]; j3 = ctx->input[3]; j4 = ctx->input[4]; j5 = ctx->input[5]; j6 = ctx->input[6]; j7 = ctx->input[7]; j8 = ctx->input[8]; j9 = ctx->input[9]; j10 = ctx->input[10]; j11 = ctx->input[11]; j12 = ctx->input[12]; j13 = ctx->input[13]; j14 = ctx->input[14]; j15 = ctx->input[15]; */ $j0 = (int) $ctx[0]; $j1 = (int) $ctx[1]; $j2 = (int) $ctx[2]; $j3 = (int) $ctx[3]; $j4 = (int) $ctx[4]; $j5 = (int) $ctx[5]; $j6 = (int) $ctx[6]; $j7 = (int) $ctx[7]; $j8 = (int) $ctx[8]; $j9 = (int) $ctx[9]; $j10 = (int) $ctx[10]; $j11 = (int) $ctx[11]; $j12 = (int) $ctx[12]; $j13 = (int) $ctx[13]; $j14 = (int) $ctx[14]; $j15 = (int) $ctx[15]; $c = ''; for (;;) { if ($bytes < 64) { $message .= str_repeat("\x00", 64 - $bytes); } $x0 = (int) $j0; $x1 = (int) $j1; $x2 = (int) $j2; $x3 = (int) $j3; $x4 = (int) $j4; $x5 = (int) $j5; $x6 = (int) $j6; $x7 = (int) $j7; $x8 = (int) $j8; $x9 = (int) $j9; $x10 = (int) $j10; $x11 = (int) $j11; $x12 = (int) $j12; $x13 = (int) $j13; $x14 = (int) $j14; $x15 = (int) $j15; # for (i = 20; i > 0; i -= 2) { for ($i = 20; $i > 0; $i -= 2) { # 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); } /* x0 = PLUS(x0, j0); x1 = PLUS(x1, j1); x2 = PLUS(x2, j2); x3 = PLUS(x3, j3); x4 = PLUS(x4, j4); x5 = PLUS(x5, j5); x6 = PLUS(x6, j6); x7 = PLUS(x7, j7); x8 = PLUS(x8, j8); x9 = PLUS(x9, j9); x10 = PLUS(x10, j10); x11 = PLUS(x11, j11); x12 = PLUS(x12, j12); x13 = PLUS(x13, j13); x14 = PLUS(x14, j14); x15 = PLUS(x15, j15); */ /** @var int $x0 */ $x0 = ($x0 & 0xffffffff) + $j0; /** @var int $x1 */ $x1 = ($x1 & 0xffffffff) + $j1; /** @var int $x2 */ $x2 = ($x2 & 0xffffffff) + $j2; /** @var int $x3 */ $x3 = ($x3 & 0xffffffff) + $j3; /** @var int $x4 */ $x4 = ($x4 & 0xffffffff) + $j4; /** @var int $x5 */ $x5 = ($x5 & 0xffffffff) + $j5; /** @var int $x6 */ $x6 = ($x6 & 0xffffffff) + $j6; /** @var int $x7 */ $x7 = ($x7 & 0xffffffff) + $j7; /** @var int $x8 */ $x8 = ($x8 & 0xffffffff) + $j8; /** @var int $x9 */ $x9 = ($x9 & 0xffffffff) + $j9; /** @var int $x10 */ $x10 = ($x10 & 0xffffffff) + $j10; /** @var int $x11 */ $x11 = ($x11 & 0xffffffff) + $j11; /** @var int $x12 */ $x12 = ($x12 & 0xffffffff) + $j12; /** @var int $x13 */ $x13 = ($x13 & 0xffffffff) + $j13; /** @var int $x14 */ $x14 = ($x14 & 0xffffffff) + $j14; /** @var int $x15 */ $x15 = ($x15 & 0xffffffff) + $j15; /* x0 = XOR(x0, LOAD32_LE(m + 0)); x1 = XOR(x1, LOAD32_LE(m + 4)); x2 = XOR(x2, LOAD32_LE(m + 8)); x3 = XOR(x3, LOAD32_LE(m + 12)); x4 = XOR(x4, LOAD32_LE(m + 16)); x5 = XOR(x5, LOAD32_LE(m + 20)); x6 = XOR(x6, LOAD32_LE(m + 24)); x7 = XOR(x7, LOAD32_LE(m + 28)); x8 = XOR(x8, LOAD32_LE(m + 32)); x9 = XOR(x9, LOAD32_LE(m + 36)); x10 = XOR(x10, LOAD32_LE(m + 40)); x11 = XOR(x11, LOAD32_LE(m + 44)); x12 = XOR(x12, LOAD32_LE(m + 48)); x13 = XOR(x13, LOAD32_LE(m + 52)); x14 = XOR(x14, LOAD32_LE(m + 56)); x15 = XOR(x15, LOAD32_LE(m + 60)); */ $x0 ^= self::load_4(self::substr($message, 0, 4)); $x1 ^= self::load_4(self::substr($message, 4, 4)); $x2 ^= self::load_4(self::substr($message, 8, 4)); $x3 ^= self::load_4(self::substr($message, 12, 4)); $x4 ^= self::load_4(self::substr($message, 16, 4)); $x5 ^= self::load_4(self::substr($message, 20, 4)); $x6 ^= self::load_4(self::substr($message, 24, 4)); $x7 ^= self::load_4(self::substr($message, 28, 4)); $x8 ^= self::load_4(self::substr($message, 32, 4)); $x9 ^= self::load_4(self::substr($message, 36, 4)); $x10 ^= self::load_4(self::substr($message, 40, 4)); $x11 ^= self::load_4(self::substr($message, 44, 4)); $x12 ^= self::load_4(self::substr($message, 48, 4)); $x13 ^= self::load_4(self::substr($message, 52, 4)); $x14 ^= self::load_4(self::substr($message, 56, 4)); $x15 ^= self::load_4(self::substr($message, 60, 4)); /* j12 = PLUSONE(j12); if (!j12) { j13 = PLUSONE(j13); } */ ++$j12; if ($j12 & 0xf0000000) { throw new SodiumException('Overflow'); } /* STORE32_LE(c + 0, x0); STORE32_LE(c + 4, x1); STORE32_LE(c + 8, x2); STORE32_LE(c + 12, x3); STORE32_LE(c + 16, x4); STORE32_LE(c + 20, x5); STORE32_LE(c + 24, x6); STORE32_LE(c + 28, x7); STORE32_LE(c + 32, x8); STORE32_LE(c + 36, x9); STORE32_LE(c + 40, x10); STORE32_LE(c + 44, x11); STORE32_LE(c + 48, x12); STORE32_LE(c + 52, x13); STORE32_LE(c + 56, x14); STORE32_LE(c + 60, x15); */ $block = self::store32_le((int) ($x0 & 0xffffffff)) . self::store32_le((int) ($x1 & 0xffffffff)) . self::store32_le((int) ($x2 & 0xffffffff)) . self::store32_le((int) ($x3 & 0xffffffff)) . self::store32_le((int) ($x4 & 0xffffffff)) . self::store32_le((int) ($x5 & 0xffffffff)) . self::store32_le((int) ($x6 & 0xffffffff)) . self::store32_le((int) ($x7 & 0xffffffff)) . self::store32_le((int) ($x8 & 0xffffffff)) . self::store32_le((int) ($x9 & 0xffffffff)) . self::store32_le((int) ($x10 & 0xffffffff)) . self::store32_le((int) ($x11 & 0xffffffff)) . self::store32_le((int) ($x12 & 0xffffffff)) . self::store32_le((int) ($x13 & 0xffffffff)) . self::store32_le((int) ($x14 & 0xffffffff)) . self::store32_le((int) ($x15 & 0xffffffff)); /* Partial block */ if ($bytes < 64) { $c .= self::substr($block, 0, $bytes); break; } /* Full block */ $c .= $block; $bytes -= 64; if ($bytes <= 0) { break; } $message = self::substr($message, 64); } /* end for(;;) loop */ $ctx[12] = $j12; $ctx[13] = $j13; return $c; } /** * @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 = '') { return self::encryptBytes( new ParagonIE_Sodium_Core_ChaCha20_Ctx($key, $nonce), str_repeat("\x00", $len) ); } /** * @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 ietfStream($len, $nonce = '', $key = '') { return self::encryptBytes( new ParagonIE_Sodium_Core_ChaCha20_IetfCtx($key, $nonce), 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 ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '') { return self::encryptBytes( new ParagonIE_Sodium_Core_ChaCha20_IetfCtx($key, $nonce, $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 streamXorIc($message, $nonce = '', $key = '', $ic = '') { return self::encryptBytes( new ParagonIE_Sodium_Core_ChaCha20_Ctx($key, $nonce, $ic), $message ); } } PK!ٷ;;File.phpnu[ ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES_MAX) { throw new TypeError('Argument 2 must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes'); } } if ($outputLength < ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES_MIN) { throw new SodiumException('Argument 3 must be at least CRYPTO_GENERICHASH_BYTES_MIN'); } if ($outputLength > ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES_MAX) { throw new SodiumException('Argument 3 must be at least CRYPTO_GENERICHASH_BYTES_MAX'); } /** @var int $size */ $size = filesize($filePath); if (!is_int($size)) { throw new SodiumException('Could not obtain the file size'); } /** @var resource $fp */ $fp = fopen($filePath, 'rb'); if (!is_resource($fp)) { throw new SodiumException('Could not open input file for reading'); } $ctx = ParagonIE_Sodium_Compat::crypto_generichash_init($key, $outputLength); while ($size > 0) { $blockSize = $size > 64 ? 64 : $size; $read = fread($fp, $blockSize); if (!is_string($read)) { throw new SodiumException('Could not read input file'); } ParagonIE_Sodium_Compat::crypto_generichash_update($ctx, $read); $size -= $blockSize; } fclose($fp); return ParagonIE_Sodium_Compat::crypto_generichash_final($ctx, $outputLength); } /** * Encrypt a file (rather than a string). Uses less memory than * ParagonIE_Sodium_Compat::crypto_secretbox(), but produces * the same result. * * @param string $inputFile Absolute path to a file on the filesystem * @param string $outputFile Absolute path to a file on the filesystem * @param string $nonce Number to be used only once * @param string $key Encryption key * * @return bool * @throws SodiumException * @throws TypeError */ public static function secretbox( $inputFile, $outputFile, $nonce, #[\SensitiveParameter] $key ) { /* Type checks: */ if (!is_string($inputFile)) { throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given..'); } if (!is_string($outputFile)) { throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.'); } if (!is_string($nonce)) { throw new TypeError('Argument 3 must be a string, ' . gettype($nonce) . ' given.'); } /* Input validation: */ if (self::strlen($nonce) !== ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES) { throw new TypeError('Argument 3 must be CRYPTO_SECRETBOX_NONCEBYTES bytes'); } if (!is_string($key)) { throw new TypeError('Argument 4 must be a string, ' . gettype($key) . ' given.'); } if (self::strlen($key) !== ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_KEYBYTES) { throw new TypeError('Argument 4 must be CRYPTO_SECRETBOX_KEYBYTES bytes'); } /** @var int $size */ $size = filesize($inputFile); if (!is_int($size)) { throw new SodiumException('Could not obtain the file size'); } /** @var resource $ifp */ $ifp = fopen($inputFile, 'rb'); if (!is_resource($ifp)) { throw new SodiumException('Could not open input file for reading'); } /** @var resource $ofp */ $ofp = fopen($outputFile, 'wb'); if (!is_resource($ofp)) { fclose($ifp); throw new SodiumException('Could not open output file for writing'); } $res = self::secretbox_encrypt($ifp, $ofp, $size, $nonce, $key); fclose($ifp); fclose($ofp); return $res; } /** * Seal a file (rather than a string). Uses less memory than * ParagonIE_Sodium_Compat::crypto_secretbox_open(), but produces * the same result. * * Warning: Does not protect against TOCTOU attacks. You should * just load the file into memory and use crypto_secretbox_open() if * you are worried about those. * * @param string $inputFile * @param string $outputFile * @param string $nonce * @param string $key * @return bool * @throws SodiumException * @throws TypeError */ public static function secretbox_open( $inputFile, $outputFile, $nonce, #[\SensitiveParameter] $key ) { /* Type checks: */ if (!is_string($inputFile)) { throw new TypeError('Argument 1 must be a string, ' . gettype($inputFile) . ' given.'); } if (!is_string($outputFile)) { throw new TypeError('Argument 2 must be a string, ' . gettype($outputFile) . ' given.'); } if (!is_string($nonce)) { throw new TypeError('Argument 3 must be a string, ' . gettype($nonce) . ' given.'); } if (!is_string($key)) { throw new TypeError('Argument 4 must be a string, ' . gettype($key) . ' given.'); } /* Input validation: */ if (self::strlen($nonce) !== ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES) { throw new TypeError('Argument 4 must be CRYPTO_SECRETBOX_NONCEBYTES bytes'); } if (self::strlen($key) !== ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_KEYBYTES) { throw new TypeError('Argument 4 must be CRYPTO_SECRETBOXBOX_KEYBYTES bytes'); } /** @var int $size */ $size = filesize($inputFile); if (!is_int($size)) { throw new SodiumException('Could not obtain the file size'); } /** @var resource $ifp */ $ifp = fopen($inputFile, 'rb'); if (!is_resource($ifp)) { throw new SodiumException('Could not open input file for reading'); } /** @var resource $ofp */ $ofp = fopen($outputFile, 'wb'); if (!is_resource($ofp)) { fclose($ifp); throw new SodiumException('Could not open output file for writing'); } $res = self::secretbox_decrypt($ifp, $ofp, $size, $nonce, $key); fclose($ifp); fclose($ofp); try { ParagonIE_Sodium_Compat::memzero($key); } catch (SodiumException $ex) { /** @psalm-suppress PossiblyUndefinedVariable */ unset($key); } return $res; } /** * Sign a file (rather than a string). Uses less memory than * ParagonIE_Sodium_Compat::crypto_sign_detached(), but produces * the same result. * * @param string $filePath Absolute path to a file on the filesystem * @param string $secretKey Secret signing key * * @return string Ed25519 signature * @throws SodiumException * @throws TypeError */ public static function sign( $filePath, #[\SensitiveParameter] $secretKey ) { /* Type checks: */ if (!is_string($filePath)) { throw new TypeError('Argument 1 must be a string, ' . gettype($filePath) . ' given.'); } if (!is_string($secretKey)) { throw new TypeError('Argument 2 must be a string, ' . gettype($secretKey) . ' given.'); } /* Input validation: */ if (self::strlen($secretKey) !== ParagonIE_Sodium_Compat::CRYPTO_SIGN_SECRETKEYBYTES) { throw new TypeError('Argument 2 must be CRYPTO_SIGN_SECRETKEYBYTES bytes'); } if (PHP_INT_SIZE === 4) { return self::sign_core32($filePath, $secretKey); } /** @var int $size */ $size = filesize($filePath); if (!is_int($size)) { throw new SodiumException('Could not obtain the file size'); } /** @var resource $fp */ $fp = fopen($filePath, 'rb'); if (!is_resource($fp)) { throw new SodiumException('Could not open input file for reading'); } /** @var string $az */ $az = hash('sha512', self::substr($secretKey, 0, 32), true); $az[0] = self::intToChr(self::chrToInt($az[0]) & 248); $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64); $hs = hash_init('sha512'); self::hash_update($hs, self::substr($az, 32, 32)); /** @var resource $hs */ $hs = self::updateHashWithFile($hs, $fp, $size); /** @var string $nonceHash */ $nonceHash = hash_final($hs, true); /** @var string $pk */ $pk = self::substr($secretKey, 32, 32); /** @var string $nonce */ $nonce = ParagonIE_Sodium_Core_Ed25519::sc_reduce($nonceHash) . self::substr($nonceHash, 32); /** @var string $sig */ $sig = ParagonIE_Sodium_Core_Ed25519::ge_p3_tobytes( ParagonIE_Sodium_Core_Ed25519::ge_scalarmult_base($nonce) ); $hs = hash_init('sha512'); self::hash_update($hs, self::substr($sig, 0, 32)); self::hash_update($hs, self::substr($pk, 0, 32)); /** @var resource $hs */ $hs = self::updateHashWithFile($hs, $fp, $size); /** @var string $hramHash */ $hramHash = hash_final($hs, true); /** @var string $hram */ $hram = ParagonIE_Sodium_Core_Ed25519::sc_reduce($hramHash); /** @var string $sigAfter */ $sigAfter = ParagonIE_Sodium_Core_Ed25519::sc_muladd($hram, $az, $nonce); /** @var string $sig */ $sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32); try { ParagonIE_Sodium_Compat::memzero($az); } catch (SodiumException $ex) { $az = null; } fclose($fp); return $sig; } /** * Verify a file (rather than a string). Uses less memory than * ParagonIE_Sodium_Compat::crypto_sign_verify_detached(), but * produces the same result. * * @param string $sig Ed25519 signature * @param string $filePath Absolute path to a file on the filesystem * @param string $publicKey Signing public key * * @return bool * @throws SodiumException * @throws TypeError * @throws Exception */ public static function verify( $sig, $filePath, $publicKey ) { /* Type checks: */ if (!is_string($sig)) { throw new TypeError('Argument 1 must be a string, ' . gettype($sig) . ' given.'); } if (!is_string($filePath)) { throw new TypeError('Argument 2 must be a string, ' . gettype($filePath) . ' given.'); } if (!is_string($publicKey)) { throw new TypeError('Argument 3 must be a string, ' . gettype($publicKey) . ' given.'); } /* Input validation: */ if (self::strlen($sig) !== ParagonIE_Sodium_Compat::CRYPTO_SIGN_BYTES) { throw new TypeError('Argument 1 must be CRYPTO_SIGN_BYTES bytes'); } if (self::strlen($publicKey) !== ParagonIE_Sodium_Compat::CRYPTO_SIGN_PUBLICKEYBYTES) { throw new TypeError('Argument 3 must be CRYPTO_SIGN_PUBLICKEYBYTES bytes'); } if (self::strlen($sig) < 64) { throw new SodiumException('Signature is too short'); } if (PHP_INT_SIZE === 4) { return self::verify_core32($sig, $filePath, $publicKey); } /* Security checks */ if ( (ParagonIE_Sodium_Core_Ed25519::chrToInt($sig[63]) & 240) && ParagonIE_Sodium_Core_Ed25519::check_S_lt_L(self::substr($sig, 32, 32)) ) { throw new SodiumException('S < L - Invalid signature'); } if (ParagonIE_Sodium_Core_Ed25519::small_order($sig)) { throw new SodiumException('Signature is on too small of an order'); } if ((self::chrToInt($sig[63]) & 224) !== 0) { throw new SodiumException('Invalid signature'); } $d = 0; for ($i = 0; $i < 32; ++$i) { $d |= self::chrToInt($publicKey[$i]); } if ($d === 0) { throw new SodiumException('All zero public key'); } /** @var int $size */ $size = filesize($filePath); if (!is_int($size)) { throw new SodiumException('Could not obtain the file size'); } /** @var resource $fp */ $fp = fopen($filePath, 'rb'); if (!is_resource($fp)) { throw new SodiumException('Could not open input file for reading'); } /** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */ $orig = ParagonIE_Sodium_Compat::$fastMult; // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification. ParagonIE_Sodium_Compat::$fastMult = true; /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A */ $A = ParagonIE_Sodium_Core_Ed25519::ge_frombytes_negate_vartime($publicKey); $hs = hash_init('sha512'); self::hash_update($hs, self::substr($sig, 0, 32)); self::hash_update($hs, self::substr($publicKey, 0, 32)); /** @var resource $hs */ $hs = self::updateHashWithFile($hs, $fp, $size); /** @var string $hDigest */ $hDigest = hash_final($hs, true); /** @var string $h */ $h = ParagonIE_Sodium_Core_Ed25519::sc_reduce($hDigest) . self::substr($hDigest, 32); /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P2 $R */ $R = ParagonIE_Sodium_Core_Ed25519::ge_double_scalarmult_vartime( $h, $A, self::substr($sig, 32) ); /** @var string $rcheck */ $rcheck = ParagonIE_Sodium_Core_Ed25519::ge_tobytes($R); // Close the file handle fclose($fp); // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before. ParagonIE_Sodium_Compat::$fastMult = $orig; return self::verify_32($rcheck, self::substr($sig, 0, 32)); } /** * @param resource $ifp * @param resource $ofp * @param int $mlen * @param string $nonce * @param string $boxKeypair * @return bool * @throws SodiumException * @throws TypeError */ protected static function box_encrypt($ifp, $ofp, $mlen, $nonce, $boxKeypair) { if (PHP_INT_SIZE === 4) { return self::secretbox_encrypt( $ifp, $ofp, $mlen, $nonce, ParagonIE_Sodium_Crypto32::box_beforenm( ParagonIE_Sodium_Crypto32::box_secretkey($boxKeypair), ParagonIE_Sodium_Crypto32::box_publickey($boxKeypair) ) ); } return self::secretbox_encrypt( $ifp, $ofp, $mlen, $nonce, ParagonIE_Sodium_Crypto::box_beforenm( ParagonIE_Sodium_Crypto::box_secretkey($boxKeypair), ParagonIE_Sodium_Crypto::box_publickey($boxKeypair) ) ); } /** * @param resource $ifp * @param resource $ofp * @param int $mlen * @param string $nonce * @param string $boxKeypair * @return bool * @throws SodiumException * @throws TypeError */ protected static function box_decrypt($ifp, $ofp, $mlen, $nonce, $boxKeypair) { if (PHP_INT_SIZE === 4) { return self::secretbox_decrypt( $ifp, $ofp, $mlen, $nonce, ParagonIE_Sodium_Crypto32::box_beforenm( ParagonIE_Sodium_Crypto32::box_secretkey($boxKeypair), ParagonIE_Sodium_Crypto32::box_publickey($boxKeypair) ) ); } return self::secretbox_decrypt( $ifp, $ofp, $mlen, $nonce, ParagonIE_Sodium_Crypto::box_beforenm( ParagonIE_Sodium_Crypto::box_secretkey($boxKeypair), ParagonIE_Sodium_Crypto::box_publickey($boxKeypair) ) ); } /** * Encrypt a file * * @param resource $ifp * @param resource $ofp * @param int $mlen * @param string $nonce * @param string $key * @return bool * @throws SodiumException * @throws TypeError */ protected static function secretbox_encrypt($ifp, $ofp, $mlen, $nonce, $key) { if (PHP_INT_SIZE === 4) { return self::secretbox_encrypt_core32($ifp, $ofp, $mlen, $nonce, $key); } $plaintext = fread($ifp, 32); if (!is_string($plaintext)) { throw new SodiumException('Could not read input file'); } $first32 = self::ftell($ifp); /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key); /** @var string $realNonce */ $realNonce = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8); /** @var string $block0 */ $block0 = str_repeat("\x00", 32); /** @var int $mlen - Length of the plaintext message */ $mlen0 = $mlen; if ($mlen0 > 64 - ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES) { $mlen0 = 64 - ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES; } $block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0, $mlen0); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20_xor( $block0, $realNonce, $subkey ); $state = new ParagonIE_Sodium_Core_Poly1305_State( ParagonIE_Sodium_Core_Util::substr( $block0, 0, ParagonIE_Sodium_Crypto::onetimeauth_poly1305_KEYBYTES ) ); // Pre-write 16 blank bytes for the Poly1305 tag $start = self::ftell($ofp); fwrite($ofp, str_repeat("\x00", 16)); /** @var string $c */ $cBlock = ParagonIE_Sodium_Core_Util::substr( $block0, ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES ); $state->update($cBlock); fwrite($ofp, $cBlock); $mlen -= 32; /** @var int $iter */ $iter = 1; /** @var int $incr */ $incr = self::BUFFER_SIZE >> 6; /* * Set the cursor to the end of the first half-block. All future bytes will * generated from salsa20_xor_ic, starting from 1 (second block). */ fseek($ifp, $first32, SEEK_SET); while ($mlen > 0) { $blockSize = $mlen > self::BUFFER_SIZE ? self::BUFFER_SIZE : $mlen; $plaintext = fread($ifp, $blockSize); if (!is_string($plaintext)) { throw new SodiumException('Could not read input file'); } $cBlock = ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic( $plaintext, $realNonce, $iter, $subkey ); fwrite($ofp, $cBlock, $blockSize); $state->update($cBlock); $mlen -= $blockSize; $iter += $incr; } try { ParagonIE_Sodium_Compat::memzero($block0); ParagonIE_Sodium_Compat::memzero($subkey); } catch (SodiumException $ex) { $block0 = null; $subkey = null; } $end = self::ftell($ofp); /* * Write the Poly1305 authentication tag that provides integrity * over the ciphertext (encrypt-then-MAC) */ fseek($ofp, $start, SEEK_SET); fwrite($ofp, $state->finish(), ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_MACBYTES); fseek($ofp, $end, SEEK_SET); unset($state); return true; } /** * Decrypt a file * * @param resource $ifp * @param resource $ofp * @param int $mlen * @param string $nonce * @param string $key * @return bool * @throws SodiumException * @throws TypeError */ protected static function secretbox_decrypt($ifp, $ofp, $mlen, $nonce, $key) { if (PHP_INT_SIZE === 4) { return self::secretbox_decrypt_core32($ifp, $ofp, $mlen, $nonce, $key); } $tag = fread($ifp, 16); if (!is_string($tag)) { throw new SodiumException('Could not read input file'); } /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key); /** @var string $realNonce */ $realNonce = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20( 64, ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8), $subkey ); /* Verify the Poly1305 MAC -before- attempting to decrypt! */ $state = new ParagonIE_Sodium_Core_Poly1305_State(self::substr($block0, 0, 32)); if (!self::onetimeauth_verify($state, $ifp, $tag, $mlen)) { throw new SodiumException('Invalid MAC'); } /* * Set the cursor to the end of the first half-block. All future bytes will * generated from salsa20_xor_ic, starting from 1 (second block). */ $first32 = fread($ifp, 32); if (!is_string($first32)) { throw new SodiumException('Could not read input file'); } $first32len = self::strlen($first32); fwrite( $ofp, self::xorStrings( self::substr($block0, 32, $first32len), self::substr($first32, 0, $first32len) ) ); $mlen -= 32; /** @var int $iter */ $iter = 1; /** @var int $incr */ $incr = self::BUFFER_SIZE >> 6; /* Decrypts ciphertext, writes to output file. */ while ($mlen > 0) { $blockSize = $mlen > self::BUFFER_SIZE ? self::BUFFER_SIZE : $mlen; $ciphertext = fread($ifp, $blockSize); if (!is_string($ciphertext)) { throw new SodiumException('Could not read input file'); } $pBlock = ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic( $ciphertext, $realNonce, $iter, $subkey ); fwrite($ofp, $pBlock, $blockSize); $mlen -= $blockSize; $iter += $incr; } return true; } /** * @param ParagonIE_Sodium_Core_Poly1305_State $state * @param resource $ifp * @param string $tag * @param int $mlen * @return bool * @throws SodiumException * @throws TypeError */ protected static function onetimeauth_verify( ParagonIE_Sodium_Core_Poly1305_State $state, $ifp, $tag = '', $mlen = 0 ) { /** @var int $pos */ $pos = self::ftell($ifp); /** @var int $iter */ $iter = 1; /** @var int $incr */ $incr = self::BUFFER_SIZE >> 6; while ($mlen > 0) { $blockSize = $mlen > self::BUFFER_SIZE ? self::BUFFER_SIZE : $mlen; $ciphertext = fread($ifp, $blockSize); if (!is_string($ciphertext)) { throw new SodiumException('Could not read input file'); } $state->update($ciphertext); $mlen -= $blockSize; $iter += $incr; } $res = ParagonIE_Sodium_Core_Util::verify_16($tag, $state->finish()); fseek($ifp, $pos, SEEK_SET); return $res; } /** * Update a hash context with the contents of a file, without * loading the entire file into memory. * * @param resource|HashContext $hash * @param resource $fp * @param int $size * @return resource|object Resource on PHP < 7.2, HashContext object on PHP >= 7.2 * @throws SodiumException * @throws TypeError * @psalm-suppress PossiblyInvalidArgument * PHP 7.2 changes from a resource to an object, * which causes Psalm to complain about an error. * @psalm-suppress TypeCoercion * Ditto. */ public static function updateHashWithFile($hash, $fp, $size = 0) { /* Type checks: */ if (PHP_VERSION_ID < 70200) { if (!is_resource($hash)) { throw new TypeError('Argument 1 must be a resource, ' . gettype($hash) . ' given.'); } } else { if (!is_object($hash)) { throw new TypeError('Argument 1 must be an object (PHP 7.2+), ' . gettype($hash) . ' given.'); } } if (!is_resource($fp)) { throw new TypeError('Argument 2 must be a resource, ' . gettype($fp) . ' given.'); } if (!is_int($size)) { throw new TypeError('Argument 3 must be an integer, ' . gettype($size) . ' given.'); } /** @var int $originalPosition */ $originalPosition = self::ftell($fp); // Move file pointer to beginning of file fseek($fp, 0, SEEK_SET); for ($i = 0; $i < $size; $i += self::BUFFER_SIZE) { /** @var string|bool $message */ $message = fread( $fp, ($size - $i) > self::BUFFER_SIZE ? $size - $i : self::BUFFER_SIZE ); if (!is_string($message)) { throw new SodiumException('Unexpected error reading from file.'); } /** @var string $message */ /** @psalm-suppress InvalidArgument */ self::hash_update($hash, $message); } // Reset file pointer's position fseek($fp, $originalPosition, SEEK_SET); return $hash; } /** * Sign a file (rather than a string). Uses less memory than * ParagonIE_Sodium_Compat::crypto_sign_detached(), but produces * the same result. (32-bit) * * @param string $filePath Absolute path to a file on the filesystem * @param string $secretKey Secret signing key * * @return string Ed25519 signature * @throws SodiumException * @throws TypeError */ private static function sign_core32($filePath, $secretKey) { $size = filesize($filePath); if (!is_int($size)) { throw new SodiumException('Could not obtain the file size'); } $fp = fopen($filePath, 'rb'); if (!is_resource($fp)) { throw new SodiumException('Could not open input file for reading'); } /** @var string $az */ $az = hash('sha512', self::substr($secretKey, 0, 32), true); $az[0] = self::intToChr(self::chrToInt($az[0]) & 248); $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64); $hs = hash_init('sha512'); self::hash_update($hs, self::substr($az, 32, 32)); /** @var resource $hs */ $hs = self::updateHashWithFile($hs, $fp, $size); $nonceHash = hash_final($hs, true); $pk = self::substr($secretKey, 32, 32); $nonce = ParagonIE_Sodium_Core32_Ed25519::sc_reduce($nonceHash) . self::substr($nonceHash, 32); $sig = ParagonIE_Sodium_Core32_Ed25519::ge_p3_tobytes( ParagonIE_Sodium_Core32_Ed25519::ge_scalarmult_base($nonce) ); $hs = hash_init('sha512'); self::hash_update($hs, self::substr($sig, 0, 32)); self::hash_update($hs, self::substr($pk, 0, 32)); /** @var resource $hs */ $hs = self::updateHashWithFile($hs, $fp, $size); $hramHash = hash_final($hs, true); $hram = ParagonIE_Sodium_Core32_Ed25519::sc_reduce($hramHash); $sigAfter = ParagonIE_Sodium_Core32_Ed25519::sc_muladd($hram, $az, $nonce); /** @var string $sig */ $sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32); try { ParagonIE_Sodium_Compat::memzero($az); } catch (SodiumException $ex) { $az = null; } fclose($fp); return $sig; } /** * * Verify a file (rather than a string). Uses less memory than * ParagonIE_Sodium_Compat::crypto_sign_verify_detached(), but * produces the same result. (32-bit) * * @param string $sig Ed25519 signature * @param string $filePath Absolute path to a file on the filesystem * @param string $publicKey Signing public key * * @return bool * @throws SodiumException * @throws Exception */ public static function verify_core32($sig, $filePath, $publicKey) { /* Security checks */ if (ParagonIE_Sodium_Core32_Ed25519::check_S_lt_L(self::substr($sig, 32, 32))) { throw new SodiumException('S < L - Invalid signature'); } if (ParagonIE_Sodium_Core32_Ed25519::small_order($sig)) { throw new SodiumException('Signature is on too small of an order'); } if ((self::chrToInt($sig[63]) & 224) !== 0) { throw new SodiumException('Invalid signature'); } $d = 0; for ($i = 0; $i < 32; ++$i) { $d |= self::chrToInt($publicKey[$i]); } if ($d === 0) { throw new SodiumException('All zero public key'); } /** @var int|bool $size */ $size = filesize($filePath); if (!is_int($size)) { throw new SodiumException('Could not obtain the file size'); } /** @var int $size */ /** @var resource|bool $fp */ $fp = fopen($filePath, 'rb'); if (!is_resource($fp)) { throw new SodiumException('Could not open input file for reading'); } /** @var resource $fp */ /** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */ $orig = ParagonIE_Sodium_Compat::$fastMult; // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification. ParagonIE_Sodium_Compat::$fastMult = true; /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A */ $A = ParagonIE_Sodium_Core32_Ed25519::ge_frombytes_negate_vartime($publicKey); $hs = hash_init('sha512'); self::hash_update($hs, self::substr($sig, 0, 32)); self::hash_update($hs, self::substr($publicKey, 0, 32)); /** @var resource $hs */ $hs = self::updateHashWithFile($hs, $fp, $size); /** @var string $hDigest */ $hDigest = hash_final($hs, true); /** @var string $h */ $h = ParagonIE_Sodium_Core32_Ed25519::sc_reduce($hDigest) . self::substr($hDigest, 32); /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $R */ $R = ParagonIE_Sodium_Core32_Ed25519::ge_double_scalarmult_vartime( $h, $A, self::substr($sig, 32) ); /** @var string $rcheck */ $rcheck = ParagonIE_Sodium_Core32_Ed25519::ge_tobytes($R); // Close the file handle fclose($fp); // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before. ParagonIE_Sodium_Compat::$fastMult = $orig; return self::verify_32($rcheck, self::substr($sig, 0, 32)); } /** * Encrypt a file (32-bit) * * @param resource $ifp * @param resource $ofp * @param int $mlen * @param string $nonce * @param string $key * @return bool * @throws SodiumException * @throws TypeError */ protected static function secretbox_encrypt_core32($ifp, $ofp, $mlen, $nonce, $key) { $plaintext = fread($ifp, 32); if (!is_string($plaintext)) { throw new SodiumException('Could not read input file'); } $first32 = self::ftell($ifp); /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key); /** @var string $realNonce */ $realNonce = ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8); /** @var string $block0 */ $block0 = str_repeat("\x00", 32); /** @var int $mlen - Length of the plaintext message */ $mlen0 = $mlen; if ($mlen0 > 64 - ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES) { $mlen0 = 64 - ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES; } $block0 .= ParagonIE_Sodium_Core32_Util::substr($plaintext, 0, $mlen0); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20_xor( $block0, $realNonce, $subkey ); $state = new ParagonIE_Sodium_Core32_Poly1305_State( ParagonIE_Sodium_Core32_Util::substr( $block0, 0, ParagonIE_Sodium_Crypto::onetimeauth_poly1305_KEYBYTES ) ); // Pre-write 16 blank bytes for the Poly1305 tag $start = self::ftell($ofp); fwrite($ofp, str_repeat("\x00", 16)); /** @var string $c */ $cBlock = ParagonIE_Sodium_Core32_Util::substr( $block0, ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES ); $state->update($cBlock); fwrite($ofp, $cBlock); $mlen -= 32; /** @var int $iter */ $iter = 1; /** @var int $incr */ $incr = self::BUFFER_SIZE >> 6; /* * Set the cursor to the end of the first half-block. All future bytes will * generated from salsa20_xor_ic, starting from 1 (second block). */ fseek($ifp, $first32, SEEK_SET); while ($mlen > 0) { $blockSize = $mlen > self::BUFFER_SIZE ? self::BUFFER_SIZE : $mlen; $plaintext = fread($ifp, $blockSize); if (!is_string($plaintext)) { throw new SodiumException('Could not read input file'); } $cBlock = ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic( $plaintext, $realNonce, $iter, $subkey ); fwrite($ofp, $cBlock, $blockSize); $state->update($cBlock); $mlen -= $blockSize; $iter += $incr; } try { ParagonIE_Sodium_Compat::memzero($block0); ParagonIE_Sodium_Compat::memzero($subkey); } catch (SodiumException $ex) { $block0 = null; $subkey = null; } $end = self::ftell($ofp); /* * Write the Poly1305 authentication tag that provides integrity * over the ciphertext (encrypt-then-MAC) */ fseek($ofp, $start, SEEK_SET); fwrite($ofp, $state->finish(), ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_MACBYTES); fseek($ofp, $end, SEEK_SET); unset($state); return true; } /** * Decrypt a file (32-bit) * * @param resource $ifp * @param resource $ofp * @param int $mlen * @param string $nonce * @param string $key * @return bool * @throws SodiumException * @throws TypeError */ protected static function secretbox_decrypt_core32($ifp, $ofp, $mlen, $nonce, $key) { $tag = fread($ifp, 16); if (!is_string($tag)) { throw new SodiumException('Could not read input file'); } /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key); /** @var string $realNonce */ $realNonce = ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20( 64, ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8), $subkey ); /* Verify the Poly1305 MAC -before- attempting to decrypt! */ $state = new ParagonIE_Sodium_Core32_Poly1305_State(self::substr($block0, 0, 32)); if (!self::onetimeauth_verify_core32($state, $ifp, $tag, $mlen)) { throw new SodiumException('Invalid MAC'); } /* * Set the cursor to the end of the first half-block. All future bytes will * generated from salsa20_xor_ic, starting from 1 (second block). */ $first32 = fread($ifp, 32); if (!is_string($first32)) { throw new SodiumException('Could not read input file'); } $first32len = self::strlen($first32); fwrite( $ofp, self::xorStrings( self::substr($block0, 32, $first32len), self::substr($first32, 0, $first32len) ) ); $mlen -= 32; /** @var int $iter */ $iter = 1; /** @var int $incr */ $incr = self::BUFFER_SIZE >> 6; /* Decrypts ciphertext, writes to output file. */ while ($mlen > 0) { $blockSize = $mlen > self::BUFFER_SIZE ? self::BUFFER_SIZE : $mlen; $ciphertext = fread($ifp, $blockSize); if (!is_string($ciphertext)) { throw new SodiumException('Could not read input file'); } $pBlock = ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic( $ciphertext, $realNonce, $iter, $subkey ); fwrite($ofp, $pBlock, $blockSize); $mlen -= $blockSize; $iter += $incr; } return true; } /** * One-time message authentication for 32-bit systems * * @param ParagonIE_Sodium_Core32_Poly1305_State $state * @param resource $ifp * @param string $tag * @param int $mlen * @return bool * @throws SodiumException * @throws TypeError */ protected static function onetimeauth_verify_core32( ParagonIE_Sodium_Core32_Poly1305_State $state, $ifp, $tag = '', $mlen = 0 ) { /** @var int $pos */ $pos = self::ftell($ifp); while ($mlen > 0) { $blockSize = $mlen > self::BUFFER_SIZE ? self::BUFFER_SIZE : $mlen; $ciphertext = fread($ifp, $blockSize); if (!is_string($ciphertext)) { throw new SodiumException('Could not read input file'); } $state->update($ciphertext); $mlen -= $blockSize; } $res = ParagonIE_Sodium_Core32_Util::verify_16($tag, $state->finish()); fseek($ifp, $pos, SEEK_SET); return $res; } /** * @param resource $resource * @return int * @throws SodiumException */ private static function ftell($resource) { $return = ftell($resource); if (!is_int($return)) { throw new SodiumException('ftell() returned false'); } return (int) $return; } } PK!^ Crypto.phpnu[update($ad); $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen)); $state->update($ciphertext); $state->update(ParagonIE_Sodium_Core_Util::store64_le($clen)); $computed_mac = $state->finish(); /* Compare the given MAC with the recalculated MAC: */ if (!ParagonIE_Sodium_Core_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_Core_ChaCha20::streamXorIc( $ciphertext, $nonce, $key, ParagonIE_Sodium_Core_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_Core_Util::strlen($message); /** @var int $adlen - Length of the associated data */ $adlen = ParagonIE_Sodium_Core_Util::strlen($ad); /** @var string The first block of the chacha20 keystream, used as a poly1305 key */ $block0 = ParagonIE_Sodium_Core_ChaCha20::stream( 32, $nonce, $key ); $state = new ParagonIE_Sodium_Core_Poly1305_State($block0); try { ParagonIE_Sodium_Compat::memzero($block0); } catch (SodiumException $ex) { $block0 = null; } /** @var string $ciphertext - Raw encrypted data */ $ciphertext = ParagonIE_Sodium_Core_ChaCha20::streamXorIc( $message, $nonce, $key, ParagonIE_Sodium_Core_Util::store64_le(1) ); $state->update($ad); $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen)); $state->update($ciphertext); $state->update(ParagonIE_Sodium_Core_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_Core_Util::strlen($ad); /** @var int $len - Length of message (ciphertext + MAC) */ $len = ParagonIE_Sodium_Core_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_Core_ChaCha20::ietfStream( 32, $nonce, $key ); /** @var string $mac - Message authentication code */ $mac = ParagonIE_Sodium_Core_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_Core_Util::substr( $message, 0, $len - self::aead_chacha20poly1305_IETF_ABYTES ); /* Recalculate the Poly1305 authentication tag (MAC): */ $state = new ParagonIE_Sodium_Core_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_Core_Util::store64_le($adlen)); $state->update(ParagonIE_Sodium_Core_Util::store64_le($clen)); $computed_mac = $state->finish(); /* Compare the given MAC with the recalculated MAC: */ if (!ParagonIE_Sodium_Core_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_Core_ChaCha20::ietfStreamXorIc( $ciphertext, $nonce, $key, ParagonIE_Sodium_Core_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_Core_Util::strlen($message); /** @var int $adlen - Length of the associated data */ $adlen = ParagonIE_Sodium_Core_Util::strlen($ad); /** @var string The first block of the chacha20 keystream, used as a poly1305 key */ $block0 = ParagonIE_Sodium_Core_ChaCha20::ietfStream( 32, $nonce, $key ); $state = new ParagonIE_Sodium_Core_Poly1305_State($block0); try { ParagonIE_Sodium_Compat::memzero($block0); } catch (SodiumException $ex) { $block0 = null; } /** @var string $ciphertext - Raw encrypted data */ $ciphertext = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( $message, $nonce, $key, ParagonIE_Sodium_Core_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_Core_Util::store64_le($adlen)); $state->update(ParagonIE_Sodium_Core_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_Core_HChaCha20::hChaCha20( ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16), $key ); $nonceLast = "\x00\x00\x00\x00" . ParagonIE_Sodium_Core_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_Core_HChaCha20::hChaCha20( ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16), $key ); $nonceLast = "\x00\x00\x00\x00" . ParagonIE_Sodium_Core_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_Core_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_Core_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) { $c = self::secretbox( $plaintext, $nonce, self::box_beforenm( self::box_secretkey($keypair), self::box_publickey($keypair) ) ); return $c; } /** * 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_Core_Util::substr($message, 0, 32); /** @var string $ciphertext (ciphertext + MAC) */ $ciphertext = ParagonIE_Sodium_Core_Util::substr($message, 32); /** @var string $secretKey */ $secretKey = self::box_secretkey($keypair); /** @var string $publicKey */ $publicKey = self::box_publickey($keypair); /** @var string $nonce */ $nonce = self::generichash( $ephemeralPK . $publicKey, '', 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_Core_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_Core_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_Core_Util::substr($sKey, 0, 32) . ParagonIE_Sodium_Core_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_Core_Util::strlen($keypair) !== 64) { throw new RangeException( 'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.' ); } return ParagonIE_Sodium_Core_Util::substr($keypair, 0, 32); } /** * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $keypair * @return string * @throws RangeException * @throws TypeError */ public static function box_publickey($keypair) { if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) { throw new RangeException( 'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.' ); } return ParagonIE_Sodium_Core_Util::substr($keypair, 32, 32); } /** * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $sKey * @return string * @throws RangeException * @throws SodiumException * @throws TypeError */ public static function box_publickey_from_secretkey($sKey) { if (ParagonIE_Sodium_Core_Util::strlen($sKey) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES) { throw new RangeException( 'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES bytes long.' ); } return self::scalarmult_base($sKey); } /** * Decrypt a message encrypted with box(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $ciphertext * @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_Core_BLAKE2b::$iv is initialized ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor(); $k = null; if (!empty($key)) { /** @var SplFixedArray $k */ $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key); if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) { throw new RangeException('Invalid key size'); } } /** @var SplFixedArray $in */ $in = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($message); /** @var SplFixedArray $ctx */ $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outlen); ParagonIE_Sodium_Core_BLAKE2b::update($ctx, $in, $in->count()); /** @var SplFixedArray $out */ $out = new SplFixedArray($outlen); $out = ParagonIE_Sodium_Core_BLAKE2b::finish($ctx, $out); /** @var array */ $outArray = $out->toArray(); return ParagonIE_Sodium_Core_Util::intArrayToString($outArray); } /** * Finalize a BLAKE2b hashing context, returning the hash. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @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_Core_BLAKE2b::stringToContext($ctx); /** @var SplFixedArray $out */ $out = ParagonIE_Sodium_Core_BLAKE2b::finish($context, $out); /** @var array */ $outArray = $out->toArray(); return ParagonIE_Sodium_Core_Util::intArrayToString($outArray); } /** * Initialize a hashing context for BLAKE2b. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param 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_Core_BLAKE2b::$iv is initialized ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor(); $k = null; if (!empty($key)) { $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key); if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) { throw new RangeException('Invalid key size'); } } /** @var SplFixedArray $ctx */ $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength); return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx); } /** * Initialize a hashing context for BLAKE2b. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param 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_Core_BLAKE2b::$iv is initialized ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor(); $k = null; if (!empty($key)) { $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key); if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) { throw new RangeException('Invalid key size'); } } if (!empty($salt)) { $s = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($salt); } else { $s = null; } if (!empty($salt)) { $p = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($personal); } else { $p = null; } /** @var SplFixedArray $ctx */ $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength, $s, $p); return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx); } /** * Update a hashing context for BLAKE2b with $message * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $ctx * @param string $message * @return string * @throws SodiumException * @throws TypeError */ public static function generichash_update($ctx, $message) { // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor(); /** @var SplFixedArray $context */ $context = ParagonIE_Sodium_Core_BLAKE2b::stringToContext($ctx); /** @var SplFixedArray $in */ $in = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($message); ParagonIE_Sodium_Core_BLAKE2b::update($context, $in, $in->count()); return ParagonIE_Sodium_Core_BLAKE2b::contextToString($context); } /** * Libsodium's crypto_kx(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $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 ParagonIE_Sodium_Compat::crypto_generichash( ParagonIE_Sodium_Compat::crypto_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_Core_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_Core_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_Core_Util::chrToInt($q[$i]); } /* branch-free variant of === 0 */ if (-(1 & (($d - 1) >> 8))) { throw new SodiumException('Zero public key is not allowed'); } } /** * XSalsa20-Poly1305 authenticated symmetric-key encryption. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $plaintext * @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_Core_HSalsa20::hsalsa20($nonce, $key); /** @var string $block0 */ $block0 = str_repeat("\x00", 32); /** @var int $mlen - Length of the plaintext message */ $mlen = ParagonIE_Sodium_Core_Util::strlen($plaintext); $mlen0 = $mlen; if ($mlen0 > 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES) { $mlen0 = 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES; } $block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0, $mlen0); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20_xor( $block0, ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8), $subkey ); /** @var string $c */ $c = ParagonIE_Sodium_Core_Util::substr( $block0, self::secretbox_xsalsa20poly1305_ZEROBYTES ); if ($mlen > $mlen0) { $c .= ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic( ParagonIE_Sodium_Core_Util::substr( $plaintext, self::secretbox_xsalsa20poly1305_ZEROBYTES ), ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8), 1, $subkey ); } $state = new ParagonIE_Sodium_Core_Poly1305_State( ParagonIE_Sodium_Core_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_Core_Util::substr( $ciphertext, 0, self::secretbox_xsalsa20poly1305_MACBYTES ); /** @var string $c */ $c = ParagonIE_Sodium_Core_Util::substr( $ciphertext, self::secretbox_xsalsa20poly1305_MACBYTES ); /** @var int $clen */ $clen = ParagonIE_Sodium_Core_Util::strlen($c); /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20( 64, ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8), $subkey ); $verified = ParagonIE_Sodium_Core_Poly1305::onetimeauth_verify( $mac, $c, ParagonIE_Sodium_Core_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_Core_Util::xorStrings( ParagonIE_Sodium_Core_Util::substr($block0, self::secretbox_xsalsa20poly1305_ZEROBYTES), ParagonIE_Sodium_Core_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_Core_Salsa20::salsa20_xor_ic( ParagonIE_Sodium_Core_Util::substr( $c, self::secretbox_xsalsa20poly1305_ZEROBYTES ), ParagonIE_Sodium_Core_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_Core_HChaCha20::hChaCha20( ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16), $key ); $nonceLast = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8); /** @var string $block0 */ $block0 = str_repeat("\x00", 32); /** @var int $mlen - Length of the plaintext message */ $mlen = ParagonIE_Sodium_Core_Util::strlen($plaintext); $mlen0 = $mlen; if ($mlen0 > 64 - self::secretbox_xchacha20poly1305_ZEROBYTES) { $mlen0 = 64 - self::secretbox_xchacha20poly1305_ZEROBYTES; } $block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0, $mlen0); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core_ChaCha20::streamXorIc( $block0, $nonceLast, $subkey ); /** @var string $c */ $c = ParagonIE_Sodium_Core_Util::substr( $block0, self::secretbox_xchacha20poly1305_ZEROBYTES ); if ($mlen > $mlen0) { $c .= ParagonIE_Sodium_Core_ChaCha20::streamXorIc( ParagonIE_Sodium_Core_Util::substr( $plaintext, self::secretbox_xchacha20poly1305_ZEROBYTES ), $nonceLast, $subkey, ParagonIE_Sodium_Core_Util::store64_le(1) ); } $state = new ParagonIE_Sodium_Core_Poly1305_State( ParagonIE_Sodium_Core_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_Core_Util::substr( $ciphertext, 0, self::secretbox_xchacha20poly1305_MACBYTES ); /** @var string $c */ $c = ParagonIE_Sodium_Core_Util::substr( $ciphertext, self::secretbox_xchacha20poly1305_MACBYTES ); /** @var int $clen */ $clen = ParagonIE_Sodium_Core_Util::strlen($c); /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core_HChaCha20::hchacha20($nonce, $key); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core_ChaCha20::stream( 64, ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8), $subkey ); $verified = ParagonIE_Sodium_Core_Poly1305::onetimeauth_verify( $mac, $c, ParagonIE_Sodium_Core_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_Core_Util::xorStrings( ParagonIE_Sodium_Core_Util::substr($block0, self::secretbox_xchacha20poly1305_ZEROBYTES), ParagonIE_Sodium_Core_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_Core_ChaCha20::streamXorIc( ParagonIE_Sodium_Core_Util::substr( $c, self::secretbox_xchacha20poly1305_ZEROBYTES ), ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8), (string) $subkey, ParagonIE_Sodium_Core_Util::store64_le(1) ); } return $m; } /** * @param string $key * @return array 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_Core_HChaCha20::hChaCha20($out, $key); $state = new ParagonIE_Sodium_Core_SecretStream_State( $subkey, ParagonIE_Sodium_Core_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_Core_HChaCha20::hChaCha20( ParagonIE_Sodium_Core_Util::substr($header, 0, 16), $key ); $state = new ParagonIE_Sodium_Core_SecretStream_State( $subkey, ParagonIE_Sodium_Core_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_Core_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_Core_Util::strlen($msg); $aadlen = ParagonIE_Sodium_Core_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_Core_Poly1305_State( ParagonIE_Sodium_Core_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_Core_ChaCha20::ietfStreamXorIc( ParagonIE_Sodium_Core_Util::intToChr($tag) . str_repeat("\0", 63), $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core_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_Core_ChaCha20::ietfStreamXorIc( $msg, $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core_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_Core_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_Core_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_Core_SecretStream_State::fromString($state); $cipherlen = ParagonIE_Sodium_Core_Util::strlen($cipher); # mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES; $msglen = $cipherlen - ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES; $aadlen = ParagonIE_Sodium_Core_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_Core_Poly1305_State( ParagonIE_Sodium_Core_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_Core_ChaCha20::ietfStreamXorIc( $cipher[0] . str_repeat("\0", 63), $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core_Util::store64_le(1) ); # tag = block[0]; # block[0] = in[0]; # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); $tag = ParagonIE_Sodium_Core_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_Core_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_Core_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_Core_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_Core_Util::substr($cipher, $msglen + 1, 16); if (!ParagonIE_Sodium_Core_Util::hashEquals($mac, $stored)) { return false; } # crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k); $out = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( ParagonIE_Sodium_Core_Util::substr($cipher, 1, $msglen), $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core_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_Core_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_Core_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_Core_ChaCha20::ietfStreamXorIc( $new_key_and_inonce, $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core_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_Core_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_Core_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_Core_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_Core_Ed25519::verify_detached($signature, $message, $pk); } } PK!```Core32/Int32.phpnu[ - 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 $a * @param array $b * @param int $baseLog2 * @return array */ public function multiplyLong(array $a, array $b, $baseLog2 = 16) { $a_l = count($a); $b_l = count($b); /** @var array $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 $limbs */ $limbs =& $return->limbs; /** @var array $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 $limbs */ $limbs =& $return->limbs; /** @var array $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 */ 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 ''; } } } PK!xHHCore32/SecretStream/State.phpnu[key = $key; $this->counter = 1; if (is_null($nonce)) { $nonce = str_repeat("\0", 12); } $this->nonce = str_pad($nonce, 12, "\0", STR_PAD_RIGHT);; $this->_pad = str_repeat("\0", 4); } /** * @return self */ public function counterReset() { $this->counter = 1; $this->_pad = str_repeat("\0", 4); return $this; } /** * @return string */ public function getKey() { return $this->key; } /** * @return string */ public function getCounter() { return ParagonIE_Sodium_Core32_Util::store32_le($this->counter); } /** * @return string */ public function getNonce() { if (!is_string($this->nonce)) { $this->nonce = str_repeat("\0", 12); } if (ParagonIE_Sodium_Core32_Util::strlen($this->nonce) !== 12) { $this->nonce = str_pad($this->nonce, 12, "\0", STR_PAD_RIGHT); } return $this->nonce; } /** * @return string */ public function getCombinedNonce() { return $this->getCounter() . ParagonIE_Sodium_Core32_Util::substr($this->getNonce(), 0, 8); } /** * @return self */ public function incrementCounter() { ++$this->counter; return $this; } /** * @return bool */ public function needsRekey() { return ($this->counter & 0xffff) === 0; } /** * @param string $newKeyAndNonce * @return self */ public function rekey($newKeyAndNonce) { $this->key = ParagonIE_Sodium_Core32_Util::substr($newKeyAndNonce, 0, 32); $this->nonce = str_pad( ParagonIE_Sodium_Core32_Util::substr($newKeyAndNonce, 32), 12, "\0", STR_PAD_RIGHT ); return $this; } /** * @param string $str * @return self */ public function xorNonce($str) { $this->nonce = ParagonIE_Sodium_Core32_Util::xorStrings( $this->getNonce(), str_pad( ParagonIE_Sodium_Core32_Util::substr($str, 0, 8), 12, "\0", STR_PAD_RIGHT ) ); return $this; } /** * @param string $string * @return self */ public static function fromString($string) { $state = new ParagonIE_Sodium_Core32_SecretStream_State( ParagonIE_Sodium_Core32_Util::substr($string, 0, 32) ); $state->counter = ParagonIE_Sodium_Core32_Util::load_4( ParagonIE_Sodium_Core32_Util::substr($string, 32, 4) ); $state->nonce = ParagonIE_Sodium_Core32_Util::substr($string, 36, 12); $state->_pad = ParagonIE_Sodium_Core32_Util::substr($string, 48, 8); return $state; } /** * @return string */ public function toString() { return $this->key . $this->getCounter() . $this->nonce . $this->_pad; } } PK![(Core32/SipHash.phpnu[ $v * @return array */ 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(); } } PK!X]>]>Core32/Poly1305/State.phpnu[ */ protected $buffer = array(); /** * @var bool */ protected $final = false; /** * @var array */ public $h; /** * @var int */ protected $leftover = 0; /** * @var array */ public $r; /** * @var array */ 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 $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(); } } PK!LTnnCore32/Curve25519.phpnu[addInt32($g[$i]); } /** @var array $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 $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 $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 */ $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 * @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 $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 $Ai */ $Ai = array(); static $Bi = array(); /** @var array $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 $Ai */ # slide(aslide,a); # slide(bslide,b); /** @var array $aslide */ $aslide = self::slide($a); /** @var array $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 $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 $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 $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 */ $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 */ $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 $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); } } PK!6VVCore32/Curve25519/Ge/P3.phpnu[X = $x; if ($y === null) { $y = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->Y = $y; if ($z === null) { $z = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->Z = $z; if ($t === null) { $t = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->T = $t; } } PK!ÍۤaaCore32/Curve25519/Ge/P2.phpnu[X = $x; if ($y === null) { $y = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->Y = $y; if ($z === null) { $z = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->Z = $z; } } PK!~gCore32/Curve25519/Ge/P1p1.phpnu[X = $x; if ($y === null) { $y = ParagonIE_Sodium_Core32_Curve25519::fe_0(); } $this->Y = $y; if ($z === null) { $z = ParagonIE_Sodium_Core32_Curve25519::fe_0(); } $this->Z = $z; if ($t === null) { $t = ParagonIE_Sodium_Core32_Curve25519::fe_0(); } $this->T = $t; } } PK!%  Core32/Curve25519/Ge/Precomp.phpnu[yplusx = $yplusx; if ($yminusx === null) { $yminusx = ParagonIE_Sodium_Core32_Curve25519::fe_0(); } $this->yminusx = $yminusx; if ($xy2d === null) { $xy2d = ParagonIE_Sodium_Core32_Curve25519::fe_0(); } $this->xy2d = $xy2d; } } PK!}M  Core32/Curve25519/Ge/Cached.phpnu[YplusX = $YplusX; if ($YminusX === null) { $YminusX = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->YminusX = $YminusX; if ($Z === null) { $Z = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->Z = $Z; if ($T2d === null) { $T2d = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->T2d = $T2d; } } PK!՗ilzzCore32/Curve25519/Fe.phpnu[ */ protected $container = array(); /** * @var int */ protected $size = 10; /** * @internal You should not use this directly from another application * * @param array $array * @param bool $save_indexes * @return self * @throws SodiumException * @throws TypeError */ public static function fromArray($array, $save_indexes = null) { $count = count($array); if ($save_indexes) { $keys = array_keys($array); } else { $keys = range(0, $count - 1); } $array = array_values($array); $obj = new ParagonIE_Sodium_Core32_Curve25519_Fe(); if ($save_indexes) { for ($i = 0; $i < $count; ++$i) { $array[$i]->overflow = 0; $obj->offsetSet($keys[$i], $array[$i]); } } else { for ($i = 0; $i < $count; ++$i) { if (!($array[$i] instanceof ParagonIE_Sodium_Core32_Int32)) { throw new TypeError('Expected ParagonIE_Sodium_Core32_Int32'); } $array[$i]->overflow = 0; $obj->offsetSet($i, $array[$i]); } } return $obj; } /** * @internal You should not use this directly from another application * * @param array $array * @param bool $save_indexes * @return self * @throws SodiumException * @throws TypeError */ public static function fromIntArray($array, $save_indexes = null) { $count = count($array); if ($save_indexes) { $keys = array_keys($array); } else { $keys = range(0, $count - 1); } $array = array_values($array); $set = array(); /** @var int $i */ /** @var int $v */ foreach ($array as $i => $v) { $set[$i] = ParagonIE_Sodium_Core32_Int32::fromInt($v); } $obj = new ParagonIE_Sodium_Core32_Curve25519_Fe(); if ($save_indexes) { for ($i = 0; $i < $count; ++$i) { $set[$i]->overflow = 0; $obj->offsetSet($keys[$i], $set[$i]); } } else { for ($i = 0; $i < $count; ++$i) { $set[$i]->overflow = 0; $obj->offsetSet($i, $set[$i]); } } return $obj; } /** * @internal You should not use this directly from another application * * @param mixed $offset * @param mixed $value * @return void * @throws SodiumException * @throws TypeError */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!($value instanceof ParagonIE_Sodium_Core32_Int32)) { throw new InvalidArgumentException('Expected an instance of ParagonIE_Sodium_Core32_Int32'); } if (is_null($offset)) { $this->container[] = $value; } else { ParagonIE_Sodium_Core32_Util::declareScalarType($offset, 'int', 1); $this->container[(int) $offset] = $value; } } /** * @internal You should not use this directly from another application * * @param mixed $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 mixed $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 mixed $offset * @return ParagonIE_Sodium_Core32_Int32 * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetGet($offset) { if (!isset($this->container[$offset])) { $this->container[(int) $offset] = new ParagonIE_Sodium_Core32_Int32(); } /** @var ParagonIE_Sodium_Core32_Int32 $get */ $get = $this->container[$offset]; return $get; } /** * @internal You should not use this directly from another application * * @return array */ public function __debugInfo() { if (empty($this->container)) { return array(); } $c = array( (int) ($this->container[0]->toInt()), (int) ($this->container[1]->toInt()), (int) ($this->container[2]->toInt()), (int) ($this->container[3]->toInt()), (int) ($this->container[4]->toInt()), (int) ($this->container[5]->toInt()), (int) ($this->container[6]->toInt()), (int) ($this->container[7]->toInt()), (int) ($this->container[8]->toInt()), (int) ($this->container[9]->toInt()) ); return array(implode(', ', $c)); } } PK!珉Core32/Curve25519/README.mdnu[# Curve25519 Data Structures These are PHP implementation of the [structs used in the ref10 curve25519 code](https://github.com/jedisct1/libsodium/blob/master/src/libsodium/include/sodium/private/curve25519_ref10.h). PK!Core32/Curve25519/H.phpnu[>>> Basically, int[32][8][3][10] */ protected static $base = array( array( array( array(25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605), array(-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378), array(-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546), ), array( array(-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303), array(-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081), array(26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697), ), array( array(15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024), array(16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574), array(30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357), ), array( array(-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540), array(23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397), array(7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325), ), array( array(10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380), array(4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306), array(19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942), ), array( array(-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777), array(-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737), array(-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652), ), array( array(5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766), array(-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701), array(28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300), ), array( array(14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726), array(-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955), array(27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425), ), ), array( array( array(-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171), array(27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510), array(17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660), ), array( array(-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639), array(29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963), array(5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950), ), array( array(-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568), array(12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335), array(25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628), ), array( array(-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007), array(-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772), array(-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653), ), array( array(2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567), array(13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686), array(21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372), ), array( array(-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887), array(-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954), array(-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953), ), array( array(24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833), array(-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532), array(-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876), ), array( array(2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268), array(33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214), array(1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038), ), ), array( array( array(6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800), array(4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645), array(-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664), ), array( array(1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933), array(-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182), array(-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222), ), array( array(-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991), array(20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880), array(9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092), ), array( array(-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295), array(19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788), array(8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553), ), array( array(-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026), array(11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347), array(-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033), ), array( array(-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395), array(-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278), array(1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890), ), array( array(32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995), array(-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596), array(-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891), ), array( array(31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060), array(11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608), array(-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606), ), ), array( array( array(7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389), array(-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016), array(-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341), ), array( array(-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505), array(14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553), array(-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655), ), array( array(15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220), array(12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631), array(-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099), ), array( array(26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556), array(14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749), array(236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930), ), array( array(1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391), array(5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253), array(20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066), ), array( array(24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958), array(-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082), array(-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383), ), array( array(-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521), array(-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807), array(23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948), ), array( array(9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134), array(-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455), array(27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629), ), ), array( array( array(-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069), array(-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746), array(24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919), ), array( array(11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837), array(8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906), array(-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771), ), array( array(-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817), array(10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098), array(10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409), ), array( array(-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504), array(-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727), array(28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420), ), array( array(-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003), array(-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605), array(-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384), ), array( array(-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701), array(-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683), array(29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708), ), array( array(-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563), array(-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260), array(-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387), ), array( array(-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672), array(23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686), array(-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665), ), ), array( array( array(11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182), array(-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277), array(14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628), ), array( array(-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474), array(-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539), array(-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822), ), array( array(-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970), array(19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756), array(-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508), ), array( array(-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683), array(-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655), array(-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158), ), array( array(-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125), array(-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839), array(-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664), ), array( array(27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294), array(-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899), array(-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070), ), array( array(3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294), array(-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949), array(-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083), ), array( array(31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420), array(-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940), array(29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396), ), ), array( array( array(-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567), array(20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127), array(-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294), ), array( array(-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887), array(22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964), array(16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195), ), array( array(9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244), array(24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999), array(-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762), ), array( array(-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274), array(-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236), array(-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605), ), array( array(-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761), array(-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884), array(-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482), ), array( array(-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638), array(-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490), array(-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170), ), array( array(5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736), array(10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124), array(-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392), ), array( array(8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029), array(6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048), array(28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958), ), ), array( array( array(24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593), array(26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071), array(-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692), ), array( array(11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687), array(-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441), array(-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001), ), array( array(-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460), array(-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007), array(-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762), ), array( array(15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005), array(-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674), array(4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035), ), array( array(7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590), array(-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957), array(-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812), ), array( array(33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740), array(-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122), array(-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158), ), array( array(8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885), array(26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140), array(19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857), ), array( array(801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155), array(19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260), array(19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483), ), ), array( array( array(-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677), array(32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815), array(22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751), ), array( array(-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203), array(-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208), array(1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230), ), array( array(16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850), array(-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389), array(-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968), ), array( array(-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689), array(14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880), array(5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304), ), array( array(30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632), array(-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412), array(20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566), ), array( array(-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038), array(-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232), array(-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943), ), array( array(17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856), array(23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738), array(15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971), ), array( array(-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718), array(-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697), array(-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883), ), ), array( array( array(5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912), array(-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358), array(3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849), ), array( array(29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307), array(-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977), array(-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335), ), array( array(-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644), array(-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616), array(-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735), ), array( array(-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099), array(29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341), array(-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336), ), array( array(-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646), array(31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425), array(-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388), ), array( array(-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743), array(-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822), array(-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462), ), array( array(18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985), array(9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702), array(-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797), ), array( array(21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293), array(27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100), array(19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688), ), ), array( array( array(12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186), array(2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610), array(-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707), ), array( array(7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220), array(915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025), array(32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044), ), array( array(32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992), array(-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027), array(21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197), ), array( array(8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901), array(31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952), array(19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878), ), array( array(-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390), array(32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730), array(2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730), ), array( array(-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180), array(-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272), array(-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715), ), array( array(-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970), array(-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772), array(-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865), ), array( array(15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750), array(20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373), array(32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348), ), ), array( array( array(9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144), array(-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195), array(5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086), ), array( array(-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684), array(-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518), array(-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233), ), array( array(-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793), array(-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794), array(580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435), ), array( array(23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921), array(13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518), array(2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563), ), array( array(14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278), array(-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024), array(4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030), ), array( array(10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783), array(27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717), array(6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844), ), array( array(14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333), array(16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048), array(22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760), ), array( array(-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760), array(-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757), array(-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112), ), ), array( array( array(-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468), array(3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184), array(10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289), ), array( array(15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066), array(24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882), array(13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226), ), array( array(16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101), array(29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279), array(-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811), ), array( array(27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709), array(20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714), array(-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121), ), array( array(9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464), array(12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847), array(13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400), ), array( array(4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414), array(-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158), array(17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045), ), array( array(-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415), array(-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459), array(-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079), ), array( array(21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412), array(-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743), array(-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836), ), ), array( array( array(12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022), array(18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429), array(-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065), ), array( array(30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861), array(10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000), array(-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101), ), array( array(32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815), array(29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642), array(10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966), ), array( array(25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574), array(-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742), array(-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689), ), array( array(12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020), array(-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772), array(3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982), ), array( array(-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953), array(-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218), array(-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265), ), array( array(29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073), array(-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325), array(-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798), ), array( array(-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870), array(-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863), array(-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927), ), ), array( array( array(-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267), array(-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663), array(22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862), ), array( array(-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673), array(15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943), array(15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020), ), array( array(-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238), array(11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064), array(14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795), ), array( array(15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052), array(-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904), array(29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531), ), array( array(-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979), array(-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841), array(10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431), ), array( array(10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324), array(-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940), array(10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320), ), array( array(-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184), array(14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114), array(30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878), ), array( array(12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784), array(-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091), array(-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585), ), ), array( array( array(-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208), array(10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864), array(17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661), ), array( array(7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233), array(26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212), array(-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525), ), array( array(-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068), array(9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397), array(-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988), ), array( array(5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889), array(32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038), array(14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697), ), array( array(20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875), array(-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905), array(-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656), ), array( array(11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818), array(27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714), array(10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203), ), array( array(20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931), array(-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024), array(-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084), ), array( array(-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204), array(20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817), array(27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667), ), ), array( array( array(11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504), array(-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768), array(-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255), ), array( array(6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790), array(1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438), array(-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333), ), array( array(17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971), array(31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905), array(29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409), ), array( array(12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409), array(6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499), array(-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363), ), array( array(28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664), array(-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324), array(-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940), ), array( array(13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990), array(-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914), array(-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290), ), array( array(24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257), array(-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433), array(-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236), ), array( array(-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045), array(11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093), array(-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347), ), ), array( array( array(-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191), array(-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507), array(-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906), ), array( array(3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018), array(-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109), array(-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926), ), array( array(-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528), array(8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625), array(-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286), ), array( array(2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033), array(27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866), array(21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896), ), array( array(30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075), array(26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347), array(-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437), ), array( array(-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165), array(-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588), array(-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193), ), array( array(-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017), array(-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883), array(21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961), ), array( array(8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043), array(29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663), array(-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362), ), ), array( array( array(-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860), array(2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466), array(-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063), ), array( array(-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997), array(-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295), array(-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369), ), array( array(9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385), array(18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109), array(2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906), ), array( array(4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424), array(-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185), array(7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962), ), array( array(-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325), array(10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593), array(696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404), ), array( array(-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644), array(17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801), array(26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804), ), array( array(-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884), array(-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577), array(-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849), ), array( array(32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473), array(-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644), array(-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319), ), ), array( array( array(-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599), array(-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768), array(-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084), ), array( array(-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328), array(-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369), array(20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920), ), array( array(12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815), array(-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025), array(-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397), ), array( array(-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448), array(6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981), array(30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165), ), array( array(32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501), array(17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073), array(-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861), ), array( array(14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845), array(-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211), array(18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870), ), array( array(10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096), array(33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803), array(-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168), ), array( array(30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965), array(-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505), array(18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598), ), ), array( array( array(5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782), array(5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900), array(-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479), ), array( array(-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208), array(8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232), array(17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719), ), array( array(16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271), array(-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326), array(-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132), ), array( array(14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300), array(8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570), array(15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670), ), array( array(-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994), array(-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913), array(31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317), ), array( array(-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730), array(842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096), array(-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078), ), array( array(-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411), array(-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905), array(-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654), ), array( array(-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870), array(-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498), array(12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579), ), ), array( array( array(14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677), array(10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647), array(-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743), ), array( array(-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468), array(21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375), array(-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155), ), array( array(6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725), array(-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612), array(-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943), ), array( array(-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944), array(30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928), array(9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406), ), array( array(22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139), array(-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963), array(-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693), ), array( array(1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734), array(-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680), array(-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410), ), array( array(-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931), array(-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654), array(22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710), ), array( array(29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180), array(-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684), array(-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895), ), ), array( array( array(22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501), array(-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413), array(6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880), ), array( array(-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874), array(22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962), array(-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899), ), array( array(21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152), array(9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063), array(7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080), ), array( array(-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146), array(-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183), array(-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133), ), array( array(-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421), array(-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622), array(-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197), ), array( array(2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663), array(31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753), array(4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755), ), array( array(-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862), array(-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118), array(26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171), ), array( array(15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380), array(16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824), array(28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270), ), ), array( array( array(-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438), array(-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584), array(-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562), ), array( array(30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471), array(18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610), array(19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269), ), array( array(-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650), array(14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369), array(19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461), ), array( array(30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462), array(-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793), array(-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218), ), array( array(-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226), array(18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019), array(-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037), ), array( array(31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171), array(-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132), array(-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841), ), array( array(21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181), array(-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210), array(-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040), ), array( array(3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935), array(24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105), array(-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814), ), ), array( array( array(793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852), array(5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581), array(-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646), ), array( array(10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844), array(10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025), array(27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453), ), array( array(-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068), array(4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192), array(-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921), ), array( array(-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259), array(-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426), array(-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072), ), array( array(-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305), array(13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832), array(28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943), ), array( array(-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011), array(24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447), array(17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494), ), array( array(-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245), array(-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859), array(28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915), ), array( array(16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707), array(10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848), array(-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224), ), ), array( array( array(-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391), array(15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215), array(-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101), ), array( array(23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713), array(21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849), array(-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930), ), array( array(-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940), array(-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031), array(-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404), ), array( array(-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243), array(-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116), array(-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525), ), array( array(-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509), array(-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883), array(15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865), ), array( array(-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660), array(4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273), array(-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138), ), array( array(-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560), array(-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135), array(2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941), ), array( array(-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739), array(18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756), array(-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819), ), ), array( array( array(-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347), array(-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028), array(21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075), ), array( array(16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799), array(-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609), array(-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817), ), array( array(-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989), array(-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523), array(4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278), ), array( array(31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045), array(19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377), array(24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480), ), array( array(17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016), array(510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426), array(18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525), ), array( array(13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396), array(9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080), array(12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892), ), array( array(15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275), array(11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074), array(20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140), ), array( array(-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717), array(-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101), array(24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127), ), ), array( array( array(-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632), array(-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415), array(-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160), ), array( array(31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876), array(22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625), array(-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478), ), array( array(27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164), array(26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595), array(-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248), ), array( array(-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858), array(15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193), array(8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184), ), array( array(-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942), array(-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635), array(21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948), ), array( array(11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935), array(-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415), array(-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416), ), array( array(-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018), array(4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778), array(366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659), ), array( array(-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385), array(18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503), array(476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329), ), ), array( array( array(20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056), array(-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838), array(24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948), ), array( array(-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691), array(-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118), array(-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517), ), array( array(-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269), array(-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904), array(-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589), ), array( array(-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193), array(-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910), array(-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930), ), array( array(-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667), array(25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481), array(-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876), ), array( array(22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640), array(-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278), array(-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112), ), array( array(26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272), array(17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012), array(-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221), ), array( array(30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046), array(13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345), array(-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310), ), ), array( array( array(19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937), array(31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636), array(-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008), ), array( array(-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429), array(-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576), array(31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066), ), array( array(-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490), array(-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104), array(33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053), ), array( array(31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275), array(-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511), array(22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095), ), array( array(-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439), array(23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939), array(-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424), ), array( array(2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310), array(3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608), array(-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079), ), array( array(-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101), array(21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418), array(18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576), ), array( array(30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356), array(9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996), array(-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099), ), ), array( array( array(-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728), array(-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658), array(-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242), ), array( array(-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001), array(-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766), array(18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373), ), array( array(26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458), array(-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628), array(-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657), ), array( array(-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062), array(25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616), array(31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014), ), array( array(24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383), array(-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814), array(-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718), ), array( array(30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417), array(2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222), array(33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444), ), array( array(-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597), array(23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970), array(1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799), ), array( array(-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647), array(13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511), array(-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032), ), ), array( array( array(9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834), array(-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461), array(29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062), ), array( array(-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516), array(-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547), array(-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240), ), array( array(-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038), array(-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741), array(16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103), ), array( array(-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747), array(-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323), array(31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016), ), array( array(-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373), array(15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228), array(-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141), ), array( array(16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399), array(11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831), array(-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376), ), array( array(-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313), array(-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958), array(-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577), ), array( array(-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743), array(29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684), array(-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476), ), ) ); /** * See: libsodium's crypto_core/curve25519/ref10/base2.h * * @var array>> basically int[8][3] */ protected static $base2 = array( array( array(25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605), array(-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378), array(-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546), ), array( array(15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024), array(16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574), array(30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357), ), array( array(10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380), array(4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306), array(19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942), ), array( array(5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766), array(-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701), array(28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300), ), array( array(-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877), array(-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951), array(4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784), ), array( array(-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436), array(25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918), array(23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877), ), array( array(-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800), array(-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305), array(-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300), ), array( array(-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876), array(-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619), array(-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683), ) ); /** * 37095705934669439343138083508754565189542113879843219016388785533085940283555 * * @var array */ protected static $d = array( -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116 ); /** * 2 * d = 16295367250680780974490674513165176452449235426866156013048779062215315747161 * * @var array */ protected static $d2 = array( -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 ); /** * sqrt(-1) * * @var array */ protected static $sqrtm1 = array( -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482 ); } PK!x)'Core32/HSalsa20.phpnu[ 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(); } } PK!w`22Core32/Poly1305.phpnu[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); } } PK!Hw=w=Core32/Ed25519.phpnu[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) && self::check_S_lt_L(self::substr($sig, 32, 32))) { throw new SodiumException('S < L - Invalid signature'); } if (self::small_order($sig)) { throw new SodiumException('Signature is on too small of an order'); } if ((self::chrToInt($sig[63]) & 224) !== 0) { throw new SodiumException('Invalid signature'); } $d = 0; for ($i = 0; $i < 32; ++$i) { $d |= self::chrToInt($pk[$i]); } if ($d === 0) { throw new SodiumException('All zero public key'); } /** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */ $orig = ParagonIE_Sodium_Compat::$fastMult; // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification. ParagonIE_Sodium_Compat::$fastMult = true; /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A */ $A = self::ge_frombytes_negate_vartime($pk); /** @var string $hDigest */ $hDigest = hash( 'sha512', self::substr($sig, 0, 32) . self::substr($pk, 0, 32) . $message, true ); /** @var string $h */ $h = self::sc_reduce($hDigest) . self::substr($hDigest, 32); /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $R */ $R = self::ge_double_scalarmult_vartime( $h, $A, self::substr($sig, 32) ); /** @var string $rcheck */ $rcheck = self::ge_tobytes($R); // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before. ParagonIE_Sodium_Compat::$fastMult = $orig; return self::verify_32($rcheck, self::substr($sig, 0, 32)); } /** * @internal You should not use this directly from another application * * @param string $S * @return bool * @throws SodiumException * @throws TypeError */ public static function check_S_lt_L($S) { if (self::strlen($S) < 32) { throw new SodiumException('Signature must be 32 bytes'); } static $L = array( 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 ); /** @var array $L */ $c = 0; $n = 1; $i = 32; do { --$i; $x = self::chrToInt($S[$i]); $c |= ( (($x - $L[$i]) >> 8) & $n ); $n &= ( (($x ^ $L[$i]) - 1) >> 8 ); } while ($i !== 0); return $c === 0; } /** * @param string $R * @return bool * @throws SodiumException * @throws TypeError */ public static function small_order($R) { static $blocklist = array( /* 0 (order 4) */ array( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), /* 1 (order 1) */ array( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), /* 2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */ array( 0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05 ), /* 55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */ array( 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a ), /* p-1 (order 2) */ array( 0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85 ), /* p (order 4) */ array( 0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa ), /* p+1 (order 1) */ array( 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f ), /* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */ array( 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f ), /* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */ array( 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f ), /* 2p-1 (order 2) */ array( 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ), /* 2p (order 4) */ array( 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ), /* 2p+1 (order 1) */ array( 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ) ); /** @var array> $blocklist */ $countBlocklist = count($blocklist); for ($i = 0; $i < $countBlocklist; ++$i) { $c = 0; for ($j = 0; $j < 32; ++$j) { $c |= self::chrToInt($R[$j]) ^ $blocklist[$i][$j]; } if ($c === 0) { return true; } } return false; } } PK!@(,,,Core32/Salsa20.phpnu[ 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 ) ); } } PK!F&bccCore32/XSalsa20.phpnu[> */ 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 */ $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 $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 $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; } } PK!Xv((Core32/ChaCha20/Ctx.phpnu[ */ 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; } } PK!Core32/ChaCha20/IetfCtx.phpnu[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)); } } PK!]D Core32/XChaCha20.phpnu[ - 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 * @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 $a * @param array $b * @param int $baseLog2 * @return array */ public function multiplyLong(array $a, array $b, $baseLog2 = 16) { $a_l = count($a); $b_l = count($b); /** @var array $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 $limbs */ $limbs =& $return->limbs; /** @var array $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 $limbs */ $limbs =& $return->limbs; /** @var array $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 */ 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 ''; } } } PK!21Core32/HChaCha20.phpnu[toReverseString() . $x1->toReverseString() . $x2->toReverseString() . $x3->toReverseString() . $x12->toReverseString() . $x13->toReverseString() . $x14->toReverseString() . $x15->toReverseString(); } } PK!["+"+Core32/X25519.phpnu[toInt(); $f1 = (int) $f[1]->toInt(); $f2 = (int) $f[2]->toInt(); $f3 = (int) $f[3]->toInt(); $f4 = (int) $f[4]->toInt(); $f5 = (int) $f[5]->toInt(); $f6 = (int) $f[6]->toInt(); $f7 = (int) $f[7]->toInt(); $f8 = (int) $f[8]->toInt(); $f9 = (int) $f[9]->toInt(); $g0 = (int) $g[0]->toInt(); $g1 = (int) $g[1]->toInt(); $g2 = (int) $g[2]->toInt(); $g3 = (int) $g[3]->toInt(); $g4 = (int) $g[4]->toInt(); $g5 = (int) $g[5]->toInt(); $g6 = (int) $g[6]->toInt(); $g7 = (int) $g[7]->toInt(); $g8 = (int) $g[8]->toInt(); $g9 = (int) $g[9]->toInt(); $b = -$b; /** @var int $x0 */ $x0 = ($f0 ^ $g0) & $b; /** @var int $x1 */ $x1 = ($f1 ^ $g1) & $b; /** @var int $x2 */ $x2 = ($f2 ^ $g2) & $b; /** @var int $x3 */ $x3 = ($f3 ^ $g3) & $b; /** @var int $x4 */ $x4 = ($f4 ^ $g4) & $b; /** @var int $x5 */ $x5 = ($f5 ^ $g5) & $b; /** @var int $x6 */ $x6 = ($f6 ^ $g6) & $b; /** @var int $x7 */ $x7 = ($f7 ^ $g7) & $b; /** @var int $x8 */ $x8 = ($f8 ^ $g8) & $b; /** @var int $x9 */ $x9 = ($f9 ^ $g9) & $b; $f[0] = ParagonIE_Sodium_Core32_Int32::fromInt($f0 ^ $x0); $f[1] = ParagonIE_Sodium_Core32_Int32::fromInt($f1 ^ $x1); $f[2] = ParagonIE_Sodium_Core32_Int32::fromInt($f2 ^ $x2); $f[3] = ParagonIE_Sodium_Core32_Int32::fromInt($f3 ^ $x3); $f[4] = ParagonIE_Sodium_Core32_Int32::fromInt($f4 ^ $x4); $f[5] = ParagonIE_Sodium_Core32_Int32::fromInt($f5 ^ $x5); $f[6] = ParagonIE_Sodium_Core32_Int32::fromInt($f6 ^ $x6); $f[7] = ParagonIE_Sodium_Core32_Int32::fromInt($f7 ^ $x7); $f[8] = ParagonIE_Sodium_Core32_Int32::fromInt($f8 ^ $x8); $f[9] = ParagonIE_Sodium_Core32_Int32::fromInt($f9 ^ $x9); $g[0] = ParagonIE_Sodium_Core32_Int32::fromInt($g0 ^ $x0); $g[1] = ParagonIE_Sodium_Core32_Int32::fromInt($g1 ^ $x1); $g[2] = ParagonIE_Sodium_Core32_Int32::fromInt($g2 ^ $x2); $g[3] = ParagonIE_Sodium_Core32_Int32::fromInt($g3 ^ $x3); $g[4] = ParagonIE_Sodium_Core32_Int32::fromInt($g4 ^ $x4); $g[5] = ParagonIE_Sodium_Core32_Int32::fromInt($g5 ^ $x5); $g[6] = ParagonIE_Sodium_Core32_Int32::fromInt($g6 ^ $x6); $g[7] = ParagonIE_Sodium_Core32_Int32::fromInt($g7 ^ $x7); $g[8] = ParagonIE_Sodium_Core32_Int32::fromInt($g8 ^ $x8); $g[9] = ParagonIE_Sodium_Core32_Int32::fromInt($g9 ^ $x9); } /** * @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 MixedAssignment * @psalm-suppress MixedMethodCall */ public static function fe_mul121666(ParagonIE_Sodium_Core32_Curve25519_Fe $f) { /** @var array $h */ $h = array(); for ($i = 0; $i < 10; ++$i) { $h[$i] = $f[$i]->toInt64()->mulInt(121666, 17); } $carry9 = $h[9]->addInt(1 << 24)->shiftRight(25); $h[0] = $h[0]->addInt64($carry9->mulInt(19, 5)); $h[9] = $h[9]->subInt64($carry9->shiftLeft(25)); $carry1 = $h[1]->addInt(1 << 24)->shiftRight(25); $h[2] = $h[2]->addInt64($carry1); $h[1] = $h[1]->subInt64($carry1->shiftLeft(25)); $carry3 = $h[3]->addInt(1 << 24)->shiftRight(25); $h[4] = $h[4]->addInt64($carry3); $h[3] = $h[3]->subInt64($carry3->shiftLeft(25)); $carry5 = $h[5]->addInt(1 << 24)->shiftRight(25); $h[6] = $h[6]->addInt64($carry5); $h[5] = $h[5]->subInt64($carry5->shiftLeft(25)); $carry7 = $h[7]->addInt(1 << 24)->shiftRight(25); $h[8] = $h[8]->addInt64($carry7); $h[7] = $h[7]->subInt64($carry7->shiftLeft(25)); $carry0 = $h[0]->addInt(1 << 25)->shiftRight(26); $h[1] = $h[1]->addInt64($carry0); $h[0] = $h[0]->subInt64($carry0->shiftLeft(26)); $carry2 = $h[2]->addInt(1 << 25)->shiftRight(26); $h[3] = $h[3]->addInt64($carry2); $h[2] = $h[2]->subInt64($carry2->shiftLeft(26)); $carry4 = $h[4]->addInt(1 << 25)->shiftRight(26); $h[5] = $h[5]->addInt64($carry4); $h[4] = $h[4]->subInt64($carry4->shiftLeft(26)); $carry6 = $h[6]->addInt(1 << 25)->shiftRight(26); $h[7] = $h[7]->addInt64($carry6); $h[6] = $h[6]->subInt64($carry6->shiftLeft(26)); $carry8 = $h[8]->addInt(1 << 25)->shiftRight(26); $h[9] = $h[9]->addInt64($carry8); $h[8] = $h[8]->subInt64($carry8->shiftLeft(26)); for ($i = 0; $i < 10; ++$i) { $h[$i] = $h[$i]->toInt32(); } /** @var array $h2 */ $h2 = $h; return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h2); } /** * @internal You should not use this directly from another application * * Inline comments preceded by # are from libsodium's ref10 code. * * @param string $n * @param string $p * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_scalarmult_curve25519_ref10($n, $p) { # for (i = 0;i < 32;++i) e[i] = n[i]; $e = '' . $n; # e[0] &= 248; $e[0] = self::intToChr( self::chrToInt($e[0]) & 248 ); # e[31] &= 127; # e[31] |= 64; $e[31] = self::intToChr( (self::chrToInt($e[31]) & 127) | 64 ); # fe_frombytes(x1,p); $x1 = self::fe_frombytes($p); # fe_1(x2); $x2 = self::fe_1(); # fe_0(z2); $z2 = self::fe_0(); # fe_copy(x3,x1); $x3 = self::fe_copy($x1); # fe_1(z3); $z3 = self::fe_1(); # swap = 0; /** @var int $swap */ $swap = 0; # for (pos = 254;pos >= 0;--pos) { for ($pos = 254; $pos >= 0; --$pos) { # b = e[pos / 8] >> (pos & 7); /** @var int $b */ $b = self::chrToInt( $e[(int) floor($pos / 8)] ) >> ($pos & 7); # b &= 1; $b &= 1; # swap ^= b; $swap ^= $b; # fe_cswap(x2,x3,swap); self::fe_cswap($x2, $x3, $swap); # fe_cswap(z2,z3,swap); self::fe_cswap($z2, $z3, $swap); # swap = b; /** @var int $swap */ $swap = $b; # fe_sub(tmp0,x3,z3); $tmp0 = self::fe_sub($x3, $z3); # fe_sub(tmp1,x2,z2); $tmp1 = self::fe_sub($x2, $z2); # fe_add(x2,x2,z2); $x2 = self::fe_add($x2, $z2); # fe_add(z2,x3,z3); $z2 = self::fe_add($x3, $z3); # fe_mul(z3,tmp0,x2); $z3 = self::fe_mul($tmp0, $x2); # fe_mul(z2,z2,tmp1); $z2 = self::fe_mul($z2, $tmp1); # fe_sq(tmp0,tmp1); $tmp0 = self::fe_sq($tmp1); # fe_sq(tmp1,x2); $tmp1 = self::fe_sq($x2); # fe_add(x3,z3,z2); $x3 = self::fe_add($z3, $z2); # fe_sub(z2,z3,z2); $z2 = self::fe_sub($z3, $z2); # fe_mul(x2,tmp1,tmp0); $x2 = self::fe_mul($tmp1, $tmp0); # fe_sub(tmp1,tmp1,tmp0); $tmp1 = self::fe_sub($tmp1, $tmp0); # fe_sq(z2,z2); $z2 = self::fe_sq($z2); # fe_mul121666(z3,tmp1); $z3 = self::fe_mul121666($tmp1); # fe_sq(x3,x3); $x3 = self::fe_sq($x3); # fe_add(tmp0,tmp0,z3); $tmp0 = self::fe_add($tmp0, $z3); # fe_mul(z3,x1,z2); $z3 = self::fe_mul($x1, $z2); # fe_mul(z2,tmp1,tmp0); $z2 = self::fe_mul($tmp1, $tmp0); } # fe_cswap(x2,x3,swap); self::fe_cswap($x2, $x3, $swap); # fe_cswap(z2,z3,swap); self::fe_cswap($z2, $z3, $swap); # fe_invert(z2,z2); $z2 = self::fe_invert($z2); # fe_mul(x2,x2,z2); $x2 = self::fe_mul($x2, $z2); # fe_tobytes(q,x2); return (string) self::fe_tobytes($x2); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsY * @param ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsZ * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError */ public static function edwards_to_montgomery( ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsY, ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsZ ) { $tempX = self::fe_add($edwardsZ, $edwardsY); $tempZ = self::fe_sub($edwardsZ, $edwardsY); $tempZ = self::fe_invert($tempZ); return self::fe_mul($tempX, $tempZ); } /** * @internal You should not use this directly from another application * * @param string $n * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_scalarmult_curve25519_ref10_base($n) { # for (i = 0;i < 32;++i) e[i] = n[i]; $e = '' . $n; # e[0] &= 248; $e[0] = self::intToChr( self::chrToInt($e[0]) & 248 ); # e[31] &= 127; # e[31] |= 64; $e[31] = self::intToChr( (self::chrToInt($e[31]) & 127) | 64 ); $A = self::ge_scalarmult_base($e); if ( !($A->Y instanceof ParagonIE_Sodium_Core32_Curve25519_Fe) || !($A->Z instanceof ParagonIE_Sodium_Core32_Curve25519_Fe) ) { throw new TypeError('Null points encountered'); } $pk = self::edwards_to_montgomery($A->Y, $A->Z); return self::fe_tobytes($pk); } } PK!ڨ~TCore32/Util.phpnu[ * @throws SodiumException * @throws TypeError */ protected static function quarterRound( ParagonIE_Sodium_Core32_Int32 $a, ParagonIE_Sodium_Core32_Int32 $b, ParagonIE_Sodium_Core32_Int32 $c, ParagonIE_Sodium_Core32_Int32 $d ) { /** @var ParagonIE_Sodium_Core32_Int32 $a */ /** @var ParagonIE_Sodium_Core32_Int32 $b */ /** @var ParagonIE_Sodium_Core32_Int32 $c */ /** @var ParagonIE_Sodium_Core32_Int32 $d */ # a = PLUS(a,b); d = ROTATE(XOR(d,a),16); $a = $a->addInt32($b); $d = $d->xorInt32($a)->rotateLeft(16); # c = PLUS(c,d); b = ROTATE(XOR(b,c),12); $c = $c->addInt32($d); $b = $b->xorInt32($c)->rotateLeft(12); # a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); $a = $a->addInt32($b); $d = $d->xorInt32($a)->rotateLeft(8); # c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); $c = $c->addInt32($d); $b = $b->xorInt32($c)->rotateLeft(7); return array($a, $b, $c, $d); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_ChaCha20_Ctx $ctx * @param string $message * * @return string * @throws SodiumException * @throws TypeError */ public static function encryptBytes( ParagonIE_Sodium_Core32_ChaCha20_Ctx $ctx, $message = '' ) { $bytes = self::strlen($message); /** @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 */ /* j0 = ctx->input[0]; j1 = ctx->input[1]; j2 = ctx->input[2]; j3 = ctx->input[3]; j4 = ctx->input[4]; j5 = ctx->input[5]; j6 = ctx->input[6]; j7 = ctx->input[7]; j8 = ctx->input[8]; j9 = ctx->input[9]; j10 = ctx->input[10]; j11 = ctx->input[11]; j12 = ctx->input[12]; j13 = ctx->input[13]; j14 = ctx->input[14]; j15 = ctx->input[15]; */ /** @var ParagonIE_Sodium_Core32_Int32 $j0 */ $j0 = $ctx[0]; /** @var ParagonIE_Sodium_Core32_Int32 $j1 */ $j1 = $ctx[1]; /** @var ParagonIE_Sodium_Core32_Int32 $j2 */ $j2 = $ctx[2]; /** @var ParagonIE_Sodium_Core32_Int32 $j3 */ $j3 = $ctx[3]; /** @var ParagonIE_Sodium_Core32_Int32 $j4 */ $j4 = $ctx[4]; /** @var ParagonIE_Sodium_Core32_Int32 $j5 */ $j5 = $ctx[5]; /** @var ParagonIE_Sodium_Core32_Int32 $j6 */ $j6 = $ctx[6]; /** @var ParagonIE_Sodium_Core32_Int32 $j7 */ $j7 = $ctx[7]; /** @var ParagonIE_Sodium_Core32_Int32 $j8 */ $j8 = $ctx[8]; /** @var ParagonIE_Sodium_Core32_Int32 $j9 */ $j9 = $ctx[9]; /** @var ParagonIE_Sodium_Core32_Int32 $j10 */ $j10 = $ctx[10]; /** @var ParagonIE_Sodium_Core32_Int32 $j11 */ $j11 = $ctx[11]; /** @var ParagonIE_Sodium_Core32_Int32 $j12 */ $j12 = $ctx[12]; /** @var ParagonIE_Sodium_Core32_Int32 $j13 */ $j13 = $ctx[13]; /** @var ParagonIE_Sodium_Core32_Int32 $j14 */ $j14 = $ctx[14]; /** @var ParagonIE_Sodium_Core32_Int32 $j15 */ $j15 = $ctx[15]; $c = ''; for (;;) { if ($bytes < 64) { $message .= str_repeat("\x00", 64 - $bytes); } $x0 = clone $j0; $x1 = clone $j1; $x2 = clone $j2; $x3 = clone $j3; $x4 = clone $j4; $x5 = clone $j5; $x6 = clone $j6; $x7 = clone $j7; $x8 = clone $j8; $x9 = clone $j9; $x10 = clone $j10; $x11 = clone $j11; $x12 = clone $j12; $x13 = clone $j13; $x14 = clone $j14; $x15 = clone $j15; # for (i = 20; i > 0; i -= 2) { for ($i = 20; $i > 0; $i -= 2) { # 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); } /* x0 = PLUS(x0, j0); x1 = PLUS(x1, j1); x2 = PLUS(x2, j2); x3 = PLUS(x3, j3); x4 = PLUS(x4, j4); x5 = PLUS(x5, j5); x6 = PLUS(x6, j6); x7 = PLUS(x7, j7); x8 = PLUS(x8, j8); x9 = PLUS(x9, j9); x10 = PLUS(x10, j10); x11 = PLUS(x11, j11); x12 = PLUS(x12, j12); x13 = PLUS(x13, j13); x14 = PLUS(x14, j14); x15 = PLUS(x15, j15); */ $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); /* x0 = XOR(x0, LOAD32_LE(m + 0)); x1 = XOR(x1, LOAD32_LE(m + 4)); x2 = XOR(x2, LOAD32_LE(m + 8)); x3 = XOR(x3, LOAD32_LE(m + 12)); x4 = XOR(x4, LOAD32_LE(m + 16)); x5 = XOR(x5, LOAD32_LE(m + 20)); x6 = XOR(x6, LOAD32_LE(m + 24)); x7 = XOR(x7, LOAD32_LE(m + 28)); x8 = XOR(x8, LOAD32_LE(m + 32)); x9 = XOR(x9, LOAD32_LE(m + 36)); x10 = XOR(x10, LOAD32_LE(m + 40)); x11 = XOR(x11, LOAD32_LE(m + 44)); x12 = XOR(x12, LOAD32_LE(m + 48)); x13 = XOR(x13, LOAD32_LE(m + 52)); x14 = XOR(x14, LOAD32_LE(m + 56)); x15 = XOR(x15, LOAD32_LE(m + 60)); */ $x0 = $x0->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 0, 4))); $x1 = $x1->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 4, 4))); $x2 = $x2->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 8, 4))); $x3 = $x3->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 12, 4))); $x4 = $x4->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 16, 4))); $x5 = $x5->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 20, 4))); $x6 = $x6->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 24, 4))); $x7 = $x7->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 28, 4))); $x8 = $x8->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 32, 4))); $x9 = $x9->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 36, 4))); $x10 = $x10->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 40, 4))); $x11 = $x11->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 44, 4))); $x12 = $x12->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 48, 4))); $x13 = $x13->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 52, 4))); $x14 = $x14->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 56, 4))); $x15 = $x15->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 60, 4))); /* j12 = PLUSONE(j12); if (!j12) { j13 = PLUSONE(j13); } */ /** @var ParagonIE_Sodium_Core32_Int32 $j12 */ $j12 = $j12->addInt(1); if ($j12->limbs[0] === 0 && $j12->limbs[1] === 0) { $j13 = $j13->addInt(1); } /* STORE32_LE(c + 0, x0); STORE32_LE(c + 4, x1); STORE32_LE(c + 8, x2); STORE32_LE(c + 12, x3); STORE32_LE(c + 16, x4); STORE32_LE(c + 20, x5); STORE32_LE(c + 24, x6); STORE32_LE(c + 28, x7); STORE32_LE(c + 32, x8); STORE32_LE(c + 36, x9); STORE32_LE(c + 40, x10); STORE32_LE(c + 44, x11); STORE32_LE(c + 48, x12); STORE32_LE(c + 52, x13); STORE32_LE(c + 56, x14); STORE32_LE(c + 60, x15); */ $block = $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(); /* Partial block */ if ($bytes < 64) { $c .= self::substr($block, 0, $bytes); break; } /* Full block */ $c .= $block; $bytes -= 64; if ($bytes <= 0) { break; } $message = self::substr($message, 64); } /* end for(;;) loop */ $ctx[12] = $j12; $ctx[13] = $j13; return $c; } /** * @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 = '') { return self::encryptBytes( new ParagonIE_Sodium_Core32_ChaCha20_Ctx($key, $nonce), str_repeat("\x00", $len) ); } /** * @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 ietfStream($len, $nonce = '', $key = '') { return self::encryptBytes( new ParagonIE_Sodium_Core32_ChaCha20_IetfCtx($key, $nonce), 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 ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '') { return self::encryptBytes( new ParagonIE_Sodium_Core32_ChaCha20_IetfCtx($key, $nonce, $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 streamXorIc($message, $nonce = '', $key = '', $ic = '') { return self::encryptBytes( new ParagonIE_Sodium_Core32_ChaCha20_Ctx($key, $nonce, $ic), $message ); } } PK!1 Compat.phpnu[>= 8; } $val = ParagonIE_Sodium_Core_Util::intArrayToString($A); } /** * @param string $encoded * @param int $variant * @param string $ignore * @return string * @throws SodiumException */ public static function base642bin( #[\SensitiveParameter] $encoded, $variant, $ignore = '' ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($encoded, 'string', 1); /** @var string $encoded */ $encoded = (string) $encoded; if (ParagonIE_Sodium_Core_Util::strlen($encoded) === 0) { return ''; } // Just strip before decoding if (!empty($ignore)) { $encoded = str_replace($ignore, '', $encoded); } try { switch ($variant) { case self::BASE64_VARIANT_ORIGINAL: return ParagonIE_Sodium_Core_Base64_Original::decode($encoded, true); case self::BASE64_VARIANT_ORIGINAL_NO_PADDING: return ParagonIE_Sodium_Core_Base64_Original::decode($encoded, false); case self::BASE64_VARIANT_URLSAFE: return ParagonIE_Sodium_Core_Base64_UrlSafe::decode($encoded, true); case self::BASE64_VARIANT_URLSAFE_NO_PADDING: return ParagonIE_Sodium_Core_Base64_UrlSafe::decode($encoded, false); default: throw new SodiumException('invalid base64 variant identifier'); } } catch (Exception $ex) { if ($ex instanceof SodiumException) { throw $ex; } throw new SodiumException('invalid base64 string'); } } /** * @param string $decoded * @param int $variant * @return string * @throws SodiumException */ public static function bin2base64( #[\SensitiveParameter] $decoded, $variant ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($decoded, 'string', 1); /** @var string $decoded */ $decoded = (string) $decoded; if (ParagonIE_Sodium_Core_Util::strlen($decoded) === 0) { return ''; } switch ($variant) { case self::BASE64_VARIANT_ORIGINAL: return ParagonIE_Sodium_Core_Base64_Original::encode($decoded); case self::BASE64_VARIANT_ORIGINAL_NO_PADDING: return ParagonIE_Sodium_Core_Base64_Original::encodeUnpadded($decoded); case self::BASE64_VARIANT_URLSAFE: return ParagonIE_Sodium_Core_Base64_UrlSafe::encode($decoded); case self::BASE64_VARIANT_URLSAFE_NO_PADDING: return ParagonIE_Sodium_Core_Base64_UrlSafe::encodeUnpadded($decoded); default: throw new SodiumException('invalid base64 variant identifier'); } } /** * Cache-timing-safe implementation of bin2hex(). * * @param string $string A string (probably raw binary) * @return string A hexadecimal-encoded string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function bin2hex( #[\SensitiveParameter] $string ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($string, 'string', 1); if (self::useNewSodiumAPI()) { return (string) sodium_bin2hex($string); } if (self::use_fallback('bin2hex')) { return (string) call_user_func('\\Sodium\\bin2hex', $string); } return ParagonIE_Sodium_Core_Util::bin2hex($string); } /** * Compare two strings, in constant-time. * Compared to memcmp(), compare() is more useful for sorting. * * @param string $left The left operand; must be a string * @param string $right The right operand; must be a string * @return int If < 0 if the left operand is less than the right * If = 0 if both strings are equal * If > 0 if the right operand is less than the left * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function compare( #[\SensitiveParameter] $left, #[\SensitiveParameter] $right ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($left, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($right, 'string', 2); if (self::useNewSodiumAPI()) { return (int) sodium_compare($left, $right); } if (self::use_fallback('compare')) { return (int) call_user_func('\\Sodium\\compare', $left, $right); } return ParagonIE_Sodium_Core_Util::compare($left, $right); } /** * Authenticated Encryption with Associated Data: Decryption * * Algorithm: * AEGIS-128L * * @param string $ciphertext Encrypted message (with MAC appended) * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 32 bytes * @param string $key Encryption key * * @return string The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_aead_aegis128l_decrypt( $ciphertext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AEGIS128L_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS_128L_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AEGIS128L_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long'); } $ct_length = ParagonIE_Sodium_Core_Util::strlen($ciphertext); if ($ct_length < self::CRYPTO_AEAD_AEGIS128L_ABYTES) { throw new SodiumException('Message must be at least CRYPTO_AEAD_AEGIS128L_ABYTES long'); } $ct = ParagonIE_Sodium_Core_Util::substr( $ciphertext, 0, $ct_length - self::CRYPTO_AEAD_AEGIS128L_ABYTES ); $tag = ParagonIE_Sodium_Core_Util::substr( $ciphertext, $ct_length - self::CRYPTO_AEAD_AEGIS128L_ABYTES, self::CRYPTO_AEAD_AEGIS128L_ABYTES ); return ParagonIE_Sodium_Core_AEGIS128L::decrypt($ct, $tag, $assocData, $key, $nonce); } /** * Authenticated Encryption with Associated Data: Encryption * * Algorithm: * AEGIS-128L * * @param string $plaintext Message to be encrypted * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 32 bytes * @param string $key Encryption key * * @return string Ciphertext with 32-byte authentication tag appended * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_aegis128l_encrypt( #[\SensitiveParameter] $plaintext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AEGIS128L_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AEGIS128L_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long'); } list($ct, $tag) = ParagonIE_Sodium_Core_AEGIS128L::encrypt($plaintext, $assocData, $key, $nonce); return $ct . $tag; } /** * Return a secure random key for use with the AEGIS-128L * symmetric AEAD interface. * * @return string * @throws Exception * @throws Error */ public static function crypto_aead_aegis128l_keygen() { return random_bytes(self::CRYPTO_AEAD_AEGIS128L_KEYBYTES); } /** * Authenticated Encryption with Associated Data: Decryption * * Algorithm: * AEGIS-256 * * @param string $ciphertext Encrypted message (with MAC appended) * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 32 bytes * @param string $key Encryption key * * @return string The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_aead_aegis256_decrypt( $ciphertext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AEGIS256_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS256_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AEGIS256_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_AEGIS256_KEYBYTES long'); } $ct_length = ParagonIE_Sodium_Core_Util::strlen($ciphertext); if ($ct_length < self::CRYPTO_AEAD_AEGIS256_ABYTES) { throw new SodiumException('Message must be at least CRYPTO_AEAD_AEGIS256_ABYTES long'); } $ct = ParagonIE_Sodium_Core_Util::substr( $ciphertext, 0, $ct_length - self::CRYPTO_AEAD_AEGIS256_ABYTES ); $tag = ParagonIE_Sodium_Core_Util::substr( $ciphertext, $ct_length - self::CRYPTO_AEAD_AEGIS256_ABYTES, self::CRYPTO_AEAD_AEGIS256_ABYTES ); return ParagonIE_Sodium_Core_AEGIS256::decrypt($ct, $tag, $assocData, $key, $nonce); } /** * Authenticated Encryption with Associated Data: Encryption * * Algorithm: * AEGIS-256 * * @param string $plaintext Message to be encrypted * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 32 bytes * @param string $key Encryption key * * @return string Ciphertext with 32-byte authentication tag appended * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_aegis256_encrypt( #[\SensitiveParameter] $plaintext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AEGIS256_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AEGIS256_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long'); } list($ct, $tag) = ParagonIE_Sodium_Core_AEGIS256::encrypt($plaintext, $assocData, $key, $nonce); return $ct . $tag; } /** * Return a secure random key for use with the AEGIS-256 * symmetric AEAD interface. * * @return string * @throws Exception * @throws Error */ public static function crypto_aead_aegis256_keygen() { return random_bytes(self::CRYPTO_AEAD_AEGIS256_KEYBYTES); } /** * Is AES-256-GCM even available to use? * * @return bool * @psalm-suppress UndefinedFunction * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_aead_aes256gcm_is_available() { if (self::useNewSodiumAPI()) { return sodium_crypto_aead_aes256gcm_is_available(); } if (self::use_fallback('crypto_aead_aes256gcm_is_available')) { return call_user_func('\\Sodium\\crypto_aead_aes256gcm_is_available'); } if (PHP_VERSION_ID < 70100) { // OpenSSL doesn't support AEAD before 7.1.0 return false; } if (!is_callable('openssl_encrypt') || !is_callable('openssl_decrypt')) { // OpenSSL isn't installed return false; } return (bool) in_array('aes-256-gcm', openssl_get_cipher_methods()); } /** * Authenticated Encryption with Associated Data: Decryption * * Algorithm: * AES-256-GCM * * This mode uses a 64-bit random nonce with a 64-bit counter. * IETF mode uses a 96-bit random nonce with a 32-bit counter. * * @param string $ciphertext Encrypted message (with Poly1305 MAC appended) * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * * @return string|bool The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_aead_aes256gcm_decrypt( $ciphertext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { if (!self::crypto_aead_aes256gcm_is_available()) { throw new SodiumException('AES-256-GCM is not available'); } ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AES256GCM_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_AES256GCM_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AES256GCM_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_AES256GCM_KEYBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_AEAD_AES256GCM_ABYTES) { throw new SodiumException('Message must be at least CRYPTO_AEAD_AES256GCM_ABYTES long'); } if (!is_callable('openssl_decrypt')) { throw new SodiumException('The OpenSSL extension is not installed, or openssl_decrypt() is not available'); } /** @var string $ctext */ $ctext = ParagonIE_Sodium_Core_Util::substr($ciphertext, 0, -self::CRYPTO_AEAD_AES256GCM_ABYTES); /** @var string $authTag */ $authTag = ParagonIE_Sodium_Core_Util::substr($ciphertext, -self::CRYPTO_AEAD_AES256GCM_ABYTES, 16); return openssl_decrypt( $ctext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $nonce, $authTag, $assocData ); } /** * Authenticated Encryption with Associated Data: Encryption * * Algorithm: * AES-256-GCM * * @param string $plaintext Message to be encrypted * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * * @return string Ciphertext with a 16-byte GCM message * authentication code appended * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_aes256gcm_encrypt( #[\SensitiveParameter] $plaintext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { if (!self::crypto_aead_aes256gcm_is_available()) { throw new SodiumException('AES-256-GCM is not available'); } ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AES256GCM_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_AES256GCM_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AES256GCM_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_AES256GCM_KEYBYTES long'); } if (!is_callable('openssl_encrypt')) { throw new SodiumException('The OpenSSL extension is not installed, or openssl_encrypt() is not available'); } $authTag = ''; $ciphertext = openssl_encrypt( $plaintext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $nonce, $authTag, $assocData ); return $ciphertext . $authTag; } /** * Return a secure random key for use with the AES-256-GCM * symmetric AEAD interface. * * @return string * @throws Exception * @throws Error */ public static function crypto_aead_aes256gcm_keygen() { return random_bytes(self::CRYPTO_AEAD_AES256GCM_KEYBYTES); } /** * Authenticated Encryption with Associated Data: Decryption * * Algorithm: * ChaCha20-Poly1305 * * This mode uses a 64-bit random nonce with a 64-bit counter. * IETF mode uses a 96-bit random nonce with a 32-bit counter. * * @param string $ciphertext Encrypted message (with Poly1305 MAC appended) * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * * @return string The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_aead_chacha20poly1305_decrypt( $ciphertext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_AEAD_CHACHA20POLY1305_ABYTES) { throw new SodiumException('Message must be at least CRYPTO_AEAD_CHACHA20POLY1305_ABYTES long'); } if (self::useNewSodiumAPI()) { /** * @psalm-suppress InvalidReturnStatement * @psalm-suppress FalsableReturnStatement */ return sodium_crypto_aead_chacha20poly1305_decrypt( $ciphertext, $assocData, $nonce, $key ); } if (self::use_fallback('crypto_aead_chacha20poly1305_decrypt')) { return call_user_func( '\\Sodium\\crypto_aead_chacha20poly1305_decrypt', $ciphertext, $assocData, $nonce, $key ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::aead_chacha20poly1305_decrypt( $ciphertext, $assocData, $nonce, $key ); } return ParagonIE_Sodium_Crypto::aead_chacha20poly1305_decrypt( $ciphertext, $assocData, $nonce, $key ); } /** * Authenticated Encryption with Associated Data * * Algorithm: * ChaCha20-Poly1305 * * This mode uses a 64-bit random nonce with a 64-bit counter. * IETF mode uses a 96-bit random nonce with a 32-bit counter. * * @param string $plaintext Message to be encrypted * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * * @return string Ciphertext with a 16-byte Poly1305 message * authentication code appended * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_chacha20poly1305_encrypt( #[\SensitiveParameter] $plaintext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_aead_chacha20poly1305_encrypt( $plaintext, $assocData, $nonce, $key ); } if (self::use_fallback('crypto_aead_chacha20poly1305_encrypt')) { return (string) call_user_func( '\\Sodium\\crypto_aead_chacha20poly1305_encrypt', $plaintext, $assocData, $nonce, $key ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::aead_chacha20poly1305_encrypt( $plaintext, $assocData, $nonce, $key ); } return ParagonIE_Sodium_Crypto::aead_chacha20poly1305_encrypt( $plaintext, $assocData, $nonce, $key ); } /** * Authenticated Encryption with Associated Data: Decryption * * Algorithm: * ChaCha20-Poly1305 * * IETF mode uses a 96-bit random nonce with a 32-bit counter. * Regular mode uses a 64-bit random nonce with a 64-bit counter. * * @param string $ciphertext Encrypted message (with Poly1305 MAC appended) * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 12 bytes * @param string $key Encryption key * * @return string The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_aead_chacha20poly1305_ietf_decrypt( $ciphertext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_AEAD_CHACHA20POLY1305_ABYTES) { throw new SodiumException('Message must be at least CRYPTO_AEAD_CHACHA20POLY1305_ABYTES long'); } if (self::useNewSodiumAPI()) { /** * @psalm-suppress InvalidReturnStatement * @psalm-suppress FalsableReturnStatement */ return sodium_crypto_aead_chacha20poly1305_ietf_decrypt( $ciphertext, $assocData, $nonce, $key ); } if (self::use_fallback('crypto_aead_chacha20poly1305_ietf_decrypt')) { return call_user_func( '\\Sodium\\crypto_aead_chacha20poly1305_ietf_decrypt', $ciphertext, $assocData, $nonce, $key ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::aead_chacha20poly1305_ietf_decrypt( $ciphertext, $assocData, $nonce, $key ); } return ParagonIE_Sodium_Crypto::aead_chacha20poly1305_ietf_decrypt( $ciphertext, $assocData, $nonce, $key ); } /** * Return a secure random key for use with the ChaCha20-Poly1305 * symmetric AEAD interface. * * @return string * @throws Exception * @throws Error */ public static function crypto_aead_chacha20poly1305_keygen() { return random_bytes(self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES); } /** * Authenticated Encryption with Associated Data * * Algorithm: * ChaCha20-Poly1305 * * IETF mode uses a 96-bit random nonce with a 32-bit counter. * Regular mode uses a 64-bit random nonce with a 64-bit counter. * * @param string $plaintext Message to be encrypted * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * * @return string Ciphertext with a 16-byte Poly1305 message * authentication code appended * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_chacha20poly1305_ietf_encrypt( #[\SensitiveParameter] $plaintext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); if (!is_null($assocData)) { ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); } ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_aead_chacha20poly1305_ietf_encrypt( $plaintext, $assocData, $nonce, $key ); } if (self::use_fallback('crypto_aead_chacha20poly1305_ietf_encrypt')) { return (string) call_user_func( '\\Sodium\\crypto_aead_chacha20poly1305_ietf_encrypt', $plaintext, $assocData, $nonce, $key ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::aead_chacha20poly1305_ietf_encrypt( $plaintext, $assocData, $nonce, $key ); } return ParagonIE_Sodium_Crypto::aead_chacha20poly1305_ietf_encrypt( $plaintext, $assocData, $nonce, $key ); } /** * Return a secure random key for use with the ChaCha20-Poly1305 * symmetric AEAD interface. (IETF version) * * @return string * @throws Exception * @throws Error */ public static function crypto_aead_chacha20poly1305_ietf_keygen() { return random_bytes(self::CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES); } /** * Authenticated Encryption with Associated Data: Decryption * * Algorithm: * XChaCha20-Poly1305 * * This mode uses a 64-bit random nonce with a 64-bit counter. * IETF mode uses a 96-bit random nonce with a 32-bit counter. * * @param string $ciphertext Encrypted message (with Poly1305 MAC appended) * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * @param bool $dontFallback Don't fallback to ext/sodium * * @return string|bool The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_xchacha20poly1305_ietf_decrypt( $ciphertext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '', $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); if (!is_null($assocData)) { ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); } else { $assocData = ''; } ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES) { throw new SodiumException('Message must be at least CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES long'); } if (self::useNewSodiumAPI() && !$dontFallback) { if (is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_decrypt')) { return sodium_crypto_aead_xchacha20poly1305_ietf_decrypt( $ciphertext, $assocData, $nonce, $key ); } } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::aead_xchacha20poly1305_ietf_decrypt( $ciphertext, $assocData, $nonce, $key ); } return ParagonIE_Sodium_Crypto::aead_xchacha20poly1305_ietf_decrypt( $ciphertext, $assocData, $nonce, $key ); } /** * Authenticated Encryption with Associated Data * * Algorithm: * XChaCha20-Poly1305 * * This mode uses a 64-bit random nonce with a 64-bit counter. * IETF mode uses a 96-bit random nonce with a 32-bit counter. * * @param string $plaintext Message to be encrypted * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * @param bool $dontFallback Don't fallback to ext/sodium * * @return string Ciphertext with a 16-byte Poly1305 message * authentication code appended * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_xchacha20poly1305_ietf_encrypt( #[\SensitiveParameter] $plaintext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '', $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); if (!is_null($assocData)) { ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); } else { $assocData = ''; } ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_XCHACHA20POLY1305_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_XCHACHA20POLY1305_KEYBYTES long'); } if (self::useNewSodiumAPI() && !$dontFallback) { if (is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_encrypt')) { return sodium_crypto_aead_xchacha20poly1305_ietf_encrypt( $plaintext, $assocData, $nonce, $key ); } } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::aead_xchacha20poly1305_ietf_encrypt( $plaintext, $assocData, $nonce, $key ); } return ParagonIE_Sodium_Crypto::aead_xchacha20poly1305_ietf_encrypt( $plaintext, $assocData, $nonce, $key ); } /** * Return a secure random key for use with the XChaCha20-Poly1305 * symmetric AEAD interface. * * @return string * @throws Exception * @throws Error */ public static function crypto_aead_xchacha20poly1305_ietf_keygen() { return random_bytes(self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES); } /** * Authenticate a message. Uses symmetric-key cryptography. * * Algorithm: * HMAC-SHA512-256. Which is HMAC-SHA-512 truncated to 256 bits. * Not to be confused with HMAC-SHA-512/256 which would use the * SHA-512/256 hash function (uses different initial parameters * but still truncates to 256 bits to sidestep length-extension * attacks). * * @param string $message Message to be authenticated * @param string $key Symmetric authentication key * @return string Message authentication code * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_auth( $message, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AUTH_KEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_AUTH_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_auth($message, $key); } if (self::use_fallback('crypto_auth')) { return (string) call_user_func('\\Sodium\\crypto_auth', $message, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::auth($message, $key); } return ParagonIE_Sodium_Crypto::auth($message, $key); } /** * @return string * @throws Exception * @throws Error */ public static function crypto_auth_keygen() { return random_bytes(self::CRYPTO_AUTH_KEYBYTES); } /** * Verify the MAC of a message previously authenticated with crypto_auth. * * @param string $mac Message authentication code * @param string $message Message whose authenticity you are attempting to * verify (with a given MAC and key) * @param string $key Symmetric authentication key * @return bool TRUE if authenticated, FALSE otherwise * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_auth_verify( $mac, $message, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($mac, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($mac) !== self::CRYPTO_AUTH_BYTES) { throw new SodiumException('Argument 1 must be CRYPTO_AUTH_BYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AUTH_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_AUTH_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { return (bool) sodium_crypto_auth_verify($mac, $message, $key); } if (self::use_fallback('crypto_auth_verify')) { return (bool) call_user_func('\\Sodium\\crypto_auth_verify', $mac, $message, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::auth_verify($mac, $message, $key); } return ParagonIE_Sodium_Crypto::auth_verify($mac, $message, $key); } /** * Authenticated asymmetric-key encryption. Both the sender and recipient * may decrypt messages. * * Algorithm: X25519-XSalsa20-Poly1305. * X25519: Elliptic-Curve Diffie Hellman over Curve25519. * XSalsa20: Extended-nonce variant of salsa20. * Poyl1305: Polynomial MAC for one-time message authentication. * * @param string $plaintext The message to be encrypted * @param string $nonce A Number to only be used Once; must be 24 bytes * @param string $keypair Your secret key and your recipient's public key * @return string Ciphertext with 16-byte Poly1305 MAC * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box( $plaintext, $nonce, #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_BOX_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_BOX_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box($plaintext, $nonce, $keypair); } if (self::use_fallback('crypto_box')) { return (string) call_user_func('\\Sodium\\crypto_box', $plaintext, $nonce, $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box($plaintext, $nonce, $keypair); } return ParagonIE_Sodium_Crypto::box($plaintext, $nonce, $keypair); } /** * Anonymous public-key encryption. Only the recipient may decrypt messages. * * Algorithm: X25519-XSalsa20-Poly1305, as with crypto_box. * The sender's X25519 keypair is ephemeral. * Nonce is generated from the BLAKE2b hash of both public keys. * * This provides ciphertext integrity. * * @param string $plaintext Message to be sealed * @param string $publicKey Your recipient's public key * @return string Sealed message that only your recipient can * decrypt * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box_seal( #[\SensitiveParameter] $plaintext, $publicKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_BOX_PUBLICKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_seal($plaintext, $publicKey); } if (self::use_fallback('crypto_box_seal')) { return (string) call_user_func('\\Sodium\\crypto_box_seal', $plaintext, $publicKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_seal($plaintext, $publicKey); } return ParagonIE_Sodium_Crypto::box_seal($plaintext, $publicKey); } /** * Opens a message encrypted with crypto_box_seal(). Requires * the recipient's keypair (sk || pk) to decrypt successfully. * * This validates ciphertext integrity. * * @param string $ciphertext Sealed message to be opened * @param string $keypair Your crypto_box keypair * @return string The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_box_seal_open( $ciphertext, #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { /** * @psalm-suppress InvalidReturnStatement * @psalm-suppress FalsableReturnStatement */ return sodium_crypto_box_seal_open($ciphertext, $keypair); } if (self::use_fallback('crypto_box_seal_open')) { return call_user_func('\\Sodium\\crypto_box_seal_open', $ciphertext, $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_seal_open($ciphertext, $keypair); } return ParagonIE_Sodium_Crypto::box_seal_open($ciphertext, $keypair); } /** * Generate a new random X25519 keypair. * * @return string A 64-byte string; the first 32 are your secret key, while * the last 32 are your public key. crypto_box_secretkey() * and crypto_box_publickey() exist to separate them so you * don't accidentally get them mixed up! * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box_keypair() { if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_keypair(); } if (self::use_fallback('crypto_box_keypair')) { return (string) call_user_func('\\Sodium\\crypto_box_keypair'); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_keypair(); } return ParagonIE_Sodium_Crypto::box_keypair(); } /** * Combine two keys into a keypair for use in library methods that expect * a keypair. This doesn't necessarily have to be the same person's keys. * * @param string $secretKey Secret key * @param string $publicKey Public key * @return string Keypair * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box_keypair_from_secretkey_and_publickey( #[\SensitiveParameter] $secretKey, $publicKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_BOX_SECRETKEYBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_BOX_PUBLICKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_keypair_from_secretkey_and_publickey($secretKey, $publicKey); } if (self::use_fallback('crypto_box_keypair_from_secretkey_and_publickey')) { return (string) call_user_func('\\Sodium\\crypto_box_keypair_from_secretkey_and_publickey', $secretKey, $publicKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_keypair_from_secretkey_and_publickey($secretKey, $publicKey); } return ParagonIE_Sodium_Crypto::box_keypair_from_secretkey_and_publickey($secretKey, $publicKey); } /** * Decrypt a message previously encrypted with crypto_box(). * * @param string $ciphertext Encrypted message * @param string $nonce Number to only be used Once; must be 24 bytes * @param string $keypair Your secret key and the sender's public key * @return string The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_box_open( $ciphertext, $nonce, #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_BOX_MACBYTES) { throw new SodiumException('Argument 1 must be at least CRYPTO_BOX_MACBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_BOX_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_BOX_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { /** * @psalm-suppress InvalidReturnStatement * @psalm-suppress FalsableReturnStatement */ return sodium_crypto_box_open($ciphertext, $nonce, $keypair); } if (self::use_fallback('crypto_box_open')) { return call_user_func('\\Sodium\\crypto_box_open', $ciphertext, $nonce, $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_open($ciphertext, $nonce, $keypair); } return ParagonIE_Sodium_Crypto::box_open($ciphertext, $nonce, $keypair); } /** * Extract the public key from a crypto_box keypair. * * @param string $keypair Keypair containing secret and public key * @return string Your crypto_box public key * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box_publickey( #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_publickey($keypair); } if (self::use_fallback('crypto_box_publickey')) { return (string) call_user_func('\\Sodium\\crypto_box_publickey', $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_publickey($keypair); } return ParagonIE_Sodium_Crypto::box_publickey($keypair); } /** * Calculate the X25519 public key from a given X25519 secret key. * * @param string $secretKey Any X25519 secret key * @return string The corresponding X25519 public key * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box_publickey_from_secretkey( #[\SensitiveParameter] $secretKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_BOX_SECRETKEYBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_publickey_from_secretkey($secretKey); } if (self::use_fallback('crypto_box_publickey_from_secretkey')) { return (string) call_user_func('\\Sodium\\crypto_box_publickey_from_secretkey', $secretKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_publickey_from_secretkey($secretKey); } return ParagonIE_Sodium_Crypto::box_publickey_from_secretkey($secretKey); } /** * Extract the secret key from a crypto_box keypair. * * @param string $keypair * @return string Your crypto_box secret key * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box_secretkey( #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_secretkey($keypair); } if (self::use_fallback('crypto_box_secretkey')) { return (string) call_user_func('\\Sodium\\crypto_box_secretkey', $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_secretkey($keypair); } return ParagonIE_Sodium_Crypto::box_secretkey($keypair); } /** * Generate an X25519 keypair from a seed. * * @param string $seed * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress UndefinedFunction */ public static function crypto_box_seed_keypair( #[\SensitiveParameter] $seed ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($seed, 'string', 1); if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_seed_keypair($seed); } if (self::use_fallback('crypto_box_seed_keypair')) { return (string) call_user_func('\\Sodium\\crypto_box_seed_keypair', $seed); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_seed_keypair($seed); } return ParagonIE_Sodium_Crypto::box_seed_keypair($seed); } /** * Calculates a BLAKE2b hash, with an optional key. * * @param string $message The message to be hashed * @param string|null $key If specified, must be a string between 16 * and 64 bytes long * @param int $length Output length in bytes; must be between 16 * and 64 (default = 32) * @return string Raw binary * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_generichash( $message, #[\SensitiveParameter] $key = '', $length = self::CRYPTO_GENERICHASH_BYTES ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); if (is_null($key)) { $key = ''; } ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($length, 'int', 3); /* Input validation: */ if (!empty($key)) { if (ParagonIE_Sodium_Core_Util::strlen($key) < self::CRYPTO_GENERICHASH_KEYBYTES_MIN) { throw new SodiumException('Unsupported key size. Must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) > self::CRYPTO_GENERICHASH_KEYBYTES_MAX) { throw new SodiumException('Unsupported key size. Must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.'); } } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_generichash($message, $key, $length); } if (self::use_fallback('crypto_generichash')) { return (string) call_user_func('\\Sodium\\crypto_generichash', $message, $key, $length); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::generichash($message, $key, $length); } return ParagonIE_Sodium_Crypto::generichash($message, $key, $length); } /** * Get the final BLAKE2b hash output for a given context. * * @param string $ctx BLAKE2 hashing context. Generated by crypto_generichash_init(). * @param int $length Hash output size. * @return string Final BLAKE2b hash. * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress ReferenceConstraintViolation * @psalm-suppress ConflictingReferenceConstraint */ public static function crypto_generichash_final( #[\SensitiveParameter] &$ctx, $length = self::CRYPTO_GENERICHASH_BYTES ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ctx, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($length, 'int', 2); if (self::useNewSodiumAPI()) { return sodium_crypto_generichash_final($ctx, $length); } if (self::use_fallback('crypto_generichash_final')) { $func = '\\Sodium\\crypto_generichash_final'; return (string) $func($ctx, $length); } if ($length < 1) { try { self::memzero($ctx); } catch (SodiumException $ex) { unset($ctx); } return ''; } if (PHP_INT_SIZE === 4) { $result = ParagonIE_Sodium_Crypto32::generichash_final($ctx, $length); } else { $result = ParagonIE_Sodium_Crypto::generichash_final($ctx, $length); } try { self::memzero($ctx); } catch (SodiumException $ex) { unset($ctx); } return $result; } /** * Initialize a BLAKE2b hashing context, for use in a streaming interface. * * @param string|null $key If specified must be a string between 16 and 64 bytes * @param int $length The size of the desired hash output * @return string A BLAKE2 hashing context, encoded as a string * (To be 100% compatible with ext/libsodium) * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_generichash_init( #[\SensitiveParameter] $key = '', $length = self::CRYPTO_GENERICHASH_BYTES ) { /* Type checks: */ if (is_null($key)) { $key = ''; } ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($length, 'int', 2); /* Input validation: */ if (!empty($key)) { if (ParagonIE_Sodium_Core_Util::strlen($key) < self::CRYPTO_GENERICHASH_KEYBYTES_MIN) { throw new SodiumException('Unsupported key size. Must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) > self::CRYPTO_GENERICHASH_KEYBYTES_MAX) { throw new SodiumException('Unsupported key size. Must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.'); } } if (self::useNewSodiumAPI()) { return sodium_crypto_generichash_init($key, $length); } if (self::use_fallback('crypto_generichash_init')) { return (string) call_user_func('\\Sodium\\crypto_generichash_init', $key, $length); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::generichash_init($key, $length); } return ParagonIE_Sodium_Crypto::generichash_init($key, $length); } /** * Initialize a BLAKE2b hashing context, for use in a streaming interface. * * @param string|null $key If specified must be a string between 16 and 64 bytes * @param int $length The size of the desired hash output * @param string $salt Salt (up to 16 bytes) * @param string $personal Personalization string (up to 16 bytes) * @return string A BLAKE2 hashing context, encoded as a string * (To be 100% compatible with ext/libsodium) * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_generichash_init_salt_personal( #[\SensitiveParameter] $key = '', $length = self::CRYPTO_GENERICHASH_BYTES, $salt = '', $personal = '' ) { /* Type checks: */ if (is_null($key)) { $key = ''; } ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($length, 'int', 2); ParagonIE_Sodium_Core_Util::declareScalarType($salt, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($personal, 'string', 4); $salt = str_pad($salt, 16, "\0", STR_PAD_RIGHT); $personal = str_pad($personal, 16, "\0", STR_PAD_RIGHT); /* Input validation: */ if (!empty($key)) { /* if (ParagonIE_Sodium_Core_Util::strlen($key) < self::CRYPTO_GENERICHASH_KEYBYTES_MIN) { throw new SodiumException('Unsupported key size. Must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.'); } */ if (ParagonIE_Sodium_Core_Util::strlen($key) > self::CRYPTO_GENERICHASH_KEYBYTES_MAX) { throw new SodiumException('Unsupported key size. Must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.'); } } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::generichash_init_salt_personal($key, $length, $salt, $personal); } return ParagonIE_Sodium_Crypto::generichash_init_salt_personal($key, $length, $salt, $personal); } /** * Update a BLAKE2b hashing context with additional data. * * @param string $ctx BLAKE2 hashing context. Generated by crypto_generichash_init(). * $ctx is passed by reference and gets updated in-place. * @param-out string $ctx * @param string $message The message to append to the existing hash state. * @return void * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress ReferenceConstraintViolation */ public static function crypto_generichash_update( #[\SensitiveParameter] &$ctx, $message ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ctx, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 2); if (self::useNewSodiumAPI()) { sodium_crypto_generichash_update($ctx, $message); return; } if (self::use_fallback('crypto_generichash_update')) { $func = '\\Sodium\\crypto_generichash_update'; $func($ctx, $message); return; } if (PHP_INT_SIZE === 4) { $ctx = ParagonIE_Sodium_Crypto32::generichash_update($ctx, $message); } else { $ctx = ParagonIE_Sodium_Crypto::generichash_update($ctx, $message); } } /** * @return string * @throws Exception * @throws Error */ public static function crypto_generichash_keygen() { return random_bytes(self::CRYPTO_GENERICHASH_KEYBYTES); } /** * @param int $subkey_len * @param int $subkey_id * @param string $context * @param string $key * @return string * @throws SodiumException */ public static function crypto_kdf_derive_from_key( $subkey_len, $subkey_id, $context, #[\SensitiveParameter] $key ) { ParagonIE_Sodium_Core_Util::declareScalarType($subkey_len, 'int', 1); ParagonIE_Sodium_Core_Util::declareScalarType($subkey_id, 'int', 2); ParagonIE_Sodium_Core_Util::declareScalarType($context, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); $subkey_id = (int) $subkey_id; $subkey_len = (int) $subkey_len; $context = (string) $context; $key = (string) $key; if ($subkey_len < self::CRYPTO_KDF_BYTES_MIN) { throw new SodiumException('subkey cannot be smaller than SODIUM_CRYPTO_KDF_BYTES_MIN'); } if ($subkey_len > self::CRYPTO_KDF_BYTES_MAX) { throw new SodiumException('subkey cannot be larger than SODIUM_CRYPTO_KDF_BYTES_MAX'); } if ($subkey_id < 0) { throw new SodiumException('subkey_id cannot be negative'); } if (ParagonIE_Sodium_Core_Util::strlen($context) !== self::CRYPTO_KDF_CONTEXTBYTES) { throw new SodiumException('context should be SODIUM_CRYPTO_KDF_CONTEXTBYTES bytes'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_KDF_KEYBYTES) { throw new SodiumException('key should be SODIUM_CRYPTO_KDF_KEYBYTES bytes'); } $salt = ParagonIE_Sodium_Core_Util::store64_le($subkey_id); $state = self::crypto_generichash_init_salt_personal( $key, $subkey_len, $salt, $context ); return self::crypto_generichash_final($state, $subkey_len); } /** * @return string * @throws Exception * @throws Error */ public static function crypto_kdf_keygen() { return random_bytes(self::CRYPTO_KDF_KEYBYTES); } /** * Perform a key exchange, between a designated client and a server. * * Typically, you would designate one machine to be the client and the * other to be the server. The first two keys are what you'd expect for * scalarmult() below, but the latter two public keys don't swap places. * * | ALICE | BOB | * | Client | Server | * |--------------------------------|-------------------------------------| * | shared = crypto_kx( | shared = crypto_kx( | * | alice_sk, | bob_sk, | <- contextual * | bob_pk, | alice_pk, | <- contextual * | alice_pk, | alice_pk, | <----- static * | bob_pk | bob_pk | <----- static * | ) | ) | * * They are used along with the scalarmult product to generate a 256-bit * BLAKE2b hash unique to the client and server keys. * * @param string $my_secret * @param string $their_public * @param string $client_public * @param string $server_public * @param bool $dontFallback * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_kx( #[\SensitiveParameter] $my_secret, $their_public, $client_public, $server_public, $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($my_secret, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($their_public, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($client_public, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($server_public, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($my_secret) !== self::CRYPTO_BOX_SECRETKEYBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($their_public) !== self::CRYPTO_BOX_PUBLICKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($client_public) !== self::CRYPTO_BOX_PUBLICKEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($server_public) !== self::CRYPTO_BOX_PUBLICKEYBYTES) { throw new SodiumException('Argument 4 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI() && !$dontFallback) { if (is_callable('sodium_crypto_kx')) { return (string) sodium_crypto_kx( $my_secret, $their_public, $client_public, $server_public ); } } if (self::use_fallback('crypto_kx')) { return (string) call_user_func( '\\Sodium\\crypto_kx', $my_secret, $their_public, $client_public, $server_public ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::keyExchange( $my_secret, $their_public, $client_public, $server_public ); } return ParagonIE_Sodium_Crypto::keyExchange( $my_secret, $their_public, $client_public, $server_public ); } /** * @param string $seed * @return string * @throws SodiumException */ public static function crypto_kx_seed_keypair( #[\SensitiveParameter] $seed ) { ParagonIE_Sodium_Core_Util::declareScalarType($seed, 'string', 1); $seed = (string) $seed; if (ParagonIE_Sodium_Core_Util::strlen($seed) !== self::CRYPTO_KX_SEEDBYTES) { throw new SodiumException('seed must be SODIUM_CRYPTO_KX_SEEDBYTES bytes'); } $sk = self::crypto_generichash($seed, '', self::CRYPTO_KX_SECRETKEYBYTES); $pk = self::crypto_scalarmult_base($sk); return $sk . $pk; } /** * @return string * @throws Exception */ public static function crypto_kx_keypair() { $sk = self::randombytes_buf(self::CRYPTO_KX_SECRETKEYBYTES); $pk = self::crypto_scalarmult_base($sk); return $sk . $pk; } /** * @param string $keypair * @param string $serverPublicKey * @return array{0: string, 1: string} * @throws SodiumException */ public static function crypto_kx_client_session_keys( #[\SensitiveParameter] $keypair, $serverPublicKey ) { ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($serverPublicKey, 'string', 2); $keypair = (string) $keypair; $serverPublicKey = (string) $serverPublicKey; if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_KX_KEYPAIRBYTES) { throw new SodiumException('keypair should be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes'); } if (ParagonIE_Sodium_Core_Util::strlen($serverPublicKey) !== self::CRYPTO_KX_PUBLICKEYBYTES) { throw new SodiumException('public keys must be SODIUM_CRYPTO_KX_PUBLICKEYBYTES bytes'); } $sk = self::crypto_kx_secretkey($keypair); $pk = self::crypto_kx_publickey($keypair); $h = self::crypto_generichash_init(null, self::CRYPTO_KX_SESSIONKEYBYTES * 2); self::crypto_generichash_update($h, self::crypto_scalarmult($sk, $serverPublicKey)); self::crypto_generichash_update($h, $pk); self::crypto_generichash_update($h, $serverPublicKey); $sessionKeys = self::crypto_generichash_final($h, self::CRYPTO_KX_SESSIONKEYBYTES * 2); return array( ParagonIE_Sodium_Core_Util::substr( $sessionKeys, 0, self::CRYPTO_KX_SESSIONKEYBYTES ), ParagonIE_Sodium_Core_Util::substr( $sessionKeys, self::CRYPTO_KX_SESSIONKEYBYTES, self::CRYPTO_KX_SESSIONKEYBYTES ) ); } /** * @param string $keypair * @param string $clientPublicKey * @return array{0: string, 1: string} * @throws SodiumException */ public static function crypto_kx_server_session_keys( #[\SensitiveParameter] $keypair, $clientPublicKey ) { ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($clientPublicKey, 'string', 2); $keypair = (string) $keypair; $clientPublicKey = (string) $clientPublicKey; if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_KX_KEYPAIRBYTES) { throw new SodiumException('keypair should be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes'); } if (ParagonIE_Sodium_Core_Util::strlen($clientPublicKey) !== self::CRYPTO_KX_PUBLICKEYBYTES) { throw new SodiumException('public keys must be SODIUM_CRYPTO_KX_PUBLICKEYBYTES bytes'); } $sk = self::crypto_kx_secretkey($keypair); $pk = self::crypto_kx_publickey($keypair); $h = self::crypto_generichash_init(null, self::CRYPTO_KX_SESSIONKEYBYTES * 2); self::crypto_generichash_update($h, self::crypto_scalarmult($sk, $clientPublicKey)); self::crypto_generichash_update($h, $clientPublicKey); self::crypto_generichash_update($h, $pk); $sessionKeys = self::crypto_generichash_final($h, self::CRYPTO_KX_SESSIONKEYBYTES * 2); return array( ParagonIE_Sodium_Core_Util::substr( $sessionKeys, self::CRYPTO_KX_SESSIONKEYBYTES, self::CRYPTO_KX_SESSIONKEYBYTES ), ParagonIE_Sodium_Core_Util::substr( $sessionKeys, 0, self::CRYPTO_KX_SESSIONKEYBYTES ) ); } /** * @param string $kp * @return string * @throws SodiumException */ public static function crypto_kx_secretkey( #[\SensitiveParameter] $kp ) { return ParagonIE_Sodium_Core_Util::substr( $kp, 0, self::CRYPTO_KX_SECRETKEYBYTES ); } /** * @param string $kp * @return string * @throws SodiumException */ public static function crypto_kx_publickey($kp) { return ParagonIE_Sodium_Core_Util::substr( $kp, self::CRYPTO_KX_SECRETKEYBYTES, self::CRYPTO_KX_PUBLICKEYBYTES ); } /** * @param int $outlen * @param string $passwd * @param string $salt * @param int $opslimit * @param int $memlimit * @param int|null $alg * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_pwhash( $outlen, #[\SensitiveParameter] $passwd, $salt, $opslimit, $memlimit, $alg = null ) { ParagonIE_Sodium_Core_Util::declareScalarType($outlen, 'int', 1); ParagonIE_Sodium_Core_Util::declareScalarType($passwd, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($salt, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($opslimit, 'int', 4); ParagonIE_Sodium_Core_Util::declareScalarType($memlimit, 'int', 5); if (self::useNewSodiumAPI()) { if (!is_null($alg)) { ParagonIE_Sodium_Core_Util::declareScalarType($alg, 'int', 6); return sodium_crypto_pwhash($outlen, $passwd, $salt, $opslimit, $memlimit, $alg); } return sodium_crypto_pwhash($outlen, $passwd, $salt, $opslimit, $memlimit); } if (self::use_fallback('crypto_pwhash')) { return (string) call_user_func('\\Sodium\\crypto_pwhash', $outlen, $passwd, $salt, $opslimit, $memlimit); } // This is the best we can do. throw new SodiumException( 'This is not implemented, as it is not possible to implement Argon2i with acceptable performance in pure-PHP' ); } /** * !Exclusive to sodium_compat! * * This returns TRUE if the native crypto_pwhash API is available by libsodium. * This returns FALSE if only sodium_compat is available. * * @return bool */ public static function crypto_pwhash_is_available() { if (self::useNewSodiumAPI()) { return true; } if (self::use_fallback('crypto_pwhash')) { return true; } return false; } /** * @param string $passwd * @param int $opslimit * @param int $memlimit * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_pwhash_str( #[\SensitiveParameter] $passwd, $opslimit, $memlimit ) { ParagonIE_Sodium_Core_Util::declareScalarType($passwd, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($opslimit, 'int', 2); ParagonIE_Sodium_Core_Util::declareScalarType($memlimit, 'int', 3); if (self::useNewSodiumAPI()) { return sodium_crypto_pwhash_str($passwd, $opslimit, $memlimit); } if (self::use_fallback('crypto_pwhash_str')) { return (string) call_user_func('\\Sodium\\crypto_pwhash_str', $passwd, $opslimit, $memlimit); } // This is the best we can do. throw new SodiumException( 'This is not implemented, as it is not possible to implement Argon2i with acceptable performance in pure-PHP' ); } /** * Do we need to rehash this password? * * @param string $hash * @param int $opslimit * @param int $memlimit * @return bool * @throws SodiumException */ public static function crypto_pwhash_str_needs_rehash( #[\SensitiveParameter] $hash, $opslimit, $memlimit ) { ParagonIE_Sodium_Core_Util::declareScalarType($hash, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($opslimit, 'int', 2); ParagonIE_Sodium_Core_Util::declareScalarType($memlimit, 'int', 3); // Just grab the first 4 pieces. $pieces = explode('$', (string) $hash); $prefix = implode('$', array_slice($pieces, 0, 4)); // Rebuild the expected header. /** @var int $ops */ $ops = (int) $opslimit; /** @var int $mem */ $mem = (int) $memlimit >> 10; $encoded = self::CRYPTO_PWHASH_STRPREFIX . 'v=19$m=' . $mem . ',t=' . $ops . ',p=1'; // Do they match? If so, we don't need to rehash, so return false. return !ParagonIE_Sodium_Core_Util::hashEquals($encoded, $prefix); } /** * @param string $passwd * @param string $hash * @return bool * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_pwhash_str_verify( #[\SensitiveParameter] $passwd, #[\SensitiveParameter] $hash ) { ParagonIE_Sodium_Core_Util::declareScalarType($passwd, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($hash, 'string', 2); if (self::useNewSodiumAPI()) { return (bool) sodium_crypto_pwhash_str_verify($passwd, $hash); } if (self::use_fallback('crypto_pwhash_str_verify')) { return (bool) call_user_func('\\Sodium\\crypto_pwhash_str_verify', $passwd, $hash); } // This is the best we can do. throw new SodiumException( 'This is not implemented, as it is not possible to implement Argon2i with acceptable performance in pure-PHP' ); } /** * @param int $outlen * @param string $passwd * @param string $salt * @param int $opslimit * @param int $memlimit * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_pwhash_scryptsalsa208sha256( $outlen, #[\SensitiveParameter] $passwd, $salt, $opslimit, $memlimit ) { ParagonIE_Sodium_Core_Util::declareScalarType($outlen, 'int', 1); ParagonIE_Sodium_Core_Util::declareScalarType($passwd, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($salt, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($opslimit, 'int', 4); ParagonIE_Sodium_Core_Util::declareScalarType($memlimit, 'int', 5); if (self::useNewSodiumAPI()) { return (string) sodium_crypto_pwhash_scryptsalsa208sha256( (int) $outlen, (string) $passwd, (string) $salt, (int) $opslimit, (int) $memlimit ); } if (self::use_fallback('crypto_pwhash_scryptsalsa208sha256')) { return (string) call_user_func( '\\Sodium\\crypto_pwhash_scryptsalsa208sha256', (int) $outlen, (string) $passwd, (string) $salt, (int) $opslimit, (int) $memlimit ); } // This is the best we can do. throw new SodiumException( 'This is not implemented, as it is not possible to implement Scrypt with acceptable performance in pure-PHP' ); } /** * !Exclusive to sodium_compat! * * This returns TRUE if the native crypto_pwhash API is available by libsodium. * This returns FALSE if only sodium_compat is available. * * @return bool */ public static function crypto_pwhash_scryptsalsa208sha256_is_available() { if (self::useNewSodiumAPI()) { return true; } if (self::use_fallback('crypto_pwhash_scryptsalsa208sha256')) { return true; } return false; } /** * @param string $passwd * @param int $opslimit * @param int $memlimit * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_pwhash_scryptsalsa208sha256_str( #[\SensitiveParameter] $passwd, $opslimit, $memlimit ) { ParagonIE_Sodium_Core_Util::declareScalarType($passwd, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($opslimit, 'int', 2); ParagonIE_Sodium_Core_Util::declareScalarType($memlimit, 'int', 3); if (self::useNewSodiumAPI()) { return (string) sodium_crypto_pwhash_scryptsalsa208sha256_str( (string) $passwd, (int) $opslimit, (int) $memlimit ); } if (self::use_fallback('crypto_pwhash_scryptsalsa208sha256_str')) { return (string) call_user_func( '\\Sodium\\crypto_pwhash_scryptsalsa208sha256_str', (string) $passwd, (int) $opslimit, (int) $memlimit ); } // This is the best we can do. throw new SodiumException( 'This is not implemented, as it is not possible to implement Scrypt with acceptable performance in pure-PHP' ); } /** * @param string $passwd * @param string $hash * @return bool * @throws SodiumException * @throws TypeError */ public static function crypto_pwhash_scryptsalsa208sha256_str_verify( #[\SensitiveParameter] $passwd, #[\SensitiveParameter] $hash ) { ParagonIE_Sodium_Core_Util::declareScalarType($passwd, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($hash, 'string', 2); if (self::useNewSodiumAPI()) { return (bool) sodium_crypto_pwhash_scryptsalsa208sha256_str_verify( (string) $passwd, (string) $hash ); } if (self::use_fallback('crypto_pwhash_scryptsalsa208sha256_str_verify')) { return (bool) call_user_func( '\\Sodium\\crypto_pwhash_scryptsalsa208sha256_str_verify', (string) $passwd, (string) $hash ); } // This is the best we can do. throw new SodiumException( 'This is not implemented, as it is not possible to implement Scrypt with acceptable performance in pure-PHP' ); } /** * Calculate the shared secret between your secret key and your * recipient's public key. * * Algorithm: X25519 (ECDH over Curve25519) * * @param string $secretKey * @param string $publicKey * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_scalarmult( #[\SensitiveParameter] $secretKey, $publicKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_BOX_SECRETKEYBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_BOX_PUBLICKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_scalarmult($secretKey, $publicKey); } if (self::use_fallback('crypto_scalarmult')) { return (string) call_user_func('\\Sodium\\crypto_scalarmult', $secretKey, $publicKey); } /* Output validation: Forbid all-zero keys */ if (ParagonIE_Sodium_Core_Util::hashEquals($secretKey, str_repeat("\0", self::CRYPTO_BOX_SECRETKEYBYTES))) { throw new SodiumException('Zero secret key is not allowed'); } if (ParagonIE_Sodium_Core_Util::hashEquals($publicKey, str_repeat("\0", self::CRYPTO_BOX_PUBLICKEYBYTES))) { throw new SodiumException('Zero public key is not allowed'); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::scalarmult($secretKey, $publicKey); } return ParagonIE_Sodium_Crypto::scalarmult($secretKey, $publicKey); } /** * Calculate an X25519 public key from an X25519 secret key. * * @param string $secretKey * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress TooFewArguments * @psalm-suppress MixedArgument */ public static function crypto_scalarmult_base( #[\SensitiveParameter] $secretKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_BOX_SECRETKEYBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_scalarmult_base($secretKey); } if (self::use_fallback('crypto_scalarmult_base')) { return (string) call_user_func('\\Sodium\\crypto_scalarmult_base', $secretKey); } if (ParagonIE_Sodium_Core_Util::hashEquals($secretKey, str_repeat("\0", self::CRYPTO_BOX_SECRETKEYBYTES))) { throw new SodiumException('Zero secret key is not allowed'); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::scalarmult_base($secretKey); } return ParagonIE_Sodium_Crypto::scalarmult_base($secretKey); } /** * Authenticated symmetric-key encryption. * * Algorithm: XSalsa20-Poly1305 * * @param string $plaintext The message you're encrypting * @param string $nonce A Number to be used Once; must be 24 bytes * @param string $key Symmetric encryption key * @return string Ciphertext with Poly1305 MAC * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_secretbox( #[\SensitiveParameter] $plaintext, $nonce, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_SECRETBOX_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SECRETBOX_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_secretbox($plaintext, $nonce, $key); } if (self::use_fallback('crypto_secretbox')) { return (string) call_user_func('\\Sodium\\crypto_secretbox', $plaintext, $nonce, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretbox($plaintext, $nonce, $key); } return ParagonIE_Sodium_Crypto::secretbox($plaintext, $nonce, $key); } /** * Decrypts a message previously encrypted with crypto_secretbox(). * * @param string $ciphertext Ciphertext with Poly1305 MAC * @param string $nonce A Number to be used Once; must be 24 bytes * @param string $key Symmetric encryption key * @return string Original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_secretbox_open( $ciphertext, $nonce, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_SECRETBOX_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SECRETBOX_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { /** * @psalm-suppress InvalidReturnStatement * @psalm-suppress FalsableReturnStatement */ return sodium_crypto_secretbox_open($ciphertext, $nonce, $key); } if (self::use_fallback('crypto_secretbox_open')) { return call_user_func('\\Sodium\\crypto_secretbox_open', $ciphertext, $nonce, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretbox_open($ciphertext, $nonce, $key); } return ParagonIE_Sodium_Crypto::secretbox_open($ciphertext, $nonce, $key); } /** * Return a secure random key for use with crypto_secretbox * * @return string * @throws Exception * @throws Error */ public static function crypto_secretbox_keygen() { return random_bytes(self::CRYPTO_SECRETBOX_KEYBYTES); } /** * Authenticated symmetric-key encryption. * * Algorithm: XChaCha20-Poly1305 * * @param string $plaintext The message you're encrypting * @param string $nonce A Number to be used Once; must be 24 bytes * @param string $key Symmetric encryption key * @return string Ciphertext with Poly1305 MAC * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_secretbox_xchacha20poly1305($plaintext, $nonce, $key) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_SECRETBOX_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SECRETBOX_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.'); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretbox_xchacha20poly1305($plaintext, $nonce, $key); } return ParagonIE_Sodium_Crypto::secretbox_xchacha20poly1305($plaintext, $nonce, $key); } /** * Decrypts a message previously encrypted with crypto_secretbox_xchacha20poly1305(). * * @param string $ciphertext Ciphertext with Poly1305 MAC * @param string $nonce A Number to be used Once; must be 24 bytes * @param string $key Symmetric encryption key * @return string Original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_secretbox_xchacha20poly1305_open( $ciphertext, $nonce, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_SECRETBOX_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SECRETBOX_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.'); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key); } return ParagonIE_Sodium_Crypto::secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key); } /** * @param string $key * @return array Returns a state and a header. * @throws Exception * @throws SodiumException */ public static function crypto_secretstream_xchacha20poly1305_init_push( #[\SensitiveParameter] $key ) { if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_init_push($key); } return ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_init_push($key); } /** * @param string $header * @param string $key * @return string Returns a state. * @throws Exception */ public static function crypto_secretstream_xchacha20poly1305_init_pull( $header, #[\SensitiveParameter] $key ) { if (ParagonIE_Sodium_Core_Util::strlen($header) < self::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES) { throw new SodiumException( 'header size should be SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES bytes' ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_init_pull($key, $header); } return ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_init_pull($key, $header); } /** * @param string $state * @param string $msg * @param string $aad * @param int $tag * @return string * @throws SodiumException */ public static function crypto_secretstream_xchacha20poly1305_push( #[\SensitiveParameter] &$state, #[\SensitiveParameter] $msg, $aad = '', $tag = 0 ) { if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_push( $state, $msg, $aad, $tag ); } return ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_push( $state, $msg, $aad, $tag ); } /** * @param string $state * @param string $msg * @param string $aad * @return bool|array{0: string, 1: int} * @throws SodiumException */ public static function crypto_secretstream_xchacha20poly1305_pull( #[\SensitiveParameter] &$state, $msg, $aad = '' ) { if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_pull( $state, $msg, $aad ); } return ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_pull( $state, $msg, $aad ); } /** * @return string * @throws Exception */ public static function crypto_secretstream_xchacha20poly1305_keygen() { return random_bytes(self::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES); } /** * @param string $state * @return void * @throws SodiumException */ public static function crypto_secretstream_xchacha20poly1305_rekey( #[\SensitiveParameter] &$state ) { if (PHP_INT_SIZE === 4) { ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_rekey($state); } else { ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_rekey($state); } } /** * Calculates a SipHash-2-4 hash of a message for a given key. * * @param string $message Input message * @param string $key SipHash-2-4 key * @return string Hash * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_shorthash( $message, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SHORTHASH_KEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SHORTHASH_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_shorthash($message, $key); } if (self::use_fallback('crypto_shorthash')) { return (string) call_user_func('\\Sodium\\crypto_shorthash', $message, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_SipHash::sipHash24($message, $key); } return ParagonIE_Sodium_Core_SipHash::sipHash24($message, $key); } /** * Return a secure random key for use with crypto_shorthash * * @return string * @throws Exception * @throws Error */ public static function crypto_shorthash_keygen() { return random_bytes(self::CRYPTO_SHORTHASH_KEYBYTES); } /** * Returns a signed message. You probably want crypto_sign_detached() * instead, which only returns the signature. * * Algorithm: Ed25519 (EdDSA over Curve25519) * * @param string $message Message to be signed. * @param string $secretKey Secret signing key. * @return string Signed message (signature is prefixed). * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_sign( $message, #[\SensitiveParameter] $secretKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_SIGN_SECRETKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SIGN_SECRETKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign($message, $secretKey); } if (self::use_fallback('crypto_sign')) { return (string) call_user_func('\\Sodium\\crypto_sign', $message, $secretKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::sign($message, $secretKey); } return ParagonIE_Sodium_Crypto::sign($message, $secretKey); } /** * Validates a signed message then returns the message. * * @param string $signedMessage A signed message * @param string $publicKey A public key * @return string The original message (if the signature is * valid for this public key) * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_sign_open( $signedMessage, $publicKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($signedMessage, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($signedMessage) < self::CRYPTO_SIGN_BYTES) { throw new SodiumException('Argument 1 must be at least CRYPTO_SIGN_BYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_SIGN_PUBLICKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SIGN_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI()) { /** * @psalm-suppress InvalidReturnStatement * @psalm-suppress FalsableReturnStatement */ return sodium_crypto_sign_open($signedMessage, $publicKey); } if (self::use_fallback('crypto_sign_open')) { return call_user_func('\\Sodium\\crypto_sign_open', $signedMessage, $publicKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::sign_open($signedMessage, $publicKey); } return ParagonIE_Sodium_Crypto::sign_open($signedMessage, $publicKey); } /** * Generate a new random Ed25519 keypair. * * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_sign_keypair() { if (self::useNewSodiumAPI()) { return sodium_crypto_sign_keypair(); } if (self::use_fallback('crypto_sign_keypair')) { return (string) call_user_func('\\Sodium\\crypto_sign_keypair'); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_Ed25519::keypair(); } return ParagonIE_Sodium_Core_Ed25519::keypair(); } /** * @param string $sk * @param string $pk * @return string * @throws SodiumException */ public static function crypto_sign_keypair_from_secretkey_and_publickey( #[\SensitiveParameter] $sk, $pk ) { ParagonIE_Sodium_Core_Util::declareScalarType($sk, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($pk, 'string', 1); $sk = (string) $sk; $pk = (string) $pk; if (ParagonIE_Sodium_Core_Util::strlen($sk) !== self::CRYPTO_SIGN_SECRETKEYBYTES) { throw new SodiumException('secretkey should be SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes'); } if (ParagonIE_Sodium_Core_Util::strlen($pk) !== self::CRYPTO_SIGN_PUBLICKEYBYTES) { throw new SodiumException('publickey should be SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES bytes'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign_keypair_from_secretkey_and_publickey($sk, $pk); } return $sk . $pk; } /** * Generate an Ed25519 keypair from a seed. * * @param string $seed Input seed * @return string Keypair * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_seed_keypair( #[\SensitiveParameter] $seed ) { ParagonIE_Sodium_Core_Util::declareScalarType($seed, 'string', 1); if (self::useNewSodiumAPI()) { return sodium_crypto_sign_seed_keypair($seed); } if (self::use_fallback('crypto_sign_keypair')) { return (string) call_user_func('\\Sodium\\crypto_sign_seed_keypair', $seed); } $publicKey = ''; $secretKey = ''; if (PHP_INT_SIZE === 4) { ParagonIE_Sodium_Core32_Ed25519::seed_keypair($publicKey, $secretKey, $seed); } else { ParagonIE_Sodium_Core_Ed25519::seed_keypair($publicKey, $secretKey, $seed); } return $secretKey . $publicKey; } /** * Extract an Ed25519 public key from an Ed25519 keypair. * * @param string $keypair Keypair * @return string Public key * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_publickey( #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_SIGN_KEYPAIRBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_SIGN_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign_publickey($keypair); } if (self::use_fallback('crypto_sign_publickey')) { return (string) call_user_func('\\Sodium\\crypto_sign_publickey', $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_Ed25519::publickey($keypair); } return ParagonIE_Sodium_Core_Ed25519::publickey($keypair); } /** * Calculate an Ed25519 public key from an Ed25519 secret key. * * @param string $secretKey Your Ed25519 secret key * @return string The corresponding Ed25519 public key * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_publickey_from_secretkey( #[\SensitiveParameter] $secretKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_SIGN_SECRETKEYBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_SIGN_SECRETKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign_publickey_from_secretkey($secretKey); } if (self::use_fallback('crypto_sign_publickey_from_secretkey')) { return (string) call_user_func('\\Sodium\\crypto_sign_publickey_from_secretkey', $secretKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_Ed25519::publickey_from_secretkey($secretKey); } return ParagonIE_Sodium_Core_Ed25519::publickey_from_secretkey($secretKey); } /** * Extract an Ed25519 secret key from an Ed25519 keypair. * * @param string $keypair Keypair * @return string Secret key * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_secretkey( #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_SIGN_KEYPAIRBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_SIGN_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign_secretkey($keypair); } if (self::use_fallback('crypto_sign_secretkey')) { return (string) call_user_func('\\Sodium\\crypto_sign_secretkey', $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_Ed25519::secretkey($keypair); } return ParagonIE_Sodium_Core_Ed25519::secretkey($keypair); } /** * Calculate the Ed25519 signature of a message and return ONLY the signature. * * Algorithm: Ed25519 (EdDSA over Curve25519) * * @param string $message Message to be signed * @param string $secretKey Secret signing key * @return string Digital signature * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_detached( $message, #[\SensitiveParameter] $secretKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_SIGN_SECRETKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SIGN_SECRETKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign_detached($message, $secretKey); } if (self::use_fallback('crypto_sign_detached')) { return (string) call_user_func('\\Sodium\\crypto_sign_detached', $message, $secretKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::sign_detached($message, $secretKey); } return ParagonIE_Sodium_Crypto::sign_detached($message, $secretKey); } /** * Verify the Ed25519 signature of a message. * * @param string $signature Digital sginature * @param string $message Message to be verified * @param string $publicKey Public key * @return bool TRUE if this signature is good for this public key; * FALSE otherwise * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_verify_detached($signature, $message, $publicKey) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($signature, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($signature) !== self::CRYPTO_SIGN_BYTES) { throw new SodiumException('Argument 1 must be CRYPTO_SIGN_BYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_SIGN_PUBLICKEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SIGN_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign_verify_detached($signature, $message, $publicKey); } if (self::use_fallback('crypto_sign_verify_detached')) { return (bool) call_user_func( '\\Sodium\\crypto_sign_verify_detached', $signature, $message, $publicKey ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::sign_verify_detached($signature, $message, $publicKey); } return ParagonIE_Sodium_Crypto::sign_verify_detached($signature, $message, $publicKey); } /** * Convert an Ed25519 public key to a Curve25519 public key * * @param string $pk * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_ed25519_pk_to_curve25519($pk) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($pk, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($pk) < self::CRYPTO_SIGN_PUBLICKEYBYTES) { throw new SodiumException('Argument 1 must be at least CRYPTO_SIGN_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI()) { if (is_callable('crypto_sign_ed25519_pk_to_curve25519')) { return (string) sodium_crypto_sign_ed25519_pk_to_curve25519($pk); } } if (self::use_fallback('crypto_sign_ed25519_pk_to_curve25519')) { return (string) call_user_func('\\Sodium\\crypto_sign_ed25519_pk_to_curve25519', $pk); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_Ed25519::pk_to_curve25519($pk); } return ParagonIE_Sodium_Core_Ed25519::pk_to_curve25519($pk); } /** * Convert an Ed25519 secret key to a Curve25519 secret key * * @param string $sk * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_ed25519_sk_to_curve25519( #[\SensitiveParameter] $sk ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($sk, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($sk) < self::CRYPTO_SIGN_SEEDBYTES) { throw new SodiumException('Argument 1 must be at least CRYPTO_SIGN_SEEDBYTES long.'); } if (self::useNewSodiumAPI()) { if (is_callable('crypto_sign_ed25519_sk_to_curve25519')) { return sodium_crypto_sign_ed25519_sk_to_curve25519($sk); } } if (self::use_fallback('crypto_sign_ed25519_sk_to_curve25519')) { return (string) call_user_func('\\Sodium\\crypto_sign_ed25519_sk_to_curve25519', $sk); } $h = hash('sha512', ParagonIE_Sodium_Core_Util::substr($sk, 0, 32), true); $h[0] = ParagonIE_Sodium_Core_Util::intToChr( ParagonIE_Sodium_Core_Util::chrToInt($h[0]) & 248 ); $h[31] = ParagonIE_Sodium_Core_Util::intToChr( (ParagonIE_Sodium_Core_Util::chrToInt($h[31]) & 127) | 64 ); return ParagonIE_Sodium_Core_Util::substr($h, 0, 32); } /** * Expand a key and nonce into a keystream of pseudorandom bytes. * * @param int $len Number of bytes desired * @param string $nonce Number to be used Once; must be 24 bytes * @param string $key XSalsa20 key * @return string Pseudorandom stream that can be XORed with messages * to provide encryption (but not authentication; see * Poly1305 or crypto_auth() for that, which is not * optional for security) * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_stream( $len, $nonce, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($len, 'int', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_STREAM_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_stream($len, $nonce, $key); } if (self::use_fallback('crypto_stream')) { return (string) call_user_func('\\Sodium\\crypto_stream', $len, $nonce, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_XSalsa20::xsalsa20($len, $nonce, $key); } return ParagonIE_Sodium_Core_XSalsa20::xsalsa20($len, $nonce, $key); } /** * DANGER! UNAUTHENTICATED ENCRYPTION! * * Unless you are following expert advice, do not use this feature. * * Algorithm: XSalsa20 * * This DOES NOT provide ciphertext integrity. * * @param string $message Plaintext message * @param string $nonce Number to be used Once; must be 24 bytes * @param string $key Encryption key * @return string Encrypted text which is vulnerable to chosen- * ciphertext attacks unless you implement some * other mitigation to the ciphertext (i.e. * Encrypt then MAC) * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_stream_xor( #[\SensitiveParameter] $message, $nonce, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_stream_xor($message, $nonce, $key); } if (self::use_fallback('crypto_stream_xor')) { return (string) call_user_func('\\Sodium\\crypto_stream_xor', $message, $nonce, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_XSalsa20::xsalsa20_xor($message, $nonce, $key); } return ParagonIE_Sodium_Core_XSalsa20::xsalsa20_xor($message, $nonce, $key); } /** * Return a secure random key for use with crypto_stream * * @return string * @throws Exception * @throws Error */ public static function crypto_stream_keygen() { return random_bytes(self::CRYPTO_STREAM_KEYBYTES); } /** * Expand a key and nonce into a keystream of pseudorandom bytes. * * @param int $len Number of bytes desired * @param string $nonce Number to be used Once; must be 24 bytes * @param string $key XChaCha20 key * @param bool $dontFallback * @return string Pseudorandom stream that can be XORed with messages * to provide encryption (but not authentication; see * Poly1305 or crypto_auth() for that, which is not * optional for security) * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_stream_xchacha20( $len, $nonce, #[\SensitiveParameter] $key, $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($len, 'int', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_STREAM_XCHACHA20_KEYBYTES long.'); } if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_stream_xchacha20($len, $nonce, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_XChaCha20::stream($len, $nonce, $key); } return ParagonIE_Sodium_Core_XChaCha20::stream($len, $nonce, $key); } /** * DANGER! UNAUTHENTICATED ENCRYPTION! * * Unless you are following expert advice, do not use this feature. * * Algorithm: XChaCha20 * * This DOES NOT provide ciphertext integrity. * * @param string $message Plaintext message * @param string $nonce Number to be used Once; must be 24 bytes * @param string $key Encryption key * @return string Encrypted text which is vulnerable to chosen- * ciphertext attacks unless you implement some * other mitigation to the ciphertext (i.e. * Encrypt then MAC) * @param bool $dontFallback * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_stream_xchacha20_xor( #[\SensitiveParameter] $message, $nonce, #[\SensitiveParameter] $key, $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_XCHACHA20_KEYBYTES long.'); } if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_stream_xchacha20_xor($message, $nonce, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_XChaCha20::streamXorIc($message, $nonce, $key); } return ParagonIE_Sodium_Core_XChaCha20::streamXorIc($message, $nonce, $key); } /** * DANGER! UNAUTHENTICATED ENCRYPTION! * * Unless you are following expert advice, do not use this feature. * * Algorithm: XChaCha20 * * This DOES NOT provide ciphertext integrity. * * @param string $message Plaintext message * @param string $nonce Number to be used Once; must be 24 bytes * @param int $counter * @param string $key Encryption key * @return string Encrypted text which is vulnerable to chosen- * ciphertext attacks unless you implement some * other mitigation to the ciphertext (i.e. * Encrypt then MAC) * @param bool $dontFallback * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_stream_xchacha20_xor_ic( #[\SensitiveParameter] $message, $nonce, $counter, #[\SensitiveParameter] $key, $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($counter, 'int', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_XCHACHA20_KEYBYTES long.'); } if (is_callable('sodium_crypto_stream_xchacha20_xor_ic') && !$dontFallback) { return sodium_crypto_stream_xchacha20_xor_ic($message, $nonce, $counter, $key); } $ic = ParagonIE_Sodium_Core_Util::store64_le($counter); if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_XChaCha20::streamXorIc($message, $nonce, $key, $ic); } return ParagonIE_Sodium_Core_XChaCha20::streamXorIc($message, $nonce, $key, $ic); } /** * Return a secure random key for use with crypto_stream_xchacha20 * * @return string * @throws Exception * @throws Error */ public static function crypto_stream_xchacha20_keygen() { return random_bytes(self::CRYPTO_STREAM_XCHACHA20_KEYBYTES); } /** * Cache-timing-safe implementation of hex2bin(). * * @param string $string Hexadecimal string * @param string $ignore List of characters to ignore; useful for whitespace * @return string Raw binary string * @throws SodiumException * @throws TypeError * @psalm-suppress TooFewArguments * @psalm-suppress MixedArgument */ public static function hex2bin( #[\SensitiveParameter] $string, $ignore = '' ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($string, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($ignore, 'string', 2); if (self::useNewSodiumAPI()) { if (is_callable('sodium_hex2bin')) { return (string) sodium_hex2bin($string, $ignore); } } if (self::use_fallback('hex2bin')) { return (string) call_user_func('\\Sodium\\hex2bin', $string, $ignore); } return ParagonIE_Sodium_Core_Util::hex2bin($string, $ignore); } /** * Increase a string (little endian) * * @param string $var * * @return void * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function increment( #[\SensitiveParameter] &$var ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($var, 'string', 1); if (self::useNewSodiumAPI()) { sodium_increment($var); return; } if (self::use_fallback('increment')) { $func = '\\Sodium\\increment'; $func($var); return; } $len = ParagonIE_Sodium_Core_Util::strlen($var); $c = 1; $copy = ''; for ($i = 0; $i < $len; ++$i) { $c += ParagonIE_Sodium_Core_Util::chrToInt( ParagonIE_Sodium_Core_Util::substr($var, $i, 1) ); $copy .= ParagonIE_Sodium_Core_Util::intToChr($c); $c >>= 8; } $var = $copy; } /** * @param string $str * @return bool * * @throws SodiumException */ public static function is_zero( #[\SensitiveParameter] $str ) { $d = 0; for ($i = 0; $i < 32; ++$i) { $d |= ParagonIE_Sodium_Core_Util::chrToInt($str[$i]); } return ((($d - 1) >> 31) & 1) === 1; } /** * The equivalent to the libsodium minor version we aim to be compatible * with (sans pwhash and memzero). * * @return int */ public static function library_version_major() { if (self::useNewSodiumAPI() && defined('SODIUM_LIBRARY_MAJOR_VERSION')) { return SODIUM_LIBRARY_MAJOR_VERSION; } if (self::use_fallback('library_version_major')) { /** @psalm-suppress UndefinedFunction */ return (int) call_user_func('\\Sodium\\library_version_major'); } return self::LIBRARY_VERSION_MAJOR; } /** * The equivalent to the libsodium minor version we aim to be compatible * with (sans pwhash and memzero). * * @return int */ public static function library_version_minor() { if (self::useNewSodiumAPI() && defined('SODIUM_LIBRARY_MINOR_VERSION')) { return SODIUM_LIBRARY_MINOR_VERSION; } if (self::use_fallback('library_version_minor')) { /** @psalm-suppress UndefinedFunction */ return (int) call_user_func('\\Sodium\\library_version_minor'); } return self::LIBRARY_VERSION_MINOR; } /** * Compare two strings. * * @param string $left * @param string $right * @return int * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function memcmp( #[\SensitiveParameter] $left, #[\SensitiveParameter] $right ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($left, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($right, 'string', 2); if (self::useNewSodiumAPI()) { return sodium_memcmp($left, $right); } if (self::use_fallback('memcmp')) { return (int) call_user_func('\\Sodium\\memcmp', $left, $right); } /** @var string $left */ /** @var string $right */ return ParagonIE_Sodium_Core_Util::memcmp($left, $right); } /** * It's actually not possible to zero memory buffers in PHP. You need the * native library for that. * * @param string|null $var * @param-out string|null $var * * @return void * @throws SodiumException (Unless libsodium is installed) * @throws TypeError * @psalm-suppress TooFewArguments */ public static function memzero( #[\SensitiveParameter] &$var ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($var, 'string', 1); if (self::useNewSodiumAPI()) { /** @psalm-suppress MixedArgument */ sodium_memzero($var); return; } if (self::use_fallback('memzero')) { $func = '\\Sodium\\memzero'; $func($var); if ($var === null) { return; } } // This is the best we can do. throw new SodiumException( 'This is not implemented in sodium_compat, as it is not possible to securely wipe memory from PHP. ' . 'To fix this error, make sure libsodium is installed and the PHP extension is enabled.' ); } /** * @param string $unpadded * @param int $blockSize * @param bool $dontFallback * @return string * @throws SodiumException */ public static function pad( #[\SensitiveParameter] $unpadded, $blockSize, $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($unpadded, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($blockSize, 'int', 2); $unpadded = (string) $unpadded; $blockSize = (int) $blockSize; if (self::useNewSodiumAPI() && !$dontFallback) { return (string) sodium_pad($unpadded, $blockSize); } if ($blockSize <= 0) { throw new SodiumException( 'block size cannot be less than 1' ); } $unpadded_len = ParagonIE_Sodium_Core_Util::strlen($unpadded); $xpadlen = ($blockSize - 1); if (($blockSize & ($blockSize - 1)) === 0) { $xpadlen -= $unpadded_len & ($blockSize - 1); } else { $xpadlen -= $unpadded_len % $blockSize; } $xpadded_len = $unpadded_len + $xpadlen; $padded = str_repeat("\0", $xpadded_len - 1); if ($unpadded_len > 0) { $st = 1; $i = 0; $k = $unpadded_len; for ($j = 0; $j <= $xpadded_len; ++$j) { $i = (int) $i; $k = (int) $k; $st = (int) $st; if ($j >= $unpadded_len) { $padded[$j] = "\0"; } else { $padded[$j] = $unpadded[$j]; } /** @var int $k */ $k -= $st; $st = (int) (~( ( ( ($k >> 48) | ($k >> 32) | ($k >> 16) | $k ) - 1 ) >> 16 ) ) & 1; $i += $st; } } $mask = 0; $tail = $xpadded_len; for ($i = 0; $i < $blockSize; ++$i) { # barrier_mask = (unsigned char) # (((i ^ xpadlen) - 1U) >> ((sizeof(size_t) - 1U) * CHAR_BIT)); $barrier_mask = (($i ^ $xpadlen) -1) >> ((PHP_INT_SIZE << 3) - 1); # tail[-i] = (tail[-i] & mask) | (0x80 & barrier_mask); $padded[$tail - $i] = ParagonIE_Sodium_Core_Util::intToChr( (ParagonIE_Sodium_Core_Util::chrToInt($padded[$tail - $i]) & $mask) | (0x80 & $barrier_mask) ); # mask |= barrier_mask; $mask |= $barrier_mask; } return $padded; } /** * @param string $padded * @param int $blockSize * @param bool $dontFallback * @return string * @throws SodiumException */ public static function unpad( #[\SensitiveParameter] $padded, $blockSize, $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($padded, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($blockSize, 'int', 2); $padded = (string) $padded; $blockSize = (int) $blockSize; if (self::useNewSodiumAPI() && !$dontFallback) { return (string) sodium_unpad($padded, $blockSize); } if ($blockSize <= 0) { throw new SodiumException('block size cannot be less than 1'); } $padded_len = ParagonIE_Sodium_Core_Util::strlen($padded); if ($padded_len < $blockSize) { throw new SodiumException('invalid padding'); } # tail = &padded[padded_len - 1U]; $tail = $padded_len - 1; $acc = 0; $valid = 0; $pad_len = 0; $found = 0; for ($i = 0; $i < $blockSize; ++$i) { # c = tail[-i]; $c = ParagonIE_Sodium_Core_Util::chrToInt($padded[$tail - $i]); # is_barrier = # (( (acc - 1U) & (pad_len - 1U) & ((c ^ 0x80) - 1U) ) >> 8) & 1U; $is_barrier = ( ( ($acc - 1) & ($pad_len - 1) & (($c ^ 80) - 1) ) >> 7 ) & 1; $is_barrier &= ~$found; $found |= $is_barrier; # acc |= c; $acc |= $c; # pad_len |= i & (1U + ~is_barrier); $pad_len |= $i & (1 + ~$is_barrier); # valid |= (unsigned char) is_barrier; $valid |= ($is_barrier & 0xff); } # unpadded_len = padded_len - 1U - pad_len; $unpadded_len = $padded_len - 1 - $pad_len; if ($valid !== 1) { throw new SodiumException('invalid padding'); } return ParagonIE_Sodium_Core_Util::substr($padded, 0, $unpadded_len); } /** * Will sodium_compat run fast on the current hardware and PHP configuration? * * @return bool */ public static function polyfill_is_fast() { if (extension_loaded('sodium')) { return true; } if (extension_loaded('libsodium')) { return true; } return PHP_INT_SIZE === 8; } /** * Generate a string of bytes from the kernel's CSPRNG. * Proudly uses /dev/urandom (if getrandom(2) is not available). * * @param int $numBytes * @return string * @throws Exception * @throws TypeError */ public static function randombytes_buf($numBytes) { /* Type checks: */ if (!is_int($numBytes)) { if (is_numeric($numBytes)) { $numBytes = (int) $numBytes; } else { throw new TypeError( 'Argument 1 must be an integer, ' . gettype($numBytes) . ' given.' ); } } /** @var positive-int $numBytes */ if (self::use_fallback('randombytes_buf')) { return (string) call_user_func('\\Sodium\\randombytes_buf', $numBytes); } if ($numBytes < 0) { throw new SodiumException("Number of bytes must be a positive integer"); } return random_bytes($numBytes); } /** * Generate an integer between 0 and $range (non-inclusive). * * @param int $range * @return int * @throws Exception * @throws Error * @throws TypeError */ public static function randombytes_uniform($range) { /* Type checks: */ if (!is_int($range)) { if (is_numeric($range)) { $range = (int) $range; } else { throw new TypeError( 'Argument 1 must be an integer, ' . gettype($range) . ' given.' ); } } if (self::use_fallback('randombytes_uniform')) { return (int) call_user_func('\\Sodium\\randombytes_uniform', $range); } return random_int(0, $range - 1); } /** * Generate a random 16-bit integer. * * @return int * @throws Exception * @throws Error * @throws TypeError */ public static function randombytes_random16() { if (self::use_fallback('randombytes_random16')) { return (int) call_user_func('\\Sodium\\randombytes_random16'); } return random_int(0, 65535); } /** * @param string $p * @param bool $dontFallback * @return bool * @throws SodiumException */ public static function ristretto255_is_valid_point( #[\SensitiveParameter] $p, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_is_valid_point($p); } try { $r = ParagonIE_Sodium_Core_Ristretto255::ristretto255_frombytes($p); return $r['res'] === 0 && ParagonIE_Sodium_Core_Ristretto255::ristretto255_point_is_canonical($p) === 1; } catch (SodiumException $ex) { if ($ex->getMessage() === 'S is not canonical') { return false; } throw $ex; } } /** * @param string $p * @param string $q * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_add( #[\SensitiveParameter] $p, #[\SensitiveParameter] $q, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_add($p, $q); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_add($p, $q); } /** * @param string $p * @param string $q * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_sub( #[\SensitiveParameter] $p, #[\SensitiveParameter] $q, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_sub($p, $q); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_sub($p, $q); } /** * @param string $r * @param bool $dontFallback * @return string * * @throws SodiumException */ public static function ristretto255_from_hash( #[\SensitiveParameter] $r, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_from_hash($r); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_from_hash($r); } /** * @param bool $dontFallback * @return string * * @throws SodiumException */ public static function ristretto255_random($dontFallback = false) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_random(); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_random(); } /** * @param bool $dontFallback * @return string * * @throws SodiumException */ public static function ristretto255_scalar_random($dontFallback = false) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_random(); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_random(); } /** * @param string $s * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_invert( #[\SensitiveParameter] $s, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_invert($s); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_invert($s); } /** * @param string $s * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_negate( #[\SensitiveParameter] $s, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_negate($s); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_negate($s); } /** * @param string $s * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_complement( #[\SensitiveParameter] $s, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_complement($s); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_complement($s); } /** * @param string $x * @param string $y * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_add( #[\SensitiveParameter] $x, #[\SensitiveParameter] $y, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_add($x, $y); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_add($x, $y); } /** * @param string $x * @param string $y * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_sub( #[\SensitiveParameter] $x, #[\SensitiveParameter] $y, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_sub($x, $y); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_sub($x, $y); } /** * @param string $x * @param string $y * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_mul( #[\SensitiveParameter] $x, #[\SensitiveParameter] $y, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_mul($x, $y); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_mul($x, $y); } /** * @param string $n * @param string $p * @param bool $dontFallback * @return string * @throws SodiumException */ public static function scalarmult_ristretto255( #[\SensitiveParameter] $n, #[\SensitiveParameter] $p, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_scalarmult_ristretto255($n, $p); } return ParagonIE_Sodium_Core_Ristretto255::scalarmult_ristretto255($n, $p); } /** * @param string $n * @param string $p * @param bool $dontFallback * @return string * @throws SodiumException */ public static function scalarmult_ristretto255_base( #[\SensitiveParameter] $n, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_scalarmult_ristretto255_base($n); } return ParagonIE_Sodium_Core_Ristretto255::scalarmult_ristretto255_base($n); } /** * @param string $s * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_reduce( #[\SensitiveParameter] $s, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_reduce($s); } return ParagonIE_Sodium_Core_Ristretto255::sc_reduce($s); } /** * Runtime testing method for 32-bit platforms. * * Usage: If runtime_speed_test() returns FALSE, then our 32-bit * implementation is to slow to use safely without risking timeouts. * If this happens, install sodium from PECL to get acceptable * performance. * * @param int $iterations Number of multiplications to attempt * @param int $maxTimeout Milliseconds * @return bool TRUE if we're fast enough, FALSE is not * @throws SodiumException */ public static function runtime_speed_test($iterations, $maxTimeout) { if (self::polyfill_is_fast()) { return true; } /** @var float $end */ $end = 0.0; /** @var float $start */ $start = microtime(true); /** @var ParagonIE_Sodium_Core32_Int64 $a */ $a = ParagonIE_Sodium_Core32_Int64::fromInt(random_int(3, 1 << 16)); for ($i = 0; $i < $iterations; ++$i) { /** @var ParagonIE_Sodium_Core32_Int64 $b */ $b = ParagonIE_Sodium_Core32_Int64::fromInt(random_int(3, 1 << 16)); $a->mulInt64($b); } /** @var float $end */ $end = microtime(true); /** @var int $diff */ $diff = (int) ceil(($end - $start) * 1000); return $diff < $maxTimeout; } /** * Add two numbers (little-endian unsigned), storing the value in the first * parameter. * * This mutates $val. * * @param string $val * @param string $addv * @return void * @throws SodiumException */ public static function sub( #[\SensitiveParameter] &$val, #[\SensitiveParameter] $addv ) { $val_len = ParagonIE_Sodium_Core_Util::strlen($val); $addv_len = ParagonIE_Sodium_Core_Util::strlen($addv); if ($val_len !== $addv_len) { throw new SodiumException('values must have the same length'); } $A = ParagonIE_Sodium_Core_Util::stringToIntArray($val); $B = ParagonIE_Sodium_Core_Util::stringToIntArray($addv); $c = 0; for ($i = 0; $i < $val_len; $i++) { $c = ($A[$i] - $B[$i] - $c); $A[$i] = ($c & 0xff); $c = ($c >> 8) & 1; } $val = ParagonIE_Sodium_Core_Util::intArrayToString($A); } /** * This emulates libsodium's version_string() function, except ours is * prefixed with 'polyfill-'. * * @return string * @psalm-suppress MixedInferredReturnType * @psalm-suppress UndefinedFunction */ public static function version_string() { if (self::useNewSodiumAPI()) { return (string) sodium_version_string(); } if (self::use_fallback('version_string')) { return (string) call_user_func('\\Sodium\\version_string'); } return (string) self::VERSION_STRING; } /** * Should we use the libsodium core function instead? * This is always a good idea, if it's available. (Unless we're in the * middle of running our unit test suite.) * * If ext/libsodium is available, use it. Return TRUE. * Otherwise, we have to use the code provided herein. Return FALSE. * * @param string $sodium_func_name * * @return bool */ protected static function use_fallback($sodium_func_name = '') { static $res = null; if ($res === null) { $res = extension_loaded('libsodium') && PHP_VERSION_ID >= 50300; } if ($res === false) { // No libsodium installed return false; } if (self::$disableFallbackForUnitTests) { // Don't fallback. Use the PHP implementation. return false; } if (!empty($sodium_func_name)) { return is_callable('\\Sodium\\' . $sodium_func_name); } return true; } /** * Libsodium as implemented in PHP 7.2 * and/or ext/sodium (via PECL) * * @ref https://wiki.php.net/rfc/libsodium * @return bool */ protected static function useNewSodiumAPI() { static $res = null; if ($res === null) { $res = PHP_VERSION_ID >= 70000 && extension_loaded('sodium'); } if (self::$disableFallbackForUnitTests) { // Don't fallback. Use the PHP implementation. return false; } return (bool) $res; } } PK! DataMapper/Manager.phpnu[get( 'datamapper' ) ) { // Set the custom query. if ( ( $custom_sql = $wp_query->get( 'custom_sql' ) ) ) { $sql = $custom_sql; } // Perhaps we're to initiate a delete query instead? elseif ( $wp_query->get( 'is_delete' ) ) { $sql = preg_replace( '/^SELECT.*FROM/i', 'DELETE FROM', $sql ); } if ( $wp_query->get( 'debug' ) ) { var_dump( $sql ); } } return $sql; } /** * Sets custom fields to select from the database * * @param string $fields * @param \WP_Query $wp_query * @return string */ public function set_custom_wp_query_fields( $fields, $wp_query ) { if ( $wp_query->get( 'datamapper' ) ) { if ( ( $custom_fields = $wp_query->get( 'fields' ) ) && $custom_fields != 'ids' ) { $fields = $custom_fields; } } return $fields; } /** * Sets custom where clauses for a query * * @param string $where * @param WP_Query $wp_query * @return string */ public function set_custom_wp_query_where( $where, $wp_query ) { if ( $wp_query->get( 'datamapper' ) ) { $this->add_post_title_where_clauses( $where, $wp_query ); $this->add_post_name_where_clauses( $where, $wp_query ); } return $where; } /** * Adds additional group by clauses to the SQL query * * @param string $group_by * @param \WP_Query $wp_query * @return string */ public function set_custom_wp_query_groupby( $group_by, $wp_query ) { $retval = $group_by; $group_by_columns = $wp_query->get( 'group_by_columns' ); if ( $group_by_columns ) { $retval = str_replace( 'GROUP BY', '', $retval ); $columns = explode( ',', $retval ); foreach ( array_reverse( $columns ) as $column ) { array_unshift( $group_by_columns, trim( $column ) ); } $retval = 'GROUP BY ' . implode( ', ', $group_by_columns ); } elseif ( $wp_query->get( 'datamapper' ) ) { // Not all mysql servers allow access to create temporary tables which are used when doing GROUP BY // statements; this can potentially ruin basic queries. If no group_by_columns is set AND the query originates // within the datamapper we strip the "GROUP BY" clause entirely in this filter. $retval = ''; } return $retval; } /** * Formats the value of used in a WHERE IN SQL clause for use in the WP_Query where clause * * @param string|array $values * @return string */ public function format_where_in_value( $values ) { if ( is_string( $values ) && strpos( $values, ',' ) !== false ) { $values = explode( ', ', $values ); } elseif ( ! is_array( $values ) ) { $values = [ $values ]; } // Quote the titles. foreach ( $values as $index => $value ) { $values[ $index ] = "'{$value}'"; } return implode( ', ', $values ); } /** * Adds post_title to the where clause * * @param string $where * @param WP_Query $wp_query * @return string */ public function add_post_title_where_clauses( &$where, &$wp_query ) { global $wpdb; // Handle post_title query var. if ( ( $titles = $wp_query->get( 'post_title' ) ) ) { $titles = $this->format_where_in_value( $titles ); $where .= " AND {$wpdb->posts}.post_title IN ({$titles})"; } elseif ( ( $value = $wp_query->get( 'post_title__like' ) ) ) { // Handle post_title_like query var. $where .= " AND {$wpdb->posts}.post_title LIKE '{$value}'"; } return $where; } /** * Adds post_name to the where clause * * @param string $where * @param \WP_Query $wp_query */ public function add_post_name_where_clauses( &$where, &$wp_query ) { global $wpdb; if ( ( $name = $wp_query->get( 'page_name__like' ) ) ) { $where .= " AND {$wpdb->posts}.post_name LIKE '{$name}'"; } elseif ( ( $names = $wp_query->get( 'page_name__in' ) ) ) { $names = $this->format_where_in_value( $names ); $where .= " AND {$wpdb->posts}.post_name IN ({$names})"; } } } PK!t1LDataMapper/WPModel.phpnu[>DataMapper/WPPostDriver.phpnu[ 20 ) { throw new \Exception( 'The custom post name can be no longer than 20 characters long' ); } parent::__construct( $object_name ); } public function lookup_columns() { if ( empty( self::$post_table_columns ) ) { $columns = parent::lookup_columns(); foreach ( $columns as $column ) { self::$post_table_columns[] = $column; } } else { foreach ( self::$post_table_columns as $column ) { $this->_table_columns[] = $column; } } } /** * Gets the name of the table * * @global string $table_prefix * @return string */ public function get_table_name() { global $table_prefix; return $table_prefix . 'posts'; } /** * Returns a list of querable table columns for posts * * @return array */ public function _get_querable_table_columns() { return [ 'name', 'author', 'date', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand', 'comment_count' ]; } /** * Specifies an order clause * * @param string $order_by * @param string $direction * @return WPPostDriver */ public function order_by( $order_by, $direction = 'ASC' ) { // Make an exception for the rand() method. $order_by = preg_replace( '/rand\(\s*\)/', 'rand', $order_by ); if ( in_array( $order_by, $this->_get_querable_table_columns() ) ) { $this->query_args['orderby'] = $order_by; } else { // ordering by a meta value. $this->query_args['orderby'] = 'meta_value'; $this->query_args['meta_key'] = $order_by; } $this->query_args['order'] = $direction; return $this; } /** * Specifies a limit and optional offset * * @param int $max * @param int|bool $offset (optional) * @return object */ public function limit( $max, $offset = false ) { if ( $max ) { $this->query_args['paged'] = true; if ( $offset ) { $this->query_args['offset'] = $offset; } else { unset( $this->query_args['offset'] ); } $this->query_args['posts_per_page'] = $max; } return $this; } /** * Specifies a list of columns to group by * * @param array|string $columns * @return object */ public function group_by( $columns = [] ) { if ( ! isset( $this->query_args['group_by_columns'] ) ) { $this->query_args['group_by_columns'] = $columns; } else { $this->query_args['group_by_columns'] = array_merge( $this->query_args['group_by_columns'], $columns ); } return $this; } /** * Adds a WP_Query where clause * * @param array $where_clauses * @param string $join */ public function add_where_clause( $where_clauses, $join ) { foreach ( $where_clauses as $clause ) { // Determine where what the where clause is comparing. switch ( $clause['column'] ) { case 'author': case 'author_id': $this->query_args['author'] = $clause['value']; break; case 'author_name': $this->query_args['author_name'] = $clause['value']; break; case 'cat': case 'cat_id': case 'category_id': switch ( $clause['compare'] ) { case '=': case 'BETWEEN'; case 'IN'; if ( ! isset( $this->query_args['category__in'] ) ) { $this->query_args['category__in'] = []; } $this->query_args['category__in'][] = $clause['value']; break; case '!=': case 'NOT BETWEEN'; case 'NOT IN'; if ( ! isset( $this->query_args['category__not_in'] ) ) { $this->query_args['category__not_in'] = []; } $this->query_args['category__not_in'][] = $clause['value']; break; } break; case 'category_name': $this->query_args['category_name'] = $clause['value']; break; case 'post_id': case $this->get_primary_key_column(): switch ( $clause['compare'] ) { case '=': case 'IN'; case 'BETWEEN'; if ( ! isset( $this->query_args['post__in'] ) ) { $this->query_args['post__in'] = []; } $this->query_args['post__in'][] = $clause['value']; break; default: if ( ! isset( $this->query_args['post__not_in'] ) ) { $this->query_args['post__not_in'] = []; } $this->query_args['post__not_in'][] = $clause['value']; break; } break; case 'pagename': case 'postname': case 'page_name': case 'post_name': if ( $clause['compare'] == 'LIKE' ) { $this->query_args['page_name__like'] = $clause['value']; } elseif ( $clause['compare'] == '=' ) { $this->query_args['pagename'] = $clause['value']; } elseif ( $clause['compare'] == 'IN' ) { $this->query_args['page_name__in'] = $clause['value']; } break; case 'post_title': // Post title uses custom WHERE clause. if ( $clause['compare'] == 'LIKE' ) { $this->query_args['post_title__like'] = $clause['value']; } else { $this->query_args['post_title'] = $clause['value']; } break; default: // Must be metadata. $clause['key'] = $clause['column']; unset( $clause['column'] ); // Convert values to array, when required. if ( in_array( $clause['compare'], [ 'IN', 'BETWEEN' ] ) ) { $clause['value'] = explode( ',', $clause['value'] ); foreach ( $clause['value'] as &$val ) { if ( ! is_numeric( $val ) ) { // In the _parse_where_clause() method, we. // quote the strings and add slashes. $val = stripslashes( $val ); $val = substr( $val, 1, strlen( $val ) - 2 ); } } } if ( ! isset( $this->query_args['meta_query'] ) ) { $this->query_args['meta_query'] = []; } $this->query_args['meta_query'][] = $clause; break; } } // If any where clauses have been added, specify how the conditions. // will be conbined/joined. if ( isset( $this->query_args['meta_query'] ) ) { $this->query_args['meta_query']['relation'] = $join; } } /** * Converts a post to an entity. * * @param \stdClass $post * @param boolean $model * @return \stdClass */ public function convert_post_to_entity( $post, $model = false ) { $entity = new \stdClass(); // Unserialize the post_content_filtered field. if ( is_string( $post->post_content_filtered ) ) { if ( ( $post_content = Serializable::unserialize( $post->post_content_filtered ) ) ) { foreach ( $post_content as $key => $value ) { $post->$key = $value; } } } // Unserialize the post content field. if ( is_string( $post->post_content ) ) { if ( ( $post_content = Serializable::unserialize( $post->post_content ) ) ) { foreach ( $post_content as $key => $value ) { $post->$key = $value; } } } // Copy post fields to entity. unset( $post->post_content ); unset( $post->post_content_filtered ); foreach ( $post as $key => $value ) { $entity->$key = $value; } $this->_convert_to_entity( $entity ); return $model ? $this->convert_to_model( $entity ) : $entity; } /** * Converts an entity to a post * * @param object $entity * @return object */ public function _convert_entity_to_post( $entity ) { // Was a model passed instead of an entity? $post = $entity; // Create the post content. $post_content = clone $post; foreach ( $this->_table_columns as $column ) { unset( $post_content->$column ); } unset( $post->id_field ); unset( $post->post_content_filtered ); unset( $post->post_content ); $post->post_content = Serializable::serialize( $post_content ); $post->post_content_filtered = $post->post_content; $post->post_type = $this->get_object_name(); // Sometimes an entity can contain a data stored in an array or object // Those will be removed from the post, and serialized in the // post_content field. foreach ( $post as $key => $value ) { if ( in_array( strtolower( gettype( $value ) ), [ 'object', 'array' ] ) ) { unset( $post->$key ); } } // A post required a title. if ( empty( $post->post_title ) ) { $post->post_title = $this->get_post_title( $post ); } // A post also requires an excerpt. if ( empty( $post->post_excerpt ) ) { $post->post_excerpt = $this->get_post_excerpt( $post ); } return $post; } /** * Returns the WordPress database class * * @global \wpdb $wpdb * @return \wpdb */ public function _wpdb() { global $wpdb; return $wpdb; } /** * Flush and update all postmeta for a particular post * * @param int $post_id */ public function _flush_and_update_postmeta( $post_id, $entity, $omit = [] ) { // We need to insert post meta data for each property // Unfortunately, that means flushing all existing postmeta // and then inserting new values. Depending on the number of // properties, this could be slow. So, we directly access the database. /* @var \wpdb $wpdb */ global $wpdb; if ( ! is_array( $omit ) ) { $omit = [ $omit ]; } // By default, we omit creating meta values for columns in the posts table. $omit = array_merge( $omit, $this->_table_columns ); // Delete the existing meta values. $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE post_id = %s", $post_id ) ); // Create query for new meta values. $sql_parts = []; foreach ( $entity as $key => $value ) { if ( in_array( $key, $omit ) ) { continue; } if ( is_array( $value ) or is_object( $value ) ) { $value = Serializable::serialize( $value ); } $sql_parts[] = $wpdb->prepare( '(%s, %s, %s)', $post_id, $key, $value ); } // The following $sql_parts is already sent through $wpdb->prepare() -- look directly above this line // // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $wpdb->query( "INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES " . implode( ',', $sql_parts ) ); } /** * Determines whether the current statement is SELECT * * @return boolean */ public function is_select_statement() { return isset( $this->query_args['is_select'] ) && $this->query_args['is_select']; } /** * Runs the query * * @param string|bool $sql (optional) Run the specified query * @param object|bool $model (optional) * @param bool $convert_to_entities (optional) Default = true * @return array */ public function run_query( $sql = false, $model = true, $convert_to_entities = true ) { $retval = []; $results = []; // All of our custom fields are stored as post meta, but is also stored as a serialized value in the post_content // field. Because of this, we don't need to look up and cache the post meta values. $this->query_args['no_found_posts'] = false; $this->query_args['update_post_meta_cache'] = false; // Don't cache any manual SQL query. if ( $sql ) { $this->query_args['cache_results'] = false; $this->query_args['custom_sql'] = $sql; } // If this is a select query, then try fetching the results from cache. $cache_key = md5( json_encode( $this->query_args ) ); if ( $this->is_select_statement() && $this->use_cache ) { $results = $this->get_from_cache( $cache_key ); } // Execute the query. if ( ! $results ) { $query = new \WP_Query( [ 'datamapper' => true, 'fields' => '*' ] ); if ( isset( $this->debug ) ) { $this->query_args['debug'] = true; } $query->query_vars = $this->query_args; add_action( 'pre_get_posts', [ &$this, 'set_query_args' ], PHP_INT_MAX - 1, 1 ); $results = $query->get_posts(); // Cache the result. if ( $this->is_select_statement() ) { $this->cache( $cache_key, $results ); } remove_action( 'pre_get_posts', [ &$this, 'set_query_args' ], PHP_INT_MAX - 1 ); } // Convert the result. if ( $convert_to_entities ) { foreach ( $results as $row ) { $retval[] = $this->convert_post_to_entity( $row, $model ); } } else { $retval = $results; } // Ensure that we return an empty array when there are no results. if ( ! $retval ) { $retval = []; } return $retval; } /** * Ensure that the query args are set. We need to do this in case a third-party * plugin overrides our query. * * @param $query */ public function set_query_args( $query ) { if ( $query->get( 'datamapper' ) ) { $query->query_vars = $this->query_args; } $filter = isset( $query->query_vars['suppress_filters'] ) ? $query->query_vars['suppress_filters'] : false; $query->query_vars['suppress_filters'] = apply_filters( 'wpml_suppress_filters', $filter ); } /** * Returns the number of total records/entities that exist * * @return int */ public function count() { $this->select( $this->get_primary_key_column() ); $retval = $this->run_query( false, false, false ); return count( $retval ); } /** * Used to select which fields should be returned. NOT currently used by * this implementation of the datamapper driver * * @param string $fields * @return WPPostDriver */ public function select( $fields = '*' ) { $this->query_args = [ 'post_type' => $this->get_object_name(), 'paged' => false, 'fields' => $fields, 'post_status' => 'any', 'datamapper' => true, 'posts_per_page' => -1, 'is_select' => true, 'is_delete' => false, ]; return $this; } /** * Destroys/deletes an entity from the database * * @param \stdClass|Model|int $entity * @param bool $skip_trash (optional) Default = true * @return bool */ public function destroy( $entity, $skip_trash = true ) { $retval = false; $key = $this->get_primary_key_column(); // Find the id of the entity. if ( is_object( $entity ) && isset( $entity->$key ) ) { $id = (int) $entity->$key; } else { $id = (int) $entity; } // If we have an ID, then delete the post. if ( is_integer( $id ) ) { // TODO: We assume that we can skip the trash. Is that correct? // FYI, Deletes postmeta as wells. if ( is_object( wp_delete_post( $id, true ) ) ) { $retval = true; } } return $retval; } /** * Saves an entity to the database * * @param object $entity * @return int Post ID */ public function save_entity( $entity ) { $post = $this->_convert_entity_to_post( $entity ); $primary_key = $this->get_primary_key_column(); // Avoid pre_replace deprecation exception on sanitize_mime_type() by ensuring mime type is not null. if ( is_null( $post->post_mime_type ) ) { $post->post_mime_type = ''; } // TODO: unsilence this. WordPress 3.9-beta2 is generating an error that should be corrected before its final release. if ( ( $post_id = wp_insert_post( (array) $post ) ) ) { $new_entity = $this->find( $post_id, true ); if ( $new_entity ) { foreach ( get_object_vars( $new_entity ) as $key => $value ) { $entity->$key = $value; } } // Save properties as post meta. $this->_flush_and_update_postmeta( $post_id, $entity ); $entity->$primary_key = $post_id; // Clean cache. $this->cache = []; } $entity->id_field = $primary_key; return $post_id; } /** * Starts a new DELETE statement. */ public function delete() { $this->select(); $this->query_args['is_select'] = false; $this->query_args['is_delete'] = true; return $this; } /** * Returns the title of the post. Used when post_title is not set * * @param \stdClass $entity * @return string */ public function get_post_title( $entity ) { return "Untitled {$this->get_object_name()}"; } /** * Returns the excerpt of the post. Used when post_excerpt is not set * * @param \stdClass $entity * @return string */ public function get_post_excerpt( $entity ) { return ''; } } PK!f#BBDataMapper/DriverBase.phpnu[_object_name = $object_name; $this->lookup_columns(); } abstract public function add_where_clause( $where_clauses, $join ); abstract public function save_entity( $entity ); abstract public function select( $fields = null ); /** * @return string */ public function get_object_name() { return $this->_object_name; } /** * @global string $table_prefix * @return string */ public function get_table_name() { global $table_prefix; global $wpdb; $prefix = $table_prefix; if ( $wpdb != null && $wpdb->prefix != null ) { $prefix = $wpdb->prefix; } return \apply_filters( 'ngg_datamapper_table_name', $prefix . $this->_object_name, $this->_object_name ); } /** * Looks up using SQL the columns existing in the database, result is cached */ public function lookup_columns() { // Avoid doing multiple SHOW COLUMNS if we can help it. $key = Transient::create_key( 'col_in_' . $this->get_table_name(), 'columns' ); $this->_table_columns = Transient::fetch( $key, false ); if ( ! $this->_table_columns ) { $this->update_columns_cache(); } return $this->_table_columns; } /** * Looks up using SQL the columns existing in the database */ public function update_columns_cache() { global $wpdb; $key = Transient::create_key( 'col_in_' . $this->get_table_name(), 'columns' ); $this->_table_columns = []; // $wpdb->prepare() cannot be used just yet as it only supported the %i placeholder for column names as of // WordPress 6.2 which is newer than NextGEN's current minimum WordPress version. // // TODO: Once NextGEN's minimum WP version is 6.2 or higher use wpdb->prepare() here. // // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared foreach ( $wpdb->get_results( "SHOW COLUMNS FROM {$this->get_table_name()}" ) as $row ) { $this->_table_columns[] = $row->Field; } Transient::update( $key, $this->_table_columns ); } /** * @param string $column_name * @return bool */ public function has_column( $column_name ) { if ( empty( $this->_table_columns ) ) { $this->lookup_columns(); } return array_search( $column_name, $this->_table_columns ) !== false; } /** * @return string */ public function get_primary_key_column() { return $this->primary_key_column; } public function cache( $key, $results ) { if ( $this->use_cache ) { $this->cache[ $key ] = $results; } } public function get_from_cache( $key, $default = null ) { if ( $this->use_cache && isset( $this->cache[ $key ] ) ) { return $this->cache[ $key ]; } else { return $default; } } public function flush_query_cache() { $this->cache = []; } /** * Used to clean column or table names in a SQL query * * @param string $val * @return string */ public function _clean_column( $val ) { return str_replace( [ ';', "'", '"', '`' ], [ '' ], $val ); } /** * Notes that a particular columns is serialized, and should be deserialized when converted to an entity * * @param $column */ public function add_serialized_column( $column ) { $this->_serialized_columns[] = $column; } public function deserialize_columns( $object ) { foreach ( $this->_serialized_columns as $column ) { if ( isset( $object->$column ) && is_string( $object->$column ) ) { $object->$column = \Imagely\NGG\Util\Serializable::unserialize( $object->$column ); } } } /** * @param array $conditions (optional) * @param object|bool $model (optional) * @return null|object */ public function find_first( $conditions = [] ) { $results = $this->select()->where_and( $conditions )->limit( 1, 0 )->run_query(); if ( $results ) { return $this->convert_to_model( $results[0] ); } else { return null; } } /** * @param array $conditions (optional) * @return array */ public function find_all( $conditions = [] ) { $results = $this->select()->where_and( $conditions )->run_query(); if ( $results ) { foreach ( $results as &$result ) { $result = $this->convert_to_model( $result ); } } return $results; } /** * Filters the query: * array("post_title = %s", "Foo") * OR * array( * array("post_title = %s", "Foo") * ) * * @param array $conditions (optional) * @return self */ public function where_and( $conditions = [] ) { return $this->_where( $conditions, 'AND' ); } /** * @param array $conditions (optional) * @return self */ public function where( $conditions = [] ) { return $this->_where( $conditions, 'AND' ); } /** * Parses the where clauses. They could look like the following: * array( * "post_id = 1" * array("post_id = %d", 1), * ) * * or simply "post_id = 1" * * @param array|string $conditions * @param string $operator * @return self */ public function _where( $conditions, $operator ) { $where_clauses = []; // If conditions is not an array, make it one. if ( ! is_array( $conditions ) ) { $conditions = [ $conditions ]; } // Just a single condition was passed, but with a bind. elseif ( ! empty( $conditions ) && ! is_array( $conditions[0] ) ) { $conditions = [ $conditions ]; } // Iterate through each condition. foreach ( $conditions as $condition ) { if ( is_string( $condition ) ) { $clause = $this->_parse_where_clause( $condition ); if ( $clause ) { $where_clauses[] = $clause; } } else { $clause = array_shift( $condition ); $clause = $this->_parse_where_clause( $clause, $condition ); if ( $clause ) { $where_clauses[] = $clause; } } } // Add where clause to query. if ( $where_clauses ) { $this->add_where_clause( $where_clauses, $operator ); } return $this; } /** * Parses a where clause and returns an associative array * representing the query * * E.g. parse_where_clause("post_title = %s", "Foo Bar") * * @global wpdb $wpdb * @param string $condition * @return array */ public function _parse_where_clause( $condition ) { $column = ''; $operator = ''; $value = ''; $numeric = true; // Substitute any placeholders. global $wpdb; $binds = func_get_args(); $binds = isset( $binds[1] ) ? $binds[1] : []; // first argument is the condition. foreach ( $binds as &$bind ) { // A bind could be an array, used for the 'IN' operator // or a simple scalar value. We need to convert arrays // into scalar values. if ( is_object( $bind ) ) { $bind = (array) $bind; } if ( is_array( $bind ) && ! empty( $bind ) ) { foreach ( $bind as &$val ) { if ( ! is_numeric( $val ) ) { $val = '"' . addslashes( $val ) . '"'; $numeric = false; } } $bind = implode( ',', $bind ); } elseif ( is_array( $bind ) && empty( $bind ) ) { $bind = 'NULL'; } elseif ( ! is_numeric( $bind ) ) { $numeric = false; } } if ( $binds ) { // PHP-CS triggers a false positive on this; $condition is a string that contains the placeholders. // // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $condition = $wpdb->prepare( $condition, $binds ); } // Parse the where clause. if ( preg_match( '/^[^\s]+/', $condition, $match ) ) { $column = trim( array_shift( $match ) ); $condition = str_replace( $column, '', $condition ); } if ( preg_match( '/(NOT )?IN|(NOT )?LIKE|(NOT )?BETWEEN|[=!<>]+/i', $condition, $match ) ) { $operator = trim( array_shift( $match ) ); $condition = str_replace( $operator, '', $condition ); $operator = strtolower( $operator ); $value = trim( $condition ); } // Values will automatically be quoted, so remove them // If the value is part of an IN clause or BETWEEN clause and // has multiple values, we attempt to split the values apart into an // array and iterate over them individually. if ( $operator == 'in' ) { $values = preg_split( "/'?\s?(,)\s?'?/i", $value ); } elseif ( $operator == 'between' ) { $values = preg_split( "/'?\s?(AND)\s?'?/i", $value ); } // If there's a single value, treat it as an array so that we can still iterate. if ( empty( $values ) ) { $values = [ $value ]; } foreach ( $values as $index => $value ) { $value = preg_replace( "/^(\()?'/", '', $value ); $value = preg_replace( "/'(\))?$/", '', $value ); $values[ $index ] = $value; } if ( count( $values ) > 1 ) { $value = $values; } // Return the WP Query meta query parameters. $retval = [ 'column' => $column, 'value' => $value, 'compare' => strtoupper( $operator ), 'type' => $numeric ? 'numeric' : 'string', ]; return $retval; } public function strip_slashes( $stdObject_or_array_or_string ) { /** * Some objects have properties that are recursive objects. To avoid this we have to keep track of what objects * we've already processed when we're running this method recursively. */ static $level = 0; static $processed_objects = []; ++$level; $processed_objects[] = $stdObject_or_array_or_string; if ( is_string( $stdObject_or_array_or_string ) ) { $stdObject_or_array_or_string = str_replace( "\\'", "'", str_replace( '\"', '"', str_replace( '\\\\', '\\', $stdObject_or_array_or_string ) ) ); } elseif ( is_object( $stdObject_or_array_or_string ) && ! in_array( $stdObject_or_array_or_string, $processed_objects ) ) { foreach ( get_object_vars( $stdObject_or_array_or_string ) as $key => $val ) { if ( $val != $stdObject_or_array_or_string && $key != '_mapper' ) { $stdObject_or_array_or_string->$key = $this->strip_slashes( $val ); } } $processed_objects[] = $stdObject_or_array_or_string; } elseif ( is_array( $stdObject_or_array_or_string ) ) { foreach ( $stdObject_or_array_or_string as $key => $val ) { if ( $key != '_mixins' ) { $stdObject_or_array_or_string[ $key ] = $this->strip_slashes( $val ); } } } --$level; if ( $level == 0 ) { $processed_objects = []; } return $stdObject_or_array_or_string; } /** * Converts a stdObject entity to a model * * @param object $stdObject * @param string|bool $context (optional) * @return object */ public function convert_to_model( $stdObject, $context = false ) { try { $this->_convert_to_entity( $stdObject ); } catch ( \Exception $ex ) { throw new \E_InvalidEntityException( $ex ); } return $this->create( $stdObject ); } /** * Determines whether an object is actually a model * * @param mixed $obj * @return bool */ public function is_model( $obj ) { return is_subclass_of( $obj, '\Imagely\NGG\DataMapper\Model' ); } /** * If a field has no value, then use the default value. * * @param \stdClass|Model $object */ public function set_default_value( $object ) { $array = null; $field = null; $default_value = null; // The first argument MUST be an object. if ( ! is_object( $object ) ) { throw new \E_InvalidEntityException(); } // This method has two signatures: // 1) _set_default_value($object, $field, $default_value) // 2) _set_default_value($object, $array_field, $field, $default_value). // Handle #1. $args = func_get_args(); if ( count( $args ) == 4 ) { list($object, $array, $field, $default_value) = $args; if ( ! isset( $object->{$array} ) ) { $object->{$array} = []; $object->{$array}[ $field ] = null; } else { $arr = &$object->{$array}; if ( ! isset( $arr[ $field ] ) ) { $arr[ $field ] = null; } } $array = &$object->{$array}; $value = &$array[ $field ]; if ( $value === '' or is_null( $value ) ) { $value = $default_value; } } // Handle #2. else { list($object, $field, $default_value) = $args; if ( ! isset( $object->$field ) ) { $object->$field = null; } $value = $object->$field; if ( $value === '' or is_null( $value ) ) { $object->$field = $default_value; } } } public function has_defined_column( $name ) { $columns = $this->_columns; return isset( $columns[ $name ] ); } public function cast_columns( $entity ) { foreach ( $this->_columns as $key => $properties ) { $value = property_exists( $entity, $key ) ? $entity->$key : null; $default_value = $properties['default_value']; if ( ! is_null( $value ) && $value !== $default_value ) { $column_type = $this->_columns[ $key ]['type']; if ( preg_match( '/varchar|text/i', $column_type ) ) { if ( ! is_array( $value ) && ! is_object( $value ) ) { $entity->$key = strval( $value ); } } elseif ( preg_match( '/decimal|numeric|double|float/i', $column_type ) ) { $entity->$key = floatval( $value ); } elseif ( preg_match( '/int/i', $column_type ) ) { $entity->$key = intval( $value ); } elseif ( preg_match( '/bool/i', $column_type ) ) { $entity->$key = ( $value ? true : false ); } } else { // Add property and default value. $entity->$key = $default_value; } } return $entity; } /** * Finds a particular entry by id * * @param int|\stdClass|Model $entity * @return null|object|Model */ public function find( $entity ) { $retval = null; // Get primary key of the entity. $pkey = $this->get_primary_key_column(); if ( ! is_numeric( $entity ) ) { $entity = isset( $entity->$pkey ) ? intval( $entity->$pkey ) : false; } // If we have an entity ID, then get the record. if ( $entity ) { $results = $this->select()->where_and( [ "{$pkey} = %d", $entity ] )->limit( 1, 0 )->run_query(); if ( $results ) { $retval = $this->convert_to_model( $results[0] ); } } return $retval; } /** * Converts a stdObject to an Entity * * @param \stdClass $entity * @return object */ public function _convert_to_entity( $entity ) { // Add extra columns to entity. if ( isset( $entity->extras ) ) { $extras = $entity->extras; unset( $entity->extras ); foreach ( explode( ',', $extras ) as $extra ) { if ( $extra ) { $parts = explode( '@@', $extra ); if ( count( $parts ) === 2 ) { // Ensure we have exactly two parts. list( $key, $value ) = $parts; if ( $this->has_defined_column( $key ) && ! isset( $entity->$key ) && $key !== 'extras_post_id' ) { $entity->$key = $value; } } } } } // Cast custom_post_id as integer. if ( isset( $entity->extras_post_id ) ) { $entity->extras_post_id = intval( $entity->extras_post_id ); } else { $entity->extras_post_id = 0; } // Add name of the id_field to the entity, and convert the ID to an integer. $entity->id_field = $this->get_primary_key_column(); // Cast columns to their appropriate data type. $this->cast_columns( $entity ); // Strip slashes. $this->strip_slashes( $entity ); // Deserialize columns. $this->deserialize_columns( $entity ); return $entity; } /** * Creates a new model * * @param array $properties (optional) * @return object */ public function create( $properties = [] ) { $entity = new \stdClass(); foreach ( $properties as $key => $value ) { $entity->$key = $value; } return new $this->model_class( $entity ); } /** * Saves an entity * * @param \stdClass|Model $entity * @return bool|int Resulting ID or false upon failure */ public function save( $entity ) { $retval = false; $model = $entity; $this->flush_query_cache(); if ( is_array( $entity ) ) { throw new \E_InvalidEntityException(); } elseif ( ! $this->is_model( $entity ) ) { // We can work with what we have. But we need to ensure that we've got a model. $model = $this->convert_to_model( $entity ); } if ( ! is_array( $model->validation() ) ) { $retval = $this->save_entity( $model ); } $this->flush_query_cache(); return $retval; } /** * Gets validation errors for the entity * * @param \stdClass|Model $entity * @return array */ public function get_errors( $entity ) { $model = $entity; if ( ! $this->is_model( $entity ) ) { $model = $this->convert_to_model( $entity ); } return $model->validation(); } /** * @param object $entity */ public function set_defaults( $entity ) {} /** * @param string $name * @param string $type * @param string|number $default_value * @param bool $extra * @return void */ public function define_column( $name, $type, $default_value = null, $extra = false ) { $this->_columns[ $name ] = [ 'type' => $type, 'default_value' => $default_value, 'extra' => $extra, ]; } } PK!^W==?=?DataMapper/TableDriver.phpnu[primary_key_column ) ) { $this->primary_key_column = $this->_lookup_primary_key_column(); } $this->migrate(); } catch ( \Exception $exception ) { } // Each record in a NextGEN Gallery table has an associated custom post in the wp_posts table. $this->_custom_post_mapper = new WPPostDriver( $this->get_object_name() ); $this->_custom_post_mapper->model_class = 'Imagely\NGG\DataTypes\DataMapperExtraFields'; } /** * Returns the database connection object for WordPress * * @global \wpdb $wpdb * @return \wpdb */ public function _wpdb() { global $wpdb; return $wpdb; } /** * Looks up the primary key column for this table * * @throws \Exception */ public function _lookup_primary_key_column() { $key = $this->_wpdb()->get_row( "SHOW INDEX FROM {$this->get_table_name()} WHERE Key_name='PRIMARY'", ARRAY_A ); if ( ! $key ) { throw new \Exception( "Please specify the primary key for {$this->get_table_name ()}" ); } return $key['Column_name']; } /** * Gets the name of the primary key column * * @return string */ public function get_primary_key_column() { return $this->primary_key_column; } /** * Determines whether we're going to execute a SELECT statement * * @return boolean */ public function is_select_statement() { return (bool) $this->select_clause; } /** * Determines if we're going to be executing a DELETE statement * * @return bool */ public function is_delete_statement() { return (bool) $this->delete_clause; } /** * Orders the results of the query * This method may be used multiple of times to order by more than column * * @param $order_by * @param $direction * @return self */ public function order_by( $order_by, $direction = 'ASC' ) { // We treat the rand() function as an exception. if ( preg_match( '/rand\(\s*\)/', $order_by ) ) { $order = 'rand()'; } else { $order_by = $this->_clean_column( $order_by ); // If the order by clause is a column, then it should be backticked. if ( $this->has_column( $order_by ) ) { $order_by = "`{$order_by}`"; } $direction = $this->_clean_column( $direction ); $order = "{$order_by} {$direction}"; } $this->order_clauses[] = $order; return $this; } /** * Specifies a limit and optional offset * * @param integer $max * @param integer $offset * @return self */ public function limit( $max, $offset = 0 ) { if ( $offset ) { $limit = $this->_wpdb()->prepare( 'LIMIT %d, %d', max( 0, $offset ), $max ); } else { $limit = $this->_wpdb()->prepare( 'LIMIT %d', max( 0, $max ) ); } /*** * Set $limit to false when we want to display all records, that is $items_per_page = all. * LIMIT 0 results in no entries found error. So we remove limit_clause altogether. */ if ( (int) $max < 0 ) { $limit = false; $this->limit_clause = false; } if ( $limit ) { $this->limit_clause = $limit; } return $this; } /** * Specifics a group by clause for one or more columns * * @param array|string $columns * @return self */ public function group_by( $columns = [] ) { if ( ! is_array( $columns ) ) { $columns = [ $columns ]; } $this->group_by_columns = array_merge( $this->group_by_columns, $columns ); return $this; } /** * Adds a where clause to the driver * * @param array $where_clauses * @param string $join */ public function add_where_clause( $where_clauses, $join ) { $clauses = []; foreach ( $where_clauses as $clause ) { extract( $clause ); if ( $this->has_column( $column ) ) { $column = "`{$column}`"; } if ( ! is_array( $value ) ) { $value = [ $value ]; } foreach ( $value as $index => $v ) { $v = $clause['type'] == 'numeric' ? $v : "'{$v}'"; $value[ $index ] = $v; } if ( $compare == 'BETWEEN' ) { $value = "{$value[0]} AND {$value[1]}"; } else { $value = implode( ', ', $value ); if ( strpos( $compare, 'IN' ) !== false ) { $value = "({$value})"; } } $clauses[] = "{$column} {$compare} {$value}"; } $this->where_clauses[] = implode( " {$join} ", $clauses ); } /** * Returns the total number of entities known * * @return int */ public function count() { $retval = 0; $key = $this->get_primary_key_column(); /** @noinspection SqlResolve */ $results = $this->run_query( "SELECT COUNT(`{$key}`) AS `{$key}` FROM `{$this->get_table_name()}`" ); if ( $results && isset( $results[0]->$key ) ) { $retval = (int) $results[0]->$key; } return $retval; } /** * Run the query * * @param string|bool $sql (optional) run the specified SQL * @param object|bool $model (optional) * @param bool $no_entities (optional) * @return array */ public function run_query( $sql = false, $model = false, $no_entities = false ) { $results = false; $retval = []; // Or generate SQL query. if ( ! $sql ) { $sql = $this->get_generated_query( $no_entities ); } // If we have a SQL statement to execute, then heck, execute it!. if ( $sql ) { if ( $this->debug ) { var_dump( $sql ); } // Try getting the result from cache first. if ( $this->is_select_statement() && $this->use_cache ) { $results = $this->get_from_cache( $sql ); } } if ( ! $results ) { $this->_wpdb()->query( $sql ); $results = $this->_wpdb()->last_result; if ( $this->is_select_statement() ) { $this->cache( $sql, $results ); } } if ( $results ) { $retval = []; // For each row, create an entity, update its properties, and add it to the result set. if ( $no_entities ) { $retval = $results; } else { $id_field = $this->get_primary_key_column(); foreach ( $results as $row ) { if ( $row ) { if ( isset( $row->$id_field ) ) { if ( $model ) { $retval[] = $this->convert_to_model( $row ); } else { $retval[] = $this->_convert_to_entity( $row ); } } } } } } elseif ( $this->debug ) { var_dump( 'No entities returned from query' ); } // Just a safety check. if ( ! $retval ) { $retval = []; } return $retval; } /** * Converts an entity to something suitable for inserting into a database column * * @param object $entity * @return array */ public function _convert_to_table_data( $entity ) { $data = (array) $entity; foreach ( $data as $key => $value ) { if ( ! isset( $this->_columns[ $key ] ) || $this->_columns[ $key ]['extra'] ) { unset( $data[ $key ] ); continue; } if ( is_array( $value ) ) { $data[ $key ] = Serializable::serialize( $value ); } } return $data; } public function get_column_names() { return array_keys( $this->_columns ); } /** * Migrates the schema of the database * * @throws \Exception */ public function migrate() { if ( ! $this->_columns ) { throw new \Exception( "Columns not defined for {$this->get_table_name()}" ); } $added = false; $removed = false; // Add any missing columns. foreach ( $this->_columns as $key => $properties ) { if ( ! in_array( $key, $this->_table_columns ) ) { if ( $this->_add_column( $key, $properties['type'], $properties['default_value'] ) ) { $added = true; } } } if ( $added or $removed ) { $this->lookup_columns(); } } public function _init() { $this->where_clauses = []; $this->order_clauses = []; $this->group_by_columns = []; $this->limit_clause = ''; $this->select_clause = ''; } /** * Selects which fields to collect from the table. * NOTE: Not protected from SQL injection - DO NOT let your users specify DB columns * * @param string $fields * @return self */ public function select( $fields = null ) { // Create a fresh slate. $this->_init(); if ( ! $fields or $fields == '*' ) { $fields = $this->get_table_name() . '.*'; } $this->select_clause = "SELECT {$fields}"; return $this; } /** * Start a delete statement */ public function delete() { // Create a fresh slate. $this->_init(); $this->delete_clause = 'DELETE'; return $this; } /** * Stores the entity * * @param object $entity * @return bool|self */ public function save_entity( $entity ) { $retval = false; unset( $entity->id_field ); $primary_key = $this->get_primary_key_column(); if ( isset( $entity->$primary_key ) && $entity->$primary_key > 0 ) { if ( $this->_update( $entity ) ) { $retval = intval( $entity->$primary_key ); } } else { $retval = $this->_create( $entity ); if ( $retval ) { $new_entity = $this->find( $retval ); foreach ( $new_entity as $key => $value ) { $entity->$key = $value; } } } $entity->id_field = $primary_key; // Clean cache. if ( $retval ) { $this->cache = []; } return $retval; } /** * Destroys/deletes an entity * * @param object|Model|int $entity * @return boolean */ public function destroy( $entity ) { $retval = false; $key = $this->get_primary_key_column(); if ( isset( $entity->extras_post_id ) ) { \wp_delete_post( $entity->extras_post_id, true ); } // Find the id of the entity. if ( is_object( $entity ) && isset( $entity->$key ) ) { $id = (int) $entity->$key; } else { $id = (int) $entity; } // If we have an ID, then delete the post. if ( is_numeric( $id ) ) { $sql = $this->_wpdb()->prepare( "DELETE FROM `{$this->get_table_name()}` WHERE {$key} = %s", $id ); $retval = $this->_wpdb()->query( $sql ); } return $retval; } /** * @param object $entity * @return boolean */ public function _create( $entity ) { $retval = false; $custom_post_entity = $this->create_custom_post_entity( $entity ); // Try persisting the custom post type record first. if ( ( $custom_post_id = $this->_custom_post_mapper->save( $custom_post_entity ) ) ) { $entity->extras_post_id = $custom_post_id; } $table_data = $this->_convert_to_table_data( $entity ); $id = $this->_wpdb()->insert( $this->get_table_name(), $table_data ); if ( $id ) { $key = $this->get_primary_key_column(); $retval = $entity->$key = intval( $this->_wpdb()->insert_id ); } // Remove the custom post if saving the normal table entry failed. if ( ! $retval && isset( $custom_post_id ) ) { $this->_custom_post_mapper->destroy( $custom_post_id ); } return $retval; } /** * Updates a record in the database * * @param object $entity * @return int|bool */ public function _update( $entity ) { $key = $this->get_primary_key_column(); $custom_post_entity = $this->create_custom_post_entity( $entity ); $custom_post_id = $this->_custom_post_mapper->save( $custom_post_entity ); $entity->extras_post_id = $custom_post_id; $table_data = $this->_convert_to_table_data( $entity ); $retval = $this->_wpdb()->update( $this->get_table_name(), $table_data, [ $key => $entity->$key, ] ); foreach ( $this->get_extra_columns() as $key ) { if ( isset( $custom_post_entity->$key ) ) { $entity->$key = $custom_post_entity->$key; } } return $retval; } /** * @param string $column_name * @param string $datatype * @param string|number $default_value * @return bool */ public function _add_column( $column_name, $datatype, $default_value = null ) { if ( isset( $this->_columns[ $column_name ] ) && $this->_columns[ $column_name ]['extra'] ) { return false; } /** @noinspection SqlResolve */ $sql = "ALTER TABLE `{$this->get_table_name()}` ADD COLUMN `{$column_name}` {$datatype}"; if ( $default_value ) { if ( is_string( $default_value ) ) { $default_value = str_replace( "'", "\\'", $default_value ); } $sql .= ' NOT NULL DEFAULT ' . ( is_string( $default_value ) ? "'{$default_value}" : "{$default_value}" ); } $return = (bool) $this->_wpdb()->query( $sql ); $this->update_columns_cache(); return $return; } /** * @param bool $no_entities Default: false * @return array|string|string[] */ public function get_generated_query( $no_entities = false ) { // Add extras column. if ( $this->is_select_statement() && stripos( $this->select_clause, 'count(' ) === false ) { $table_name = $this->get_table_name(); $primary_key = "{$table_name}.{$this->get_primary_key_column()}"; if ( stripos( $this->select_clause, 'DISTINCT' ) === false ) { $this->select_clause = str_replace( 'SELECT', 'SELECT DISTINCT', $this->select_clause ); } $this->group_by( $primary_key ); $sql = $this->get_actual_generated_query( $no_entities ); // Sections may be omitted by wrapping them in mysql's C style comments. if ( stripos( $sql, '/*NGG_NO_EXTRAS_TABLE*/' ) !== false ) { $parts = explode( '/*NGG_NO_EXTRAS_TABLE*/', $sql ); foreach ( $parts as $ndx => $row ) { if ( $ndx % 2 != 0 ) { continue; } $parts[ $ndx ] = $this->_regex_replace( $row ); } $sql = implode( '', $parts ); } else { $sql = $this->_regex_replace( $sql ); } } else { $sql = $this->get_actual_generated_query( $no_entities ); } return $sql; } /** * @param bool $no_entities Default = false * @return string */ public function get_actual_generated_query( $no_entities = false ) { $sql = []; if ( $this->is_select_statement() ) { $sql[] = $this->select_clause; } elseif ( $this->is_delete_statement() ) { $sql[] = $this->delete_clause; } $sql[] = 'FROM `' . $this->get_table_name() . '`'; $where_clauses = []; foreach ( $this->where_clauses as $where ) { $where_clauses[] = '(' . $where . ')'; } if ( $where_clauses ) { $sql[] = 'WHERE ' . implode( ' AND ', $where_clauses ); } if ( $this->is_select_statement() ) { if ( $this->group_by_columns ) { $sql[] = 'GROUP BY ' . implode( ', ', $this->group_by_columns ); } if ( $this->order_clauses ) { $sql[] = 'ORDER BY ' . implode( ', ', $this->order_clauses ); } if ( $this->limit_clause ) { $sql[] = $this->limit_clause; } } return implode( ' ', $sql ); } /** * @return array */ public function get_extra_columns() { $retval = []; foreach ( $this->_columns as $key => $properties ) { if ( $properties['extra'] ) { $retval[] = $key; } } return $retval; } public function create_custom_post_entity( $entity ) { $custom_post_entity = new \stdClass(); // If the custom post entity already exists then it needs an ID. if ( isset( $entity->extras_post_id ) ) { $custom_post_entity->ID = $entity->extras_post_id; } // If a property isn't a column for the table, then it belongs to the custom post record. foreach ( get_object_vars( $entity ) as $key => $value ) { if ( ! $this->has_column( $key ) ) { unset( $entity->$key ); if ( $this->has_defined_column( $key ) && $key != $this->get_primary_key_column() ) { $custom_post_entity->$key = $value; } } } // Used to help find these type of records. $custom_post_entity->post_name = $this->custom_post_name; return $custom_post_entity; } public function _regex_replace( $in ) { global $wpdb; $from = 'FROM `' . $this->get_table_name() . '`'; $out = str_replace( 'FROM', ", GROUP_CONCAT(CONCAT_WS('@@', meta_key, meta_value)) AS 'extras' FROM", $in ); $out = str_replace( $from, "{$from} LEFT OUTER JOIN `{$wpdb->postmeta}` ON `{$wpdb->postmeta}`.`post_id` = `extras_post_id` ", $out ); return $out; } } PK!iTDataMapper/Model.phpnu[ namespace transition will // still retain this attribute and generate a warning with PHP 8.0 when hydrating the object. public $__defaults_set; public function __construct( \stdClass $object = null ) { if ( $object ) { foreach ( get_object_vars( $object ) as $key => $value ) { $this->$key = $value; } } $this->set_defaults(); } abstract function get_mapper(); /** * This should be removed when POPE compat v1 is reached in Pro * * @deprecated * @return bool|array */ public function validate() { return $this->validation(); } public function validation() { return true; } public function set_defaults() { $mapper = $this->get_mapper(); if ( method_exists( $mapper, 'set_defaults' ) ) { $mapper->set_defaults( $this ); } } /** * @return bool */ public function is_new() { return ! $this->id(); } public function get_primary_key_column() { return 'id'; } /** * @param null|int|string $value (optional) * @return mixed */ public function id( $value = null ) { $key = $this->get_primary_key_column(); if ( $value ) { $this->$key = $value; } return $this->$key; } /** * This should be removed when POPE compat v1 is reached in Pro * * @deprecated * @return array */ public function get_errors() { return $this->validation(); } /** * Necessary for compatibility with some WP-Admin pages. * * @deprecated */ public function clear_errors() { return true; } /** * Determines if a particular field for the object has errors * * @param string $property * @return bool */ public function is_valid( $property = null ) { $errors = $this->validation(); return ! ( is_array( $errors ) && isset( $errors[ $property ] ) ); } /** * @param array $updated_attributes * @return int|bool Object ID or false upon failure */ public function save( $updated_attributes = [] ) { foreach ( $updated_attributes as $key => $value ) { $this->$key = $value; } return $this->get_mapper()->save( $this ); } } PK!&P,+,+DataMapper/Validation.phpnu[ $str * @return string */ public function humanize_string( $str ) { $retval = []; if ( is_array( $str ) ) { foreach ( $str as $s ) { $retval[] = $this->humanize_string( $s ); } } else { $retval = ucfirst( str_replace( '_', ' ', $str ) ); } return $retval; } /** * Returns TRUE if a property is empty. * * @deprecated Don't use this, it's silly. * @param string $var * @return bool */ public function is_empty( $var, $element = false ) { if ( is_array( $var ) && $element ) { if ( isset( $var[ $element ] ) ) { $var = $var[ $element ]; } else { $var = false; } } return ( is_null( $var ) or ( is_string( $var ) and strlen( $var ) == 0 ) or $var === false ); } /** * @param string $property * @param int $length * @param string $comparison_operator ===, !=, <, >, <=, or >= * @param bool|string $msg * @return array */ public function validates_length_of( $property, $length, $comparison_operator = '=', $msg = false ) { $valid = true; $default_msg = $this->_get_default_error_message_for( __METHOD__ ); if ( ! $this->is_empty( $this->$property ) ) { switch ( $comparison_operator ) { case '=': case '==': $valid = strlen( $this->$property ) == $length; $default_msg = $this->_get_default_error_message_for( 'validates_equals' ); break; case '!=': case '!': $valid = strlen( $this->$property ) != $length; $default_msg = $this->_get_default_error_message_for( 'validates_equals' ); break; case '<': $valid = strlen( $this->$property ) < $length; $default_msg = $this->_get_default_error_message_for( 'validates_less_than' ); break; case '>': $valid = strlen( $this->$property ) > $length; $default_msg = $this->_get_default_error_message_for( 'validates_greater_than' ); break; case '<=': $valid = strlen( $this->$property ) <= $length; $default_msg = $this->_get_default_error_message_for( 'validates_less_than' ); break; case '>=': $valid = strlen( $this->$property ) >= $length; $default_msg = $this->_get_default_error_message_for( 'validates_greater_than' ); break; } } else { $valid = false; } if ( ! $valid ) { if ( ! $msg ) { $error_msg = sprintf( $default_msg, $this->humanize_string( $property ) ); } else { $error_msg = $msg; } return [ $property => [ $error_msg ] ]; } return []; } /** * @param string $property * @param int|float $comparison * @param string $comparison_operator * @param string $msg * @return array */ public function validates_numericality_of( $property, $comparison = false, $comparison_operator = false, $int_only = false, $msg = false ) { $default_msg = $this->_get_default_error_message_for( __METHOD__ ); if ( ! $this->is_empty( $this->$property ) ) { $invalid = false; if ( is_numeric( $this->$property ) ) { $this->$property += 0; if ( $int_only ) { $invalid = ! is_int( $this->$property ); } if ( ! $invalid ) { switch ( $comparison_operator ) { case '=': case '==': $invalid = ( $this->$property == $comparison ) ? false : true; $default_msg = $this->_get_default_error_message_for( 'validates_equals' ); break; case '!=': case '!': $invalid = ( $this->$property != $comparison ) ? false : true; $default_msg = $this->_get_default_error_message_for( 'validates_equals' ); break; case '<': $invalid = ( $this->$property < $comparison ) ? false : true; $default_msg = $this->_get_default_error_message_for( 'validates_less_than' ); break; case '>': $invalid = ( $this->$property > $comparison ) ? false : true; $default_msg = $this->_get_default_error_message_for( 'validates_greater_than' ); break; case '<=': $invalid = ( $this->$property <= $comparison ) ? false : true; $default_msg = $this->_get_default_error_message_for( 'validates_less_than' ); break; case '>=': $invalid = ( $this->$property >= $comparison ) ? false : true; $default_msg = $this->_get_default_error_message_for( 'validates_greater_than' ); break; } } } else { $invalid = true; } if ( $invalid ) { if ( ! $msg ) { $error_msg = sprintf( $default_msg, $this->humanize_string( $property ) ); } else { $error_msg = $msg; } return [ $property => [ $error_msg ] ]; } } return []; } /** * @param string $property * @param array $values * @param string $msg * @return array */ public function validates_inclusion_of( $property, $values = [], $msg = false ) { if ( ! is_array( $values ) ) { $values = [ $values ]; } if ( ! in_array( $this->$property, $values ) ) { if ( ! $msg ) { $msg = $this->_get_default_error_message_for( __METHOD__ ); $msg = sprintf( $msg, $this->humanize_string( $property ) ); } return [ $property => [ $msg ] ]; } return []; } /** * @param string|array $property * @param string $pattern * @param string $msg * @return array */ public function validates_format_of( $property, $pattern, $msg = false ) { // We do not validate blank values - we rely on "validates_presence_of" for that. if ( ! $this->is_empty( $this->$property ) ) { // If it doesn't match, then it's an error. if ( ! preg_match( $pattern, $this->$property ) ) { // Get default message. if ( ! $msg ) { $msg = $this->_get_default_error_message_for( __METHOD__ ); $msg = sprintf( $msg, $this->humanize_string( $property ) ); } return [ $property => [ $msg ] ]; } } return []; } /** * @param string $property * @param array $exclusions * @param string $msg (optional) * @return array */ public function validates_exclusion_of( $property, $exclusions, $msg = false ) { $invalid = false; foreach ( $exclusions as $exclusion ) { if ( $exclusion == $this->$property ) { $invalid = true; break; } } if ( $invalid ) { if ( ! $msg ) { $msg = $this->_get_default_error_message_for( __METHOD__ ); $msg = sprintf( $msg, $this->humanize_string( $property ) ); } return [ $property => [ $msg ] ]; } return []; } /** * @param string $property * @param string $confirmation * @param string $msg * @return array */ public function validates_confirmation_of( $property, $confirmation, $msg = false ) { if ( $this->$property != $this->$confirmation ) { if ( ! $msg ) { $msg = $this->_get_default_error_message_for( __METHOD__ ); $msg = sprintf( $msg, $this->humanize_string( $property ) ); } return [ $property => [ $msg ] ]; } return []; } /** * @param string $property * @param array $scope * @param string $msg * @return array */ public function validates_uniqueness_of( $property, $scope = [], $msg = false ) { // Get any entities that have the same property. $mapper = $this->get_mapper(); $key = $mapper->get_primary_key_column(); $mapper->select( $key ); $mapper->limit( 1 ); $mapper->where_and( [ "{$property} = %s", $this->$property ] ); if ( ! $this->is_new() ) { $mapper->where_and( [ "{$key} != %s", $this->id() ] ); } foreach ( $scope as $another_property ) { $mapper->where_and( [ "{$another_property} = %s", $another_property ] ); } $result = $mapper->run_query(); // If there's a result, it means that the entity is NOT unique. if ( $result ) { // Get default msg. if ( ! $msg ) { $msg = $this->_get_default_error_message_for( __METHOD__ ); $msg = sprintf( $msg, $this->humanize_string( $property ) ); } return [ $property => [ $msg ] ]; } return []; } /** * @param string $property * @param array $with * @param string $msg * @return array */ public function validates_presence_of( $property, $with = [], $msg = false ) { $missing = []; $invalid = true; // Is a value present? if ( ! $this->is_empty( $this->$property ) ) { $invalid = false; // This property must be present with at least another property. if ( $with ) { if ( ! is_array( $with ) ) { $with = [ $with ]; } foreach ( $with as $other ) { if ( $this->is_empty( $this->$other ) ) { $invalid = true; $missing[] = $other; } } } } // Add error. if ( $invalid ) { if ( ! $msg ) { // If missing isn't empty, it means that we're to use the "with" error message. if ( $missing ) { $missing = implode( ', ', $this->humanize_string( $missing ) ); $msg = sprintf( $this->_get_default_error_message_for( 'validates_presence_with' ), $property, $missing ); } else { // Has no 'with' arguments. Use the default error msg. $msg = sprintf( $this->_get_default_error_message_for( __METHOD__ ), $property ); } } return [ $property => [ $msg ] ]; } return []; } } /** * This class exists to prevent the Validation trait from adding any new attributes to the classes that use it and is * only used by the above Validation trait. */ class ValidationMessages { public static $default_messages = [ 'validates_presence_of' => '%s should be present', 'validates_presence_with' => '%s should be present with %s', 'validates_uniqueness_of' => '%s should be unique', 'validates_confirmation_of' => '%s should match confirmation', 'validates_exclusion_of' => '%s is reserved', 'validates_format_of' => '%s is invalid', 'validates_inclusion_of' => '%s is not included in the list', 'validates_numericality_of' => '%s is not numeric', 'validates_less_than' => '%s is too small', 'validates_greater_than' => '%s is too large', 'validates_equals' => '%s is invalid', ]; public static $default_patterns = [ 'email_address' => '//', ]; } PK!غBt[t[DataStorage/Manager.phpnu[gallery_mapper = GalleryMapper::get_instance(); $this->image_mapper = ImageMapper::get_instance(); /** * @TODO Remove in a later release - this fixes an issue with Imagify at the time of 3.50's release. */ $this->object = $this; $this->_image_mapper = $this->image_mapper; } /** * @return Manager */ static function get_instance() { if ( ! isset( self::$instance ) ) { self::$instance = new Manager(); } return self::$instance; } public function has_method( $name ) { return method_exists( $this, $name ); } /** * @TODO: Remove this 'magic' method so that our code is always understandable without needing deep context * @param string $method * @param array $args * @return mixed * @throws \Exception */ public function __call( $method, $args ) { if ( preg_match( '/^get_(\w+)_(abspath|url|dimensions|html|size_params)$/', $method, $match ) ) { if ( isset( $match[1] ) && isset( $match[2] ) && ! method_exists( $this, $method ) ) { $method = 'get_image_' . $match[2]; $args[] = $match[1]; return $this->$method( $args ); } } return $this->$method( $args ); } /** * Remove after Pro attains level 1 compatibility with the POPE removal */ public function get_wrapped_instance() { return $this; } /** * Remove after Pro attains level 1 compatibility with the POPE removal */ public function add_mixin( $unused = '' ) {} /** * Backs up an image file * * @param int|object $image * @param bool $save * @return bool */ public function backup_image( $image, $save = true ) { $retval = false; $image_path = $this->get_image_abspath( $image ); if ( $image_path && @file_exists( $image_path ) ) { $retval = copy( $image_path, $this->get_backup_abspath( $image ) ); // Store the dimensions of the image. if ( function_exists( 'getimagesize' ) ) { $mapper = ImageMapper::get_instance(); if ( ! is_object( $image ) ) { $image = $mapper->find( $image ); } if ( $image ) { if ( empty( $image->meta_data ) || ! is_array( $image->meta_data ) ) { $image->meta_data = []; } $dimensions = getimagesize( $image_path ); $image->meta_data['backup'] = [ 'filename' => basename( $image_path ), 'width' => $dimensions[0], 'height' => $dimensions[1], 'generated' => microtime(), ]; if ( $save ) { $mapper->save( $image ); } } } } return $retval; } /** * @param string $zipfile * @param string $dest_path * @return bool false on failure */ public function extract_zip( $zipfile, $dest_path ) { wp_mkdir_p( $dest_path ); if ( class_exists( 'ZipArchive', false ) && apply_filters( 'unzip_file_use_ziparchive', true ) ) { $zipObj = new \ZipArchive(); if ( $zipObj->open( $zipfile ) === false ) { return false; } for ( $i = 0; $i < $zipObj->numFiles; $i++ ) { $filename = $zipObj->getNameIndex( $i ); if ( ! $this->is_allowed_image_extension( $filename ) ) { continue; } $zipObj->extractTo( $dest_path, [ $zipObj->getNameIndex( $i ) ] ); } } else { require_once ABSPATH . 'wp-admin/includes/class-pclzip.php'; $zipObj = new \PclZip( $zipfile ); $zipContent = $zipObj->listContent(); $indexesToExtract = []; foreach ( $zipContent as $zipItem ) { if ( $zipItem['folder'] ) { continue; } if ( ! $this->is_allowed_image_extension( $zipItem['stored_filename'] ) ) { continue; } $indexesToExtract[] = $zipItem['index']; } if ( ! $zipObj->extractByIndex( implode( ',', $indexesToExtract ), $dest_path ) ) { return false; } } return true; } /** * Gets the id of a gallery, regardless of whether an integer or object was passed as an argument * * @param mixed $gallery_obj_or_id * @return null|int */ public function get_gallery_id( $gallery_obj_or_id ) { $retval = null; $gallery_key = $this->gallery_mapper->get_primary_key_column(); if ( is_object( $gallery_obj_or_id ) ) { if ( isset( $gallery_obj_or_id->$gallery_key ) ) { $retval = $gallery_obj_or_id->$gallery_key; } } elseif ( is_numeric( $gallery_obj_or_id ) ) { $retval = $gallery_obj_or_id; } return $retval; } /** * Empties the gallery cache directory of content * * @param object $gallery */ public function flush_cache( $gallery ) { $fs = Filesystem::get_instance(); $fs->flush_directory( $this->get_cache_abspath( $gallery ) ); } /** * Returns an array of dimensional properties (width, height, real_width, real_height) of a resulting clone image if and when generated * * @param object|int $image Image ID or an image object * @param string $size * @param array $params * @param bool $skip_defaults * @return bool|array */ public function calculate_image_size_dimensions( $image, $size, $params = null, $skip_defaults = false ) { $retval = false; // Get the image entity. if ( is_numeric( $image ) ) { $image = $this->image_mapper->find( $image ); } // Ensure we have a valid image. if ( $image ) { $params = $this->get_image_size_params( $image, $size, $params, $skip_defaults ); // Get the image filename. $image_path = $this->get_image_abspath( $image, 'full', true ); $clone_path = $this->get_image_abspath( $image, $size ); $retval = $this->calculate_image_clone_dimensions( $image_path, $clone_path, $params ); } return $retval; } /** * Generates a "clone" for an existing image, the clone can be altered using the $params array * * @param string $image_path * @param string $clone_path * @param array $params * @return null|object */ public function generate_image_clone( $image_path, $clone_path, $params ) { $crop = isset( $params['crop'] ) ? $params['crop'] : null; $watermark = isset( $params['watermark'] ) ? $params['watermark'] : null; $reflection = isset( $params['reflection'] ) ? $params['reflection'] : null; $rotation = isset( $params['rotation'] ) ? $params['rotation'] : null; $flip = isset( $params['flip'] ) ? $params['flip'] : ''; $destpath = null; $thumbnail = null; $result = $this->calculate_image_clone_result( $image_path, $clone_path, $params ); // XXX this should maybe be removed and extra settings go into $params? $settings = apply_filters( 'ngg_settings_during_image_generation', Settings::get_instance()->to_array() ); // Ensure we have a valid image. if ( $image_path && @file_exists( $image_path ) && null != $result && ! isset( $result['error'] ) ) { $image_dir = dirname( $image_path ); $clone_path = $result['clone_path']; $clone_dir = $result['clone_directory']; $clone_format = $result['clone_format']; $format_list = $this->get_image_format_list(); // Ensure target directory exists, but only create 1 subdirectory. if ( ! @file_exists( $clone_dir ) ) { if ( strtolower( realpath( $image_dir ) ) != strtolower( realpath( $clone_dir ) ) ) { if ( strtolower( realpath( $image_dir ) ) == strtolower( realpath( dirname( $clone_dir ) ) ) ) { wp_mkdir_p( $clone_dir ); } } } $method = $result['method']; $width = $result['width']; $height = $result['height']; $quality = $result['quality']; if ( null === $quality ) { $quality = 100; } // phpcs:ignore WordPress.WP.CapitalPDangit.MisspelledInText if ( $method == 'wordpress' ) { $original = wp_get_image_editor( $image_path ); $destpath = $clone_path; if ( ! is_wp_error( $original ) ) { $original->resize( $width, $height, $crop ); $original->set_quality( $quality ); $original->save( $clone_path ); } } elseif ( $method == 'nextgen' ) { $destpath = $clone_path; $thumbnail = new LegacyThumbnail( $image_path, true ); if ( ! $thumbnail->error ) { if ( $crop ) { $crop_area = $result['crop_area']; $crop_x = $crop_area['x']; $crop_y = $crop_area['y']; $crop_width = $crop_area['width']; $crop_height = $crop_area['height']; $thumbnail->crop( $crop_x, $crop_y, $crop_width, $crop_height ); } $thumbnail->resize( $width, $height ); } else { $thumbnail = null; } } // We successfully generated the thumbnail. if ( is_string( $destpath ) && ( @file_exists( $destpath ) || $thumbnail != null ) ) { if ( $clone_format != null ) { if ( isset( $format_list[ $clone_format ] ) ) { $clone_format_extension = $format_list[ $clone_format ]; $clone_format_extension_str = null; if ( $clone_format_extension != null ) { $clone_format_extension_str = '.' . $clone_format_extension; } $destpath_info = I18N::mb_pathinfo( $destpath ); $destpath_extension = $destpath_info['extension']; if ( strtolower( $destpath_extension ) != strtolower( $clone_format_extension ) ) { $destpath_dir = $destpath_info['dirname']; $destpath_basename = $destpath_info['filename']; $destpath_new = $destpath_dir . DIRECTORY_SEPARATOR . $destpath_basename . $clone_format_extension_str; if ( ( @file_exists( $destpath ) && rename( $destpath, $destpath_new ) ) || $thumbnail != null ) { $destpath = $destpath_new; } } } } if ( is_null( $thumbnail ) ) { $thumbnail = new LegacyThumbnail( $destpath, true ); if ( $thumbnail->error ) { $thumbnail = null; return null; } } else { $thumbnail->fileName = $destpath; } // This is quite odd, when watermark equals int(0) it seems all statements below ($watermark == 'image') and ($watermark == 'text') both evaluate as true // so we set it at null if it evaluates to any null-like value. if ( null === $watermark ) { $watermark = null; } if ( 1 == $watermark || true === $watermark ) { $watermark_setting_keys = [ 'wmFont', 'wmType', 'wmPos', 'wmXpos', 'wmYpos', 'wmPath', 'wmText', 'wmOpaque', 'wmFont', 'wmSize', 'wmColor', ]; foreach ( $watermark_setting_keys as $watermark_key ) { if ( ! isset( $params[ $watermark_key ] ) ) { $params[ $watermark_key ] = $settings[ $watermark_key ]; } } if ( in_array( strval( $params['wmType'] ), [ 'image', 'text' ], true ) ) { $watermark = $params['wmType']; } else { $watermark = 'text'; } } $watermark = strval( $watermark ); if ( $watermark == 'image' ) { $thumbnail->watermarkImgPath = $params['wmPath']; $thumbnail->watermarkImage( $params['wmPos'], $params['wmXpos'], $params['wmYpos'] ); } elseif ( $watermark == 'text' ) { $thumbnail->watermarkText = $params['wmText']; $thumbnail->watermarkCreateText( $params['wmColor'], $params['wmFont'], $params['wmSize'], $params['wmOpaque'] ); $thumbnail->watermarkImage( $params['wmPos'], $params['wmXpos'], $params['wmYpos'] ); } if ( $rotation && in_array( abs( $rotation ), [ 90, 180, 270 ], true ) ) { $thumbnail->rotateImageAngle( $rotation ); } $flip = strtolower( $flip ); if ( $flip && in_array( $flip, [ 'h', 'v', 'hv' ], true ) ) { $flip_h = in_array( $flip, [ 'h', 'hv' ], true ); $flip_v = in_array( $flip, [ 'v', 'hv' ], true ); $thumbnail->flipImage( $flip_h, $flip_v ); } if ( $reflection ) { $thumbnail->createReflection( 40, 40, 50, false, '#a4a4a4' ); } // Force format. if ( $clone_format != null && isset( $format_list[ $clone_format ] ) ) { $thumbnail->format = strtoupper( $format_list[ $clone_format ] ); } $thumbnail = apply_filters( 'ngg_before_save_thumbnail', $thumbnail ); // Always retrieve metadata from the backup when possible. $backup_path = $image_path . '_backup'; $exif_abspath = @file_exists( $backup_path ) ? $backup_path : $image_path; $exif_iptc = EXIFWriter::read_metadata( $exif_abspath ); $thumbnail->save( $destpath, $quality ); @EXIFWriter::write_metadata( $destpath, $exif_iptc ); } } return $thumbnail; } /** * Returns an array of dimensional properties (width, height, real_width, real_height) of a resulting clone image if and when generated * * @param string $image_path * @param string $clone_path * @param array $params * @return null|array */ public function calculate_image_clone_dimensions( $image_path, $clone_path, $params ) { $retval = null; $result = $this->calculate_image_clone_result( $image_path, $clone_path, $params ); if ( $result != null ) { $retval = [ 'width' => $result['width'], 'height' => $result['height'], 'real_width' => $result['real_width'], 'real_height' => $result['real_height'], ]; } return $retval; } /** * Returns an array of properties of a resulting clone image if and when generated * * @param string $image_path * @param string $clone_path * @param array $params * @return null|array */ public function calculate_image_clone_result( $image_path, $clone_path, $params ) { $width = isset( $params['width'] ) ? $params['width'] : null; $height = isset( $params['height'] ) ? $params['height'] : null; $quality = isset( $params['quality'] ) ? $params['quality'] : null; $type = isset( $params['type'] ) ? $params['type'] : null; $crop = isset( $params['crop'] ) ? $params['crop'] : null; $watermark = isset( $params['watermark'] ) ? $params['watermark'] : null; $rotation = isset( $params['rotation'] ) ? $params['rotation'] : null; $reflection = isset( $params['reflection'] ) ? $params['reflection'] : null; $crop_frame = isset( $params['crop_frame'] ) ? $params['crop_frame'] : null; $result = null; // Ensure we have a valid image. if ( $image_path && @file_exists( $image_path ) ) { // Ensure target directory exists, but only create 1 subdirectory. $image_dir = dirname( $image_path ); $clone_dir = dirname( $clone_path ); $image_extension = I18N::mb_pathinfo( $image_path, PATHINFO_EXTENSION ); $image_extension_str = null; $clone_extension = I18N::mb_pathinfo( $clone_path, PATHINFO_EXTENSION ); $clone_extension_str = null; if ( $image_extension != null ) { $image_extension_str = '.' . $image_extension; } if ( $clone_extension != null ) { $clone_extension_str = '.' . $clone_extension; } $image_basename = I18N::mb_basename( $image_path ); $clone_basename = I18N::mb_basename( $clone_path ); // We use a default suffix as passing in null as the suffix will make WordPress use a default. $clone_suffix = null; $format_list = $this->get_image_format_list(); $clone_format = null; // format is determined below and based on $type otherwise left to null. // suffix is only used to reconstruct paths for image_resize function. if ( strpos( $clone_basename, $image_basename ) === 0 ) { $clone_suffix = substr( $clone_basename, strlen( $image_basename ) ); } if ( $clone_suffix != null && $clone_suffix[0] == '-' ) { // WordPress adds '-' on its own. $clone_suffix = substr( $clone_suffix, 1 ); } // Get original image dimensions. $dimensions = getimagesize( $image_path ); if ( $width == null && $height == null ) { if ( $dimensions != null ) { if ( $width == null ) { $width = $dimensions[0]; } if ( $height == null ) { $height = $dimensions[1]; } } else { // XXX Don't think there's any other option here but to fail miserably...use some hard-coded defaults maybe? return null; } } if ( $dimensions != null ) { $dimensions_ratio = $dimensions[0] / $dimensions[1]; if ( $width == null ) { $width = (int) round( $height * $dimensions_ratio ); if ( $width == ( $dimensions[0] - 1 ) ) { $width = $dimensions[0]; } } elseif ( $height == null ) { $height = (int) round( $width / $dimensions_ratio ); if ( $height == ( $dimensions[1] - 1 ) ) { $height = $dimensions[1]; } } if ( $width > $dimensions[0] ) { $width = $dimensions[0]; } if ( $height > $dimensions[1] ) { $height = $dimensions[1]; } $image_format = $dimensions[2]; if ( $type != null ) { if ( is_string( $type ) ) { $type = strtolower( $type ); // Indexes in the $format_list array correspond to IMAGETYPE_XXX values appropriately. if ( ( $index = array_search( $type, $format_list ) ) !== false ) { $type = $index; if ( $type != $image_format ) { // Note: this only changes the FORMAT of the image but not the extension. $clone_format = $type; } } } } } if ( $width == null || $height == null ) { // Something went wrong... return null; } // We now need to estimate the 'quality' or level of compression applied to the original JPEG: *IF* the // original image has a quality lower than the $quality parameter we will end up generating a new image // that is MUCH larger than the original. 'Quality' as an EXIF or IPTC property is quite unreliable // and not all software honors or treats it the same way. This calculation is simple: just compare the size // that our image could become to what it currently is. '3' is important here as JPEG uses 3 bytes per pixel. // // First we attempt to use ImageMagick if we can; it has a more robust method of calculation. if ( ! empty( $dimensions['mime'] ) && $dimensions['mime'] == 'image/jpeg' ) { $possible_quality = null; $try_image_magick = true; if ( ( defined( 'NGG_DISABLE_IMAGICK' ) && NGG_DISABLE_IMAGICK ) || ( function_exists( 'is_wpe' ) && ( $dimensions[0] >= 8000 || $dimensions[1] >= 8000 ) ) ) { $try_image_magick = false; } if ( $try_image_magick && extension_loaded( 'imagick' ) && class_exists( 'Imagick' ) ) { $img = new \Imagick( $image_path ); if ( method_exists( $img, 'getImageCompressionQuality' ) ) { $possible_quality = $img->getImageCompressionQuality(); } } // ImageMagick wasn't available or quality is zero so we guess it from the dimensions and filesize. if ( null === $possible_quality || 0 === $possible_quality ) { $filesize = filesize( $image_path ); $possible_quality = ( 101 - ( ( $width * $height ) * 3 ) / $filesize ); } if ( $possible_quality !== null && $possible_quality < $quality ) { $quality = $possible_quality; } } $result['clone_path'] = $clone_path; $result['clone_directory'] = $clone_dir; $result['clone_suffix'] = $clone_suffix; $result['clone_format'] = $clone_format; $result['base_width'] = $dimensions[0]; $result['base_height'] = $dimensions[1]; // image_resize() has limitations: // - no easy crop frame support // - fails if the dimensions are unchanged // - doesn't support filename prefix, only suffix so names like thumbs_original_name.jpg for $clone_path are not supported // also suffix cannot be null as that will make WordPress use a default suffix...we could use an object that returns empty string from __toString() but for now just fallback to ngg generator. if ( false ) { // phpcs:ignore WordPress.WP.CapitalPDangit.MisspelledInText $result['method'] = 'wordpress'; $new_dims = image_resize_dimensions( $dimensions[0], $dimensions[1], $width, $height, $crop ); if ( $new_dims ) { list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $new_dims; $width = $dst_w; $height = $dst_h; } else { $result['error'] = new \WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions', 'nggallery' ) ); } } else { $result['method'] = 'nextgen'; $original_width = $dimensions[0]; $original_height = $dimensions[1]; $aspect_ratio = $width / $height; $orig_ratio_x = $original_width / $width; $orig_ratio_y = $original_height / $height; if ( $crop ) { $algo = 'shrink'; // either 'adapt' or 'shrink'. if ( $crop_frame != null ) { $crop_x = (int) round( $crop_frame['x'] ); $crop_y = (int) round( $crop_frame['y'] ); $crop_width = (int) round( $crop_frame['width'] ); $crop_height = (int) round( $crop_frame['height'] ); $crop_final_width = (int) round( $crop_frame['final_width'] ); $crop_final_height = (int) round( $crop_frame['final_height'] ); $crop_width_orig = $crop_width; $crop_height_orig = $crop_height; $crop_factor_x = $crop_width / $crop_final_width; $crop_factor_y = $crop_height / $crop_final_height; $crop_ratio_x = $crop_width / $width; $crop_ratio_y = $crop_height / $height; if ( $algo == 'adapt' ) { // XXX not sure about this...don't use for now // $crop_width = (int) round($width * $crop_factor_x); // $crop_height = (int) round($height * $crop_factor_y);. } elseif ( $algo == 'shrink' ) { if ( $crop_ratio_x < $crop_ratio_y ) { $crop_width = max( $crop_width, $width ); $crop_height = (int) round( $crop_width / $aspect_ratio ); } else { $crop_height = max( $crop_height, $height ); $crop_width = (int) round( $crop_height * $aspect_ratio ); } if ( $crop_width == ( $crop_width_orig - 1 ) ) { $crop_width = $crop_width_orig; } if ( $crop_height == ( $crop_height_orig - 1 ) ) { $crop_height = $crop_height_orig; } } $crop_diff_x = (int) round( ( $crop_width_orig - $crop_width ) / 2 ); $crop_diff_y = (int) round( ( $crop_height_orig - $crop_height ) / 2 ); $crop_x += $crop_diff_x; $crop_y += $crop_diff_y; $crop_max_x = ( $crop_x + $crop_width ); $crop_max_y = ( $crop_y + $crop_height ); // Check if we're overflowing borders. // if ( $crop_x < 0 ) { $crop_x = 0; } elseif ( $crop_max_x > $original_width ) { $crop_x -= ( $crop_max_x - $original_width ); } if ( $crop_y < 0 ) { $crop_y = 0; } elseif ( $crop_max_y > $original_height ) { $crop_y -= ( $crop_max_y - $original_height ); } } else { if ( $orig_ratio_x < $orig_ratio_y ) { $crop_width = $original_width; $crop_height = (int) round( $height * $orig_ratio_x ); } else { $crop_height = $original_height; $crop_width = (int) round( $width * $orig_ratio_y ); } if ( $crop_width == ( $width - 1 ) ) { $crop_width = $width; } if ( $crop_height == ( $height - 1 ) ) { $crop_height = $height; } $crop_x = (int) round( ( $original_width - $crop_width ) / 2 ); $crop_y = (int) round( ( $original_height - $crop_height ) / 2 ); } $result['crop_area'] = [ 'x' => $crop_x, 'y' => $crop_y, 'width' => $crop_width, 'height' => $crop_height, ]; } else { // Just constraint dimensions to ensure there's no stretching or deformations. list($width, $height) = wp_constrain_dimensions( $original_width, $original_height, $width, $height ); } } $result['width'] = $width; $result['height'] = $height; $result['quality'] = $quality; $real_width = $width; $real_height = $height; if ( $rotation && in_array( abs( $rotation ), [ 90, 270 ], true ) ) { $real_width = $height; $real_height = $width; } if ( $reflection ) { // default for nextgen was 40%, this is used in generate_image_clone as well. $reflection_amount = 40; // Note, round() would probably be best here but using the same code that LegacyThumbnail uses for compatibility. $reflection_height = intval( $real_height * ( $reflection_amount / 100 ) ); $real_height = $real_height + $reflection_height; } $result['real_width'] = $real_width; $result['real_height'] = $real_height; } return $result; } public function generate_resized_image( $image, $save = true ) { $image_abspath = $this->get_image_abspath( $image, 'full' ); $generated = $this->generate_image_clone( $image_abspath, $image_abspath, $this->get_image_size_params( $image, 'full' ) ); if ( $generated && $save ) { $this->update_image_dimension_metadata( $image, $image_abspath ); } if ( $generated ) { $generated->destruct(); } } public function update_image_dimension_metadata( $image, $image_abspath ) { // Ensure that fullsize dimensions are added to metadata array. $dimensions = getimagesize( $image_abspath ); $full_meta = [ 'width' => $dimensions[0], 'height' => $dimensions[1], 'md5' => $this->get_image_checksum( $image, 'full' ), ]; if ( ! isset( $image->meta_data ) or ( is_string( $image->meta_data ) && strlen( $image->meta_data ) == 0 ) or is_bool( $image->meta_data ) ) { $image->meta_data = []; } $image->meta_data = array_merge( $image->meta_data, $full_meta ); $image->meta_data['full'] = $full_meta; // Don't forget to append the 'full' entry in meta_data in the db. $this->image_mapper->save( $image ); } /** * Most major browsers do not honor the Orientation meta found in EXIF. To prevent display issues we inspect * the EXIF data and rotate the image so that the EXIF field is not necessary to display the image correctly. * Note: generate_image_clone() will handle the removal of the Orientation tag inside the image EXIF. * Note: This only handles single-dimension rotation; at the time this method was written there are no known * camera manufacturers that both rotate and flip images. * * @param $image * @param bool $save */ public function correct_exif_rotation( $image, $save = true ) { $image_abspath = $this->get_image_abspath( $image, 'full' ); if ( ! EXIFWriter::is_jpeg_file( $image_abspath ) ) { return; } // This method is necessary. if ( ! function_exists( 'exif_read_data' ) ) { return; } // We only need to continue if the Orientation tag is set. $exif = @exif_read_data( $image_abspath, 'exif' ); if ( empty( $exif['Orientation'] ) || $exif['Orientation'] == 1 ) { return; } $degree = 0; if ( $exif['Orientation'] == 3 ) { $degree = 180; } if ( $exif['Orientation'] == 6 ) { $degree = 90; } if ( $exif['Orientation'] == 8 ) { $degree = 270; } $parameters = [ 'rotation' => $degree ]; $generated = $this->generate_image_clone( $image_abspath, $image_abspath, $this->get_image_size_params( $image, 'full', $parameters ), $parameters ); if ( $generated && $save ) { $this->update_image_dimension_metadata( $image, $image_abspath ); } if ( $generated ) { $generated->destruct(); } } /** * Flushes the cache we use for path/url calculation for galleries */ public function flush_gallery_path_cache( $gallery ) { $gallery = is_numeric( $gallery ) ? $gallery : $gallery->gid; unset( self::$gallery_abspath_cache[ $gallery ] ); } /** * Returns the absolute path to the cache directory of a gallery. * * Without the gallery parameter the legacy (pre 2.0) shared directory is returned. * * @param int|object|false|Gallery $gallery (optional) * @return string Absolute path to cache directory */ public function get_cache_abspath( $gallery = false ) { return path_join( $this->get_gallery_abspath( $gallery ), 'cache' ); } /** * Gets the absolute path where the full-sized image is stored * * @param int|object $image * @return null|string */ public function get_full_abspath( $image ) { return $this->get_image_abspath( $image, 'full' ); } /** * Alias to get_image_dimensions() * * @param int|object $image * @return array */ public function get_full_dimensions( $image ) { return $this->get_image_dimensions( $image, 'full' ); } /** * Alias for get_original_url() * * @param Image $image * @return string */ public function get_full_url( $image ) { return $this->get_image_url( $image, 'full' ); } public function get_gallery_root() { return wp_normalize_path( Filesystem::get_instance()->get_document_root( 'galleries' ) ); } public function get_computed_gallery_abspath( $gallery ) { $retval = null; $gallery_root = $this->get_gallery_root(); // Get the gallery entity from the database. if ( $gallery ) { if ( is_numeric( $gallery ) ) { $gallery = $this->gallery_mapper->find( $gallery ); } } // It just doesn't exist. if ( ! $gallery ) { return $retval; } // We we have a gallery, determine it's path. if ( $gallery ) { if ( isset( $gallery->path ) ) { $retval = $gallery->path; } elseif ( isset( $gallery->slug ) ) { $basepath = wp_normalize_path( Settings::get_instance()->gallerypath ); $retval = path_join( $basepath, $this->sanitize_directory_name( sanitize_title( $gallery->slug ) ) ); } // Normalize the gallery path. If the gallery path starts with /wp-content, and // NGG_GALLERY_ROOT_TYPE is set to 'content', then we need to strip out the /wp-content // from the start of the gallery path. if ( NGG_GALLERY_ROOT_TYPE === 'content' ) { $retval = preg_replace( '#^/?wp-content#', '', $retval ); } // Ensure that the path is absolute. if ( strpos( $retval, $gallery_root ) !== 0 ) { // path_join() behaves funny - if the second argument starts with a slash, // it won't join the two paths together. $retval = preg_replace( '#^/#', '', $retval ); $retval = path_join( $gallery_root, $retval ); } $retval = wp_normalize_path( $retval ); } return $retval; } /** * Get the abspath to the gallery folder for the given gallery * The gallery may or may not already be persisted * * @param int|object|Gallery $gallery * * @return string */ public function get_gallery_abspath( $gallery ) { $gallery_id = is_numeric( $gallery ) ? $gallery : ( is_object( $gallery ) && isset( $gallery->gid ) ? $gallery->gid : null ); if ( ! $gallery_id || ! isset( self::$gallery_abspath_cache[ $gallery_id ] ) ) { self::$gallery_abspath_cache[ $gallery_id ] = $this->get_computed_gallery_abspath( $gallery ); } return self::$gallery_abspath_cache[ $gallery_id ]; } public function get_gallery_relpath( $gallery ) { // Special hack for home.pl: their document root is just '/'. $root = $this->get_gallery_root(); if ( $root === '/' ) { return $this->get_gallery_abspath( $gallery ); } return str_replace( $this->get_gallery_root(), '', $this->get_gallery_abspath( $gallery ) ); } /** * Gets the absolute path where the image is stored. Can optionally return the path for a particular sized image. * * @param int|object $image * @param string $size (optional) Default = full * @return string */ public function get_computed_image_abspath( $image, $size = 'full', $check_existance = false ) { $retval = null; // If we have the id, get the actual image entity. if ( is_numeric( $image ) ) { $image = $this->image_mapper->find( $image ); } // Ensure we have the image entity - user could have passed in an incorrect id. if ( is_object( $image ) ) { if ( ( $gallery_path = $this->get_gallery_abspath( $image->galleryid ) ) ) { $folder = $prefix = $size; switch ( $size ) { // Images are stored in the associated gallery folder. case 'full': $retval = \path_join( $gallery_path, $image->filename ); break; case 'backup': $retval = \path_join( $gallery_path, $image->filename . '_backup' ); if ( ! @file_exists( $retval ) ) { $retval = \path_join( $gallery_path, $image->filename ); } break; case 'thumbnail': $size = 'thumbnail'; $folder = 'thumbs'; $prefix = 'thumbs'; // deliberately no break here. default: // NGG 2.0 stores relative filenames in the meta data of // an image. It does this because it uses filenames // that follow conventional WordPress naming scheme. $image_path = null; $dynthumbs = \Imagely\NGG\DynamicThumbnails\Manager::get_instance(); if ( isset( $image->meta_data ) && isset( $image->meta_data[ $size ] ) && isset( $image->meta_data[ $size ]['filename'] ) ) { if ( $dynthumbs && $dynthumbs->is_size_dynamic( $size ) ) { $image_path = \path_join( $this->get_cache_abspath( $image->galleryid ), $image->meta_data[ $size ]['filename'] ); } else { $image_path = \path_join( $gallery_path, $folder ); $image_path = \path_join( $image_path, $image->meta_data[ $size ]['filename'] ); } } // Filename not found in meta, but is dynamic. elseif ( $dynthumbs && $dynthumbs->is_size_dynamic( $size ) ) { $params = $dynthumbs->get_params_from_name( $size, true ); $image_path = \path_join( $this->get_cache_abspath( $image->galleryid ), $dynthumbs->get_image_name( $image, $params ) ); // Filename is not found in meta, nor dynamic. } else { $settings = Settings::get_instance(); // This next bit is annoying but necessary for legacy reasons. NextGEN until 3.19 stored thumbnails // with a filename of "thumbs_(whatever.jpg)" which Google indexes as "thumbswhatever.jpg" which is // not good for SEO. From 3.19 on the default setting is "thumbs-" but we must account for legacy // sites. $image_path = \path_join( $gallery_path, $folder ); $new_thumb_path = \path_join( $image_path, "{$prefix}-{$image->filename}" ); $old_thumb_path = \path_join( $image_path, "{$prefix}_{$image->filename}" ); if ( $settings->get( 'dynamic_image_filename_separator_use_dash', false ) ) { // Check for thumbs- first. if ( file_exists( $new_thumb_path ) ) { $image_path = $new_thumb_path; } elseif ( file_exists( $old_thumb_path ) ) { // Check for thumbs_ as a fallback. $image_path = $old_thumb_path; } else { // The thumbnail file does not exist, default to thumbs-. $image_path = $new_thumb_path; } } else { // Reversed: the option is disabled so check for thumbs_. if ( file_exists( $old_thumb_path ) ) { $image_path = $old_thumb_path; } elseif ( file_exists( $new_thumb_path ) ) { // In case the user has switched back and forth, check for thumbs-. $image_path = $new_thumb_path; } else { // Default to thumbs_ per the site setting. $image_path = $old_thumb_path; } } } $retval = $image_path; break; } } } if ( $retval && $check_existance && ! @file_exists( $retval ) ) { $retval = null; } return $retval; } public function get_image_checksum( $image, $size = 'full' ) { $retval = null; if ( ( $image_abspath = $this->get_image_abspath( $image, $size, true ) ) ) { $retval = md5_file( $image_abspath ); } return $retval; } /** * Gets the dimensions for a particular-sized image * * @param int|object $image * @param string $size * @return null|array */ public function get_image_dimensions( $image, $size = 'full' ) { $retval = null; // If an image id was provided, get the entity. if ( is_numeric( $image ) ) { $image = $this->image_mapper->find( $image ); } // Ensure we have a valid image. if ( $image ) { $size = $this->normalize_image_size_name( $size ); if ( ! $size ) { $size = 'full'; } // Image dimensions are stored in the $image->meta_data // property for all implementations. if ( isset( $image->meta_data ) && isset( $image->meta_data[ $size ] ) ) { $retval = $image->meta_data[ $size ]; } // Didn't exist for meta data. We'll have to compute // dimensions in the meta_data after computing? This is most likely // due to a dynamic image size being calculated for the first time. else { $dynthumbs = \Imagely\NGG\DynamicThumbnails\Manager::get_instance(); $abspath = $this->get_image_abspath( $image, $size, true ); if ( $abspath ) { $dims = @getimagesize( $abspath ); if ( $dims ) { $retval['width'] = $dims[0]; $retval['height'] = $dims[1]; } } elseif ( $size == 'backup' ) { $retval = $this->get_image_dimensions( $image, 'full' ); } if ( ! $retval && $dynthumbs && $dynthumbs->is_size_dynamic( $size ) ) { $new_dims = $this->calculate_image_size_dimensions( $image, $size ); // Prevent a possible PHP warning if the sizes weren't calculated. if ( isset( $new_dims['real_width'] ) && isset( $new_dims['real_height'] ) ) { $retval = [ 'width' => $new_dims['real_width'], 'height' => $new_dims['real_height'], ]; } } } } return $retval; } public function get_image_format_list() { $format_list = [ IMAGETYPE_GIF => 'gif', IMAGETYPE_JPEG => 'jpg', IMAGETYPE_PNG => 'png', IMAGETYPE_WEBP => 'webp', ]; return $format_list; } /** * Gets the HTML for an image * * @param int|object $image * @param string $size * @param array $attributes (optional) * @return string */ public function get_image_html( $image, $size = 'full', $attributes = [] ) { $retval = ''; if ( is_numeric( $image ) ) { $image = $this->image_mapper->find( $image ); } if ( $image ) { // Set alt text if not already specified. if ( ! isset( $attributes['alttext'] ) ) { $attributes['alt'] = esc_attr( $image->alttext ); } // Set the title if not already set. if ( ! isset( $attributes['title'] ) ) { $attributes['title'] = esc_attr( $image->alttext ); } // Set the dimensions if not set already. if ( ! isset( $attributes['width'] ) or ! isset( $attributes['height'] ) ) { $dimensions = $this->get_image_dimensions( $image, $size ); if ( ! isset( $attributes['width'] ) ) { $attributes['width'] = $dimensions['width']; } if ( ! isset( $attributes['height'] ) ) { $attributes['height'] = $dimensions['height']; } } // Set the url if not already specified. if ( ! isset( $attributes['src'] ) ) { $attributes['src'] = $this->get_image_url( $image, $size ); } // Format attributes. $attribs = []; foreach ( $attributes as $attrib => $value ) { $attribs[] = "{$attrib}=\"{$value}\""; } $attribs = implode( ' ', $attribs ); // Return HTML string. $retval = ""; } return $retval; } public function get_computed_image_url( $image, $size = 'full' ) { $retval = null; $dynthumbs = \Imagely\NGG\DynamicThumbnails\Manager::get_instance(); // Get the image abspath. $image_abspath = $this->get_image_abspath( $image, $size ); if ( $dynthumbs->is_size_dynamic( $size ) && ! file_exists( $image_abspath ) ) { if ( defined( 'NGG_DISABLE_DYNAMIC_IMG_URLS' ) && constant( 'NGG_DISABLE_DYNAMIC_IMG_URLS' ) ) { $params = [ 'watermark' => false, 'reflection' => false, 'crop' => true, ]; $result = $this->generate_image_size( $image, $size, $params ); if ( $result ) { $image_abspath = $this->get_image_abspath( $image, $size ); } } else { return null; } } // Assuming we have an abspath, we can translate that to a url. if ( $image_abspath ) { // Replace the gallery root with the proper url segment. $gallery_root = preg_quote( $this->get_gallery_root(), '#' ); $image_uri = preg_replace( "#^{$gallery_root}#", '', $image_abspath ); // Url encode each uri segment. $segments = explode( '/', $image_uri ); $segments = array_map( 'rawurlencode', $segments ); $image_uri = preg_replace( '#^/#', '', implode( '/', $segments ) ); // Join gallery root and image uri. $gallery_root = trailingslashit( NGG_GALLERY_ROOT_TYPE == 'site' ? site_url() : WP_CONTENT_URL ); $gallery_root = is_ssl() ? str_replace( 'http:', 'https:', $gallery_root ) : $gallery_root; $retval = $gallery_root . $image_uri; } return $retval; } public function normalize_image_size_name( $size = 'full' ) { switch ( $size ) { case 'full': case 'image': case 'orig': case 'original': case 'resized': $size = 'full'; break; case 'thumb': case 'thumbnail': case 'thumbnails': case 'thumbs': $size = 'thumbnail'; break; } return $size; } /** * Returns the named sizes available for images * * @return array */ public function get_image_sizes( $image = false ) { $retval = [ 'full', 'thumbnail' ]; if ( is_numeric( $image ) ) { $image = ImageMapper::get_instance()->find( $image ); } if ( $image ) { if ( $image->meta_data ) { $meta_data = is_object( $image->meta_data ) ? get_object_vars( $image->meta_data ) : $image->meta_data; foreach ( $meta_data as $key => $value ) { if ( is_array( $value ) && isset( $value['width'] ) && ! in_array( $key, $retval ) ) { $retval[] = $key; } } } } return $retval; } public function get_image_size_params( $image, $size, $params = [], $skip_defaults = false ) { // Get the image entity. if ( is_numeric( $image ) ) { $image = $this->image_mapper->find( $image ); } $dynthumbs = \Imagely\NGG\DynamicThumbnails\Manager::get_instance(); if ( $dynthumbs && $dynthumbs->is_size_dynamic( $size ) ) { $named_params = $dynthumbs->get_params_from_name( $size, true ); if ( ! $params ) { $params = []; } $params = array_merge( $params, $named_params ); } $params = apply_filters( 'ngg_get_image_size_params', $params, $size, $image ); // Ensure we have a valid image. if ( $image ) { $settings = Settings::get_instance(); if ( ! $skip_defaults ) { // Get default settings. if ( $size == 'full' ) { if ( ! isset( $params['quality'] ) ) { $params['quality'] = $settings->get( 'imgQuality' ); } } else { if ( ! isset( $params['crop'] ) ) { $params['crop'] = $settings->get( 'thumbfix' ); } if ( ! isset( $params['quality'] ) ) { $params['quality'] = $settings->get( 'thumbquality' ); } } } // width and height when omitted make generate_image_clone create a clone with original size, so try find defaults regardless of $skip_defaults. if ( ! isset( $params['width'] ) || ! isset( $params['height'] ) ) { // First test if this is a "known" image size, i.e. if we store these sizes somewhere when users re-generate these sizes from the UI...this is required to be compatible with legacy. // try the 2 default built-in sizes, first thumbnail... if ( $size == 'thumbnail' ) { if ( ! isset( $params['width'] ) ) { $params['width'] = $settings->thumbwidth; } if ( ! isset( $params['height'] ) ) { $params['height'] = $settings->thumbheight; } } // ...and then full, which is the size specified in the global resize options. elseif ( $size == 'full' ) { if ( ! isset( $params['width'] ) ) { if ( $settings->imgAutoResize ) { $params['width'] = $settings->imgWidth; } } if ( ! isset( $params['height'] ) ) { if ( $settings->imgAutoResize ) { $params['height'] = $settings->imgHeight; } } } // Only re-use old sizes as last resort. elseif ( isset( $image->meta_data ) && isset( $image->meta_data[ $size ] ) ) { $dimensions = $image->meta_data[ $size ]; if ( ! isset( $params['width'] ) ) { $params['width'] = $dimensions['width']; } if ( ! isset( $params['height'] ) ) { $params['height'] = $dimensions['height']; } } } if ( ! isset( $params['crop_frame'] ) ) { $crop_frame_size_name = 'thumbnail'; if ( isset( $image->meta_data[ $size ]['crop_frame'] ) ) { $crop_frame_size_name = $size; } if ( isset( $image->meta_data[ $crop_frame_size_name ]['crop_frame'] ) ) { $params['crop_frame'] = $image->meta_data[ $crop_frame_size_name ]['crop_frame']; if ( ! isset( $params['crop_frame']['final_width'] ) ) { $params['crop_frame']['final_width'] = $image->meta_data[ $crop_frame_size_name ]['width']; } if ( ! isset( $params['crop_frame']['final_height'] ) ) { $params['crop_frame']['final_height'] = $image->meta_data[ $crop_frame_size_name ]['height']; } } } else { if ( ! isset( $params['crop_frame']['final_width'] ) ) { $params['crop_frame']['final_width'] = $params['width']; } if ( ! isset( $params['crop_frame']['final_height'] ) ) { $params['crop_frame']['final_height'] = $params['height']; } } } return $params; } /** * Alias to get_image_dimensions() * * @param int|object $image * @return array */ public function get_original_dimensions( $image ) { return $this->get_image_dimensions( $image, 'full' ); } /** * @param object|bool $gallery (optional) * @return string */ public function get_upload_abspath( $gallery = false ) { // Base upload path. $retval = Settings::get_instance()->get( 'gallerypath' ); $fs = Filesystem::get_instance(); // Append the slug if a gallery has been specified. if ( $gallery ) { $retval = $this->get_gallery_abspath( $gallery ); } // We need to make this an absolute path. if ( ! empty( $retval ) && strpos( $retval, $fs->get_document_root( 'gallery' ) ) !== 0 ) { $retval = rtrim( $fs->join_paths( $fs->get_document_root( 'gallery' ), $retval ), '/\\' ); } // Convert slashes. return wp_normalize_path( $retval ); } /** * Gets the upload path, optionally for a particular gallery * * @param int|Gallery|object|false $gallery (optional) * * @return string */ public function get_upload_relpath( $gallery = false ) { $fs = Filesystem::get_instance(); $retval = str_replace( $fs->get_document_root( 'gallery' ), '', $this->get_upload_abspath( $gallery ) ); return '/' . wp_normalize_path( ltrim( $retval, '/' ) ); } public function delete_gallery_directory( $abspath ) { // Remove all image files and purge all empty directories left over. $iterator = new \DirectoryIterator( $abspath ); // Only delete image files! Other files may be stored incorrectly but it's not our place to delete them. $removable_extensions = apply_filters( 'ngg_allowed_file_types', NGG_DEFAULT_ALLOWED_FILE_TYPES ); foreach ( $removable_extensions as $extension ) { $removable_extensions[] = $extension . '_backup'; } foreach ( $iterator as $file ) { if ( in_array( $file->getBasename(), [ '.', '..' ] ) ) { continue; } elseif ( $file->isFile() || $file->isLink() ) { $extension = strtolower( pathinfo( $file->getPathname(), PATHINFO_EXTENSION ) ); if ( in_array( $extension, $removable_extensions, true ) ) { @unlink( $file->getPathname() ); } } elseif ( $file->isDir() ) { $this->delete_gallery_directory( $file->getPathname() ); } } // DO NOT remove directories that still have files in them. Note: '.' and '..' are included with getSize(). $empty = true; foreach ( $iterator as $file ) { if ( in_array( $file->getBasename(), [ '.', '..' ] ) ) { continue; } $empty = false; } if ( $empty ) { @rmdir( $iterator->getPath() ); } } /** * @param Image[] $images * @param Gallery|int $dst_gallery * * @return int[] */ public function copy_images( $images, $dst_gallery ) { $retval = []; // Ensure that the image ids we have are valid. $image_mapper = ImageMapper::get_instance(); foreach ( $images as $image ) { if ( is_numeric( $image ) ) { $image = $image_mapper->find( $image ); } $image_abspath = $this->get_image_abspath( $image, 'backup' ) ?: $this->get_image_abspath( $image ); if ( $image_abspath ) { // Import the image; this will copy the main file. $new_image_id = $this->import_image_file( $dst_gallery, $image_abspath, $image->filename ); if ( $new_image_id ) { // Copy the properties of the old image. $new_image = $image_mapper->find( $new_image_id ); foreach ( get_object_vars( $image ) as $key => $value ) { if ( in_array( $key, [ 'pid', 'galleryid', 'meta_data', 'filename', 'sortorder', 'extras_post_id' ] ) ) { continue; } $new_image->$key = $value; } $image_mapper->save( $new_image ); // Copy tags. $tags = wp_get_object_terms( $image->pid, 'ngg_tag', 'fields=ids' ); $tags = array_map( 'intval', $tags ); wp_set_object_terms( $new_image_id, $tags, 'ngg_tag', true ); // Copy all of the generated versions (resized versions, watermarks, etc). foreach ( $this->get_image_sizes( $image ) as $named_size ) { if ( in_array( $named_size, [ 'full', 'thumbnail' ] ) ) { continue; } $old_abspath = $this->get_image_abspath( $image, $named_size ); $new_abspath = $this->get_image_abspath( $new_image, $named_size ); if ( is_array( @stat( $old_abspath ) ) ) { $new_dir = dirname( $new_abspath ); // Ensure the target directory exists. if ( @stat( $new_dir ) === false ) { wp_mkdir_p( $new_dir ); } @copy( $old_abspath, $new_abspath ); } } // Mark as done. $retval[] = $new_image_id; } } } return $retval; } /** * Moves images from to another gallery * * @param array $images * @param int|object $gallery * @return int[] */ public function move_images( $images, $gallery ) { $retval = $this->copy_images( $images, $gallery ); if ( $images ) { foreach ( $images as $image_id ) { $this->delete_image( $image_id ); } } return $retval; } /** * @param string $abspath * @return bool */ public function delete_directory( $abspath ) { $retval = false; if ( @file_exists( $abspath ) ) { $files = scandir( $abspath ); array_shift( $files ); array_shift( $files ); foreach ( $files as $file ) { $file_abspath = implode( DIRECTORY_SEPARATOR, [ rtrim( $abspath, '/\\' ), $file ] ); if ( is_dir( $file_abspath ) ) { $this->delete_directory( $file_abspath ); } else { unlink( $file_abspath ); } } rmdir( $abspath ); $retval = @file_exists( $abspath ); } return $retval; } public function delete_gallery( $gallery ) { $fs = Filesystem::get_instance(); $safe_dirs = [ DIRECTORY_SEPARATOR, $fs->get_document_root( 'plugins' ), $fs->get_document_root( 'plugins_mu' ), $fs->get_document_root( 'templates' ), $fs->get_document_root( 'stylesheets' ), $fs->get_document_root( 'content' ), $fs->get_document_root( 'galleries' ), $fs->get_document_root(), ]; $abspath = $this->get_gallery_abspath( $gallery ); if ( $abspath && file_exists( $abspath ) && ! in_array( stripslashes( $abspath ), $safe_dirs ) ) { $this->delete_gallery_directory( $abspath ); } } /** * @param Image $image * @param string|false $size * @return bool */ public function delete_image( $image, $size = false ) { $retval = false; // Ensure that we have the image entity. if ( is_numeric( $image ) ) { $image = $this->image_mapper->find( $image ); } if ( $image ) { $image_id = $image->{$image->id_field}; do_action( 'ngg_delete_image', $image_id, $size ); // Delete only a particular image size. if ( $size ) { $abspath = $this->get_image_abspath( $image, $size ); if ( $abspath && @file_exists( $abspath ) ) { @unlink( $abspath ); } if ( isset( $image->meta_data ) && isset( $image->meta_data[ $size ] ) ) { unset( $image->meta_data[ $size ] ); $this->image_mapper->save( $image ); } } // Delete all sizes of the image. else { foreach ( $this->get_image_sizes( $image ) as $named_size ) { $image_abspath = $this->get_image_abspath( $image, $named_size ); @unlink( $image_abspath ); } // Delete the entity. $this->image_mapper->destroy( $image ); } $retval = true; } return $retval; } /** * Outputs/renders an image * * @param Image $image * @return bool */ public function render_image( $image, $size = false ) { $format_list = $this->get_image_format_list(); $abspath = $this->get_image_abspath( $image, $size, true ); if ( $abspath == null ) { $thumbnail = $this->generate_image_size( $image, $size ); if ( $thumbnail != null ) { $abspath = $thumbnail->fileName; $thumbnail->destruct(); } } if ( $abspath != null ) { $data = @getimagesize( $abspath ); $format = 'jpg'; if ( $data != null && is_array( $data ) && isset( $format_list[ $data[2] ] ) ) { $format = $format_list[ $data[2] ]; } // Clear output. while ( ob_get_level() > 0 ) { ob_end_clean(); } $format = strtolower( $format ); // output image and headers. header( 'Content-type: image/' . $format ); readfile( $abspath ); return true; } return false; } /** * Recover image from backup copy and reprocess it * * @param Image $image * @return bool|string result code */ public function recover_image( $image ) { $retval = false; if ( is_numeric( $image ) ) { $image = $this->image_mapper->find( $image ); } if ( $image ) { $full_abspath = $this->get_image_abspath( $image ); $backup_abspath = $this->get_image_abspath( $image, 'backup' ); if ( $backup_abspath != $full_abspath && @file_exists( $backup_abspath ) ) { if ( is_writable( $full_abspath ) && is_writable( dirname( $full_abspath ) ) ) { // Copy the backup. if ( @copy( $backup_abspath, $full_abspath ) ) { // Backup images are not altered at all; we must re-correct the EXIF/Orientation tag. $this->correct_exif_rotation( $image, true ); // Re-create non-fullsize image sizes. foreach ( $this->get_image_sizes( $image ) as $named_size ) { if ( in_array( $named_size, [ 'full', 'backup' ] ) ) { continue; } // Reset thumbnail cropping set by 'Edit thumb' dialog. if ( $named_size === 'thumbnail' ) { unset( $image->meta_data[ $named_size ]['crop_frame'] ); } $thumbnail = $this->generate_image_clone( $full_abspath, $this->get_image_abspath( $image, $named_size ), $this->get_image_size_params( $image, $named_size ) ); if ( $thumbnail ) { $thumbnail->destruct(); } } do_action( 'ngg_recovered_image', $image ); // Reimport all metadata. $retval = $this->image_mapper->reimport_metadata( $image ); } } } } return $retval; } /** * Copies a NGG image to the media library and returns the attachment_id * * @param Image $image * @return false|int attachment_id */ public function copy_to_media_library( $image ) { $retval = false; // Get the image. if ( is_int( $image ) ) { $imageId = $image; $mapper = ImageMapper::get_instance(); $image = $mapper->find( $imageId ); } if ( $image ) { $subdir = apply_filters( 'ngg_import_to_media_library_subdir', 'nggallery_import' ); $wordpress_upload_dir = wp_upload_dir(); $path = $wordpress_upload_dir['path'] . DIRECTORY_SEPARATOR . $subdir; if ( ! file_exists( $path ) ) { wp_mkdir_p( $path ); } $image_abspath = $this->get_image_abspath( $image, 'full' ); $new_file_path = $path . DIRECTORY_SEPARATOR . $image->filename; $image_data = getimagesize( $image_abspath ); $new_file_mime = $image_data['mime']; $i = 1; while ( file_exists( $new_file_path ) ) { ++$i; $new_file_path = $path . DIRECTORY_SEPARATOR . $i . '-' . $image->filename; } if ( @copy( $image_abspath, $new_file_path ) ) { $upload_id = wp_insert_attachment( [ 'guid' => $new_file_path, 'post_mime_type' => $new_file_mime, 'post_title' => preg_replace( '/\.[^.]+$/', '', $image->alttext ), 'post_content' => '', 'post_status' => 'inherit', ], $new_file_path ); update_post_meta( $upload_id, '_ngg_image_id', intval( $image->pid ) ); // wp_generate_attachment_metadata() comes from this file. require_once ABSPATH . 'wp-admin/includes/image.php'; $image_meta = wp_generate_attachment_metadata( $upload_id, $new_file_path ); // Generate and save the attachment metas into the database. wp_update_attachment_metadata( $upload_id, $image_meta ); $retval = $upload_id; } } return $retval; } /** * Delete the given NGG image from the media library * * @var int|stdClass $imageId */ public function delete_from_media_library( $imageId ) { // Get the image. if ( ! is_int( $imageId ) ) { $image = $imageId; $imageId = $image->pid; } if ( ( $postId = $this->is_in_media_library( $imageId ) ) ) { wp_delete_post( $postId ); } } /** * Determines if the given NGG image id has been uploaded to the media library * * @param integer $imageId * @return false|int attachment_id */ public function is_in_media_library( $imageId ) { $retval = false; // Get the image. if ( is_object( $imageId ) ) { $image = $imageId; $imageId = $image->pid; } // Try to find an attachment for the given image_id. if ( $imageId ) { $query = new \WP_Query( [ 'post_type' => 'attachment', 'meta_key' => '_ngg_image_id', 'meta_value_num' => $imageId, ] ); foreach ( $query->get_posts() as $post ) { $retval = $post->ID; } } return $retval; } /** * @param string $filename * @return bool */ public function is_allowed_image_extension( $filename ) { $extension = pathinfo( $filename, PATHINFO_EXTENSION ); $extension = strtolower( $extension ); $allowed_extensions = apply_filters( 'ngg_allowed_file_types', NGG_DEFAULT_ALLOWED_FILE_TYPES ); foreach ( $allowed_extensions as $extension ) { $allowed_extensions[] = $extension . '_backup'; } return in_array( $extension, $allowed_extensions ); } public function is_current_user_over_quota() { $retval = false; $settings = Settings::get_instance(); if ( ( is_multisite() ) && $settings->get( 'wpmuQuotaCheck' ) ) { require_once ABSPATH . 'wp-admin/includes/ms.php'; $retval = upload_is_user_over_quota( false ); } return $retval; } /** * @param string? $filename * @return bool */ public function is_image_file( $filename = null ): bool { $retval = false; // Security::verify_nonce() is a wrapper to wp_verify_nonce(). // // phpcs:disable WordPress.Security.NonceVerification.Missing // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( ! $filename && isset( $_FILES['file']['error'] ) && isset( $_FILES['file']['tmp_name'] ) && 0 === $_FILES['file']['error'] && isset( $_REQUEST['nonce'] ) && Security::verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ), 'nextgen_upload_image' ) ) { // Windows' use of backslash characters for file paths means wp_unslash() here is destructive. if ( 0 === strncasecmp( PHP_OS, 'WIN', 3 ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash $filename = sanitize_text_field( $_FILES['file']['tmp_name'] ); } else { $filename = sanitize_text_field( wp_unslash( $_FILES['file']['tmp_name'] ) ); } } // phpcs:enable WordPress.Security.NonceVerification.Missing // phpcs:enable WordPress.Security.NonceVerification.Recommended $allowed_mime = apply_filters( 'ngg_allowed_mime_types', NGG_DEFAULT_ALLOWED_MIME_TYPES ); // If we can, we'll verify the mime type. if ( function_exists( 'exif_imagetype' ) ) { if ( ( $image_type = @exif_imagetype( $filename ) ) !== false ) { $retval = in_array( image_type_to_mime_type( $image_type ), $allowed_mime ); } } else { $file_info = @getimagesize( $filename ); if ( isset( $file_info[2] ) ) { $retval = in_array( image_type_to_mime_type( $file_info[2] ), $allowed_mime ); } } return $retval; } public function is_zip(): bool { $retval = false; // Security::verify_nonce() is a wrapper to wp_verify_nonce(). // // phpcs:disable WordPress.Security.NonceVerification.Missing // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( isset( $_FILES['file']['error'] ) && 0 === $_FILES['file']['error'] && isset( $_REQUEST['nonce'] ) && Security::verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ), 'nextgen_upload_image' ) ) { $file_info = $_FILES['file']; if ( isset( $file_info['type'] ) ) { $type = $file_info['type']; $type_parts = explode( '/', $type ); if ( strtolower( $type_parts[0] ) == 'application' ) { $spec = $type_parts[1]; $spec_parts = explode( '-', $spec ); $spec_parts = array_map( 'strtolower', $spec_parts ); if ( in_array( $spec, [ 'zip', 'octet-stream' ] ) || in_array( 'zip', $spec_parts ) ) { $retval = true; } } } } // phpcs:enable WordPress.Security.NonceVerification.Missing // phpcs:enable WordPress.Security.NonceVerification.Recommended return $retval; } public function get_unique_abspath( $file_abspath ) { $filename = basename( $file_abspath ); $dir_abspath = dirname( $file_abspath ); $num = 1; $pattern = path_join( $dir_abspath, "*_{$filename}" ); if ( ( $found = glob( $pattern ) ) ) { natsort( $found ); $last = array_pop( $found ); $last = basename( $last ); if ( preg_match( '/^(\d+)_/', $last, $match ) ) { $num = intval( $match[1] ) + 1; } } return path_join( $dir_abspath, "{$num}_{$filename}" ); } /** * Determines whether a WebP image is animated which GD does not support. * * @see https://developers.google.com/speed/webp/docs/riff_container * @param string $filename * @return bool */ public function is_animated_webp( $filename ) { $retval = false; $handle = fopen( $filename, 'rb' ); fseek( $handle, 12 ); if ( fread( $handle, 4 ) === 'VP8X' ) { fseek( $handle, 20 ); $flag = fread( $handle, 1 ); $retval = (bool) ( ( ( ord( $flag ) >> 1 ) & 1 ) ); } fclose( $handle ); return $retval; } public function import_image_file( $dst_gallery, $image_abspath, $filename = null, $image = false, $override = false, $move = false ) { $image_abspath = wp_normalize_path( $image_abspath ); if ( $this->is_current_user_over_quota() ) { $message = sprintf( __( 'Sorry, you have used your space allocation. Please delete some files to upload more files.', 'nggallery' ) ); throw new \E_NoSpaceAvailableException( esc_html( $message ) ); } // Do we have a gallery to import to? if ( $dst_gallery ) { // Get the gallery abspath. This is where we will put the image files. $gallery_abspath = $this->get_gallery_abspath( $dst_gallery ); // If we can't write to the directory, then there's no point in continuing. if ( ! @file_exists( $gallery_abspath ) ) { @wp_mkdir_p( $gallery_abspath ); } if ( ! is_writable( $gallery_abspath ) ) { throw new \E_InsufficientWriteAccessException( false, $gallery_abspath, false ); } // Sanitize the filename for storing in the DB. $filename = $this->sanitize_filename_for_db( $filename ); // Ensure that the filename is valid. $extensions = apply_filters( 'ngg_allowed_file_types', NGG_DEFAULT_ALLOWED_FILE_TYPES ); $extensions[] = '_backup'; $ext_list = implode( '|', $extensions ); if ( ! preg_match( "/({$ext_list})\$/i", $filename ) ) { throw new \E_UploadException( __( 'Invalid image file. Acceptable formats: JPG, GIF, and PNG.', 'nggallery' ) ); } // GD does not support animated WebP and will generate a fatal error when we try to create thumbnails or resize. if ( $this->is_animated_webp( $image_abspath ) ) { throw new \E_UploadException( __( 'Animated WebP images are not supported.', 'nggallery' ) ); } // Compute the destination folder. $new_image_abspath = path_join( $gallery_abspath, $filename ); // Are the src and dst the same? If so, we don't have to copy or move files. if ( $image_abspath != $new_image_abspath ) { // If we're not to override, ensure that the filename is unique. if ( ! $override && @file_exists( $new_image_abspath ) ) { $new_image_abspath = $this->get_unique_abspath( $new_image_abspath ); $filename = $this->sanitize_filename_for_db( basename( $new_image_abspath ) ); } // Try storing the file. $copied = copy( $image_abspath, $new_image_abspath ); if ( $copied && $move ) { unlink( $image_abspath ); } // Ensure that we're not vulerable to CVE-2017-2416 exploit. if ( ( $dimensions = getimagesize( $new_image_abspath ) ) !== false ) { if ( ( isset( $dimensions[0] ) && intval( $dimensions[0] ) > 30000 ) || ( isset( $dimensions[1] ) && intval( $dimensions[1] ) > 30000 ) ) { unlink( $new_image_abspath ); throw new \E_UploadException( esc_html( __( 'Image file too large. Maximum image dimensions supported are 30k x 30k.' ) ) ); } } } // Save the image in the DB. $image_mapper = ImageMapper::get_instance(); $image_mapper->use_cache = false; if ( $image ) { if ( is_numeric( $image ) ) { $image = $image_mapper->find( $image ); } } if ( ! $image ) { $image = $image_mapper->create(); } $image->alttext = preg_replace( '#\.\w{2,4}$#', '', $filename ); $image->galleryid = is_numeric( $dst_gallery ) ? $dst_gallery : $dst_gallery->gid; $image->filename = $filename; $image->image_slug = \nggdb::get_unique_slug( sanitize_title_with_dashes( $image->alttext ), 'image' ); $image_id = $image_mapper->save( $image ); if ( ! $image_id ) { $exception = ''; $validation = $image->validation(); if ( is_array( $validation ) ) { foreach ( $validation as $field => $errors ) { foreach ( $errors as $error ) { if ( ! empty( $exception ) ) { $exception .= '
'; } $exception .= __( sprintf( 'Error while uploading %s: %s', $filename, $error ), 'nextgen-gallery' ); } } throw new \E_UploadException( $exception ); } } // Important: do not remove this line. The image mapper's save() routine imports metadata // meaning we must re-acquire a new $image object after saving it above; if we do not our // existing $image object will lose any metadata retrieved during said save() method. $image = $image_mapper->find( $image_id ); $image_mapper->use_cache = true; $settings = Settings::get_instance(); // Backup the image. if ( $settings->get( 'imgBackup', false ) ) { $this->backup_image( $image, true ); } // Most browsers do not honor EXIF's Orientation header: rotate the image to prevent display issues. $this->correct_exif_rotation( $image, true ); // Create resized version of image. if ( $settings->get( 'imgAutoResize', false ) ) { $this->generate_resized_image( $image, true ); } // Generate a thumbnail for the image. $this->generate_thumbnail( $image ); // Set gallery preview image if missing. GalleryMapper::get_instance()->set_preview_image( $dst_gallery, $image_id, true ); // Automatically watermark the main image if requested. if ( $settings->get( 'watermark_automatically_at_upload', 0 ) ) { $image_abspath = $this->get_image_abspath( $image, 'full' ); $this->generate_image_clone( $image_abspath, $image_abspath, [ 'watermark' => true ] ); } // Notify other plugins that an image has been added. do_action( 'ngg_added_new_image', $image ); // delete dirsize after adding new images. delete_transient( 'dirsize_cache' ); // Seems redundant to above hook. Maintaining for legacy purposes. do_action( 'ngg_after_new_images_added', is_numeric( $dst_gallery ) ? $dst_gallery : $dst_gallery->gid, [ $image_id ] ); return $image_id; } else { throw new \E_EntityNotFoundException(); } return null; } /** * Generates a specific size for an image * * @param Image $image * @param string $size * @param array|null $params (optional) * @param bool $skip_defaults (optional) * @return bool|object */ public function generate_image_size( $image, $size, $params = null, $skip_defaults = false ) { $retval = false; // Get the image entity. if ( is_numeric( $image ) ) { $image = $this->image_mapper->find( $image ); } // Ensure we have a valid image. if ( $image ) { $params = $this->get_image_size_params( $image, $size, $params, $skip_defaults ); $settings = Settings::get_instance(); // Get the image filename. $filename = $this->get_image_abspath( $image, 'full' ); if ( ! @file_exists( $filename ) ) { return false; // bail out if the file doesn't exist. } $thumbnail = null; if ( $size == 'full' && $settings->get( 'imgBackup' ) == 1 ) { $backup_path = $this->get_backup_abspath( $image ); if ( ! @file_exists( $backup_path ) ) { @copy( $filename, $backup_path ); } } // Generate the thumbnail using WordPress. $existing_image_abpath = $this->get_image_abspath( $image, $size ); $existing_image_dir = dirname( $existing_image_abpath ); \wp_mkdir_p( $existing_image_dir ); $clone_path = $existing_image_abpath; $thumbnail = $this->generate_image_clone( $filename, $clone_path, $params ); // We successfully generated the thumbnail. if ( $thumbnail != null ) { $clone_path = $thumbnail->fileName; if ( function_exists( 'getimagesize' ) ) { $dimensions = getimagesize( $clone_path ); } else { $dimensions = [ $params['width'], $params['height'] ]; } if ( ! isset( $image->meta_data ) ) { $image->meta_data = []; } $size_meta = [ 'width' => $dimensions[0], 'height' => $dimensions[1], 'filename' => I18N::mb_basename( $clone_path ), 'generated' => microtime(), ]; if ( isset( $params['crop_frame'] ) ) { $size_meta['crop_frame'] = $params['crop_frame']; } $image->meta_data[ $size ] = $size_meta; if ( $size == 'full' ) { $image->meta_data['width'] = $size_meta['width']; $image->meta_data['height'] = $size_meta['height']; } $retval = $this->image_mapper->save( $image ); \do_action( 'ngg_generated_image', $image, $size, $params ); if ( $retval == 0 ) { $retval = false; } if ( $retval ) { $retval = $thumbnail; } } } return $retval; } /** * Generates a thumbnail for an image * * @param Image $image * @return bool */ public function generate_thumbnail( $image, $params = null, $skip_defaults = false ) { $sized_image = $this->generate_image_size( $image, 'thumbnail', $params, $skip_defaults ); $retval = false; if ( $sized_image != null ) { $retval = true; $sized_image->destruct(); } if ( is_admin() && ( $image = ImageMapper::get_instance()->find( $image ) ) ) { $app = Router::get_instance()->get_routed_app(); $image->thumb_url = $app->set_parameter_value( 'timestamp', time(), null, $this->get_image_url( $image, 'thumb' ), $app->get_routed_url( true ) ); $event = new \stdClass(); $event->pid = $image->{$image->id_field}; $event->id_field = $image->id_field; $event->thumb_url = $image->thumb_url; EventPublisher::get_instance()->add_event( [ 'event' => 'thumbnail_modified', 'image' => $event, ] ); } return $retval; } /** * Gets the absolute path of the backup of an original image * * @param object|string $image * @return null|string */ public function get_backup_abspath( $image ) { $retval = null; if ( ( $image_path = $this->get_image_abspath( $image ) ) ) { $retval = $image_path . '_backup'; } return $retval; } public function get_backup_dimensions( $image ) { return $this->get_image_dimensions( $image, 'backup' ); } /** * Gets the absolute path where the image is stored. Can optionally return the path for a particular sized image * * @param int|object $image * @param string $size (optional) Default = full * @param bool $check_existence (optional) Default = false * @return string */ public function get_image_abspath( $image, $size = 'full', $check_existence = false ) { $image_id = is_numeric( $image ) ? $image : $image->pid; $size = $this->normalize_image_size_name( $size ); $key = strval( $image_id ) . $size; if ( $check_existence || ! isset( self::$image_abspath_cache[ $key ] ) ) { self::$image_abspath_cache[ $key ] = $this->get_computed_image_abspath( $image, $size, $check_existence ); } return self::$image_abspath_cache[ $key ]; } /** * Gets the url of a particular-sized image * * @param int|object $image * @param string $size * @return string */ public function get_image_url( $image, $size = 'full' ) { $retval = null; $image_id = is_numeric( $image ) ? $image : $image->pid; $key = strval( $image_id ) . $size; $success = true; if ( ! isset( self::$image_url_cache[ $key ] ) ) { $url = $this->get_computed_image_url( $image, $size ); if ( $url ) { self::$image_url_cache[ $key ] = $url; $success = true; } else { $success = false; } } if ( $success ) { $retval = self::$image_url_cache[ $key ]; } else { $dynthumbs = \Imagely\NGG\DynamicThumbnails\Manager::get_instance(); if ( $dynthumbs->is_size_dynamic( $size ) ) { $params = $dynthumbs->get_params_from_name( $size ); $retval = Router::get_instance()->get_url( $dynthumbs->get_image_uri( $image, $params ), false, 'root' ); } } return apply_filters( 'ngg_get_image_url', $retval, $image, $size ); } /** * Flushes the cache we use for path/url calculation for images */ public function flush_image_path_cache( $image, $size ) { $image = is_numeric( $image ) ? $image : $image->pid; $key = strval( $image ) . $size; unset( self::$image_abspath_cache[ $key ] ); unset( self::$image_url_cache[ $key ] ); } /** * @param string $abspath * @param int $gallery_id * @param bool $create_new_gallerypath * @param null|string $gallery_title * @param array[string] $filenames * @return array|bool false on failure */ public function import_gallery_from_fs( $abspath, $gallery_id = null, $create_new_gallerypath = true, $gallery_title = null, $filenames = [] ) { if ( @ ! file_exists( $abspath ) ) { return false; } $fs = Filesystem::get_instance(); $retval = [ 'image_ids' => [] ]; // Ensure that this folder has images. $files = []; $directories = []; foreach ( scandir( $abspath ) as $file ) { if ( $file == '.' || $file == '..' || strtoupper( $file ) == '__MACOSX' ) { continue; } $file_abspath = $fs->join_paths( $abspath, $file ); // Omit 'hidden' directories prefixed with a period. if ( is_dir( $file_abspath ) && strpos( $file, '.' ) !== 0 ) { $directories[] = $file_abspath; } elseif ( $this->is_image_file( $file_abspath ) ) { if ( $filenames && array_search( $file_abspath, $filenames ) !== false ) { $files[] = $file_abspath; } elseif ( ! $filenames ) { $files[] = $file_abspath; } } } if ( empty( $files ) && empty( $directories ) ) { return false; } // Get needed utilities. $gallery_mapper = GalleryMapper::get_instance(); // Recurse through the directory and pull in all of the valid images we find. if ( ! empty( $directories ) ) { foreach ( $directories as $dir ) { $subImport = $this->import_gallery_from_fs( $dir, $gallery_id, $create_new_gallerypath, $gallery_title, $filenames ); if ( $subImport ) { $retval['image_ids'] = array_merge( $retval['image_ids'], $subImport['image_ids'] ); } } } // If no gallery has been specified, then use the directory name as the gallery name. if ( ! $gallery_id ) { // Create the gallery. $gallery = $gallery_mapper->create( [ 'title' => $gallery_title ? $gallery_title : I18N::mb_basename( $abspath ), ] ); if ( ! $create_new_gallerypath ) { $gallery_root = $fs->get_document_root( 'gallery' ); $gallery->path = str_ireplace( $gallery_root, '', $abspath ); } // Save the gallery. if ( $gallery->save() ) { $gallery_id = $gallery->id(); } } // Ensure that we have a gallery id. if ( ! $gallery_id ) { return false; } else { $retval['gallery_id'] = $gallery_id; } // Remove full sized image if backup is included. $files_to_import = []; foreach ( $files as $file_abspath ) { if ( preg_match( '#_backup$#', $file_abspath ) ) { $files_to_import[] = $file_abspath; continue; } elseif ( in_array( [ $file_abspath . '_backup', 'thumbs_' . $file_abspath, 'thumbs-' . $file_abspath ], $files ) ) { continue; } $files_to_import[] = $file_abspath; } foreach ( $files_to_import as $file_abspath ) { $basename = preg_replace( '#_backup$#', '', pathinfo( $file_abspath, PATHINFO_BASENAME ) ); if ( $this->is_image_file( $file_abspath ) ) { if ( ( $image_id = $this->import_image_file( $gallery_id, $file_abspath, $basename, false, false, false ) ) ) { $retval['image_ids'][] = $image_id; } } } // Add the gallery name to the result. if ( ! isset( $gallery ) ) { $gallery = $gallery_mapper->find( $gallery_id ); } $retval['gallery_name'] = $gallery->title; return $retval; } public function maybe_base64_decode( $data ) { $decoded = base64_decode( $data ); if ( $decoded === false ) { return $data; } elseif ( base64_encode( $decoded ) == $data ) { return base64_decode( $data ); } return $data; } public static function register_custom_post_types() { $types = [ 'ngg_album' => 'NextGEN Gallery - Album', 'ngg_gallery' => 'NextGEN Gallery - Gallery', 'ngg_pictures' => 'NextGEN Gallery - Image', ]; foreach ( $types as $type => $label ) { \register_post_type( $type, [ 'label' => $label, 'publicly_queryable' => false, 'exclude_from_search' => true, ] ); } } /** * Sanitizes a directory path, replacing whitespace with dashes. * * Taken from WP' sanitize_file_name() and modified to not act on file extensions. * * Removes special characters that are illegal in filenames on certain * operating systems and special characters requiring special escaping * to manipulate at the command line. Replaces spaces and consecutive * dashes with a single dash. Trims period, dash and underscore from beginning * and end of filename. It is not guaranteed that this function will return a * filename that is allowed to be uploaded. * * @param string $dirname The directory name to be sanitized * @return string The sanitized directory name */ public function sanitize_directory_name( $dirname ) { $dirname_raw = $dirname; $special_chars = [ '?', '[', ']', '/', '\\', '=', '<', '>', ':', ';', ',', "'", '"', '&', '$', '#', '*', '(', ')', '|', '~', '`', '!', '{', '}', '%', '+', chr( 0 ) ]; $special_chars = apply_filters( 'sanitize_file_name_chars', $special_chars, $dirname_raw ); $dirname = preg_replace( "#\x{00a0}#siu", ' ', $dirname ); $dirname = str_replace( $special_chars, '', $dirname ); $dirname = str_replace( [ '%20', '+' ], '-', $dirname ); $dirname = preg_replace( '/[\r\n\t -]+/', '-', $dirname ); $dirname = trim( $dirname, '.-_' ); return $dirname; } public function sanitize_filename_for_db( $filename = null ) { $filename = $filename ? $filename : uniqid( 'nextgen-gallery' ); $filename = preg_replace( '#^/#', '', $filename ); $filename = sanitize_file_name( $filename ); if ( preg_match( '/\-(png|jpg|gif|jpeg|jpg_backup)$/i', $filename, $match ) ) { $filename = str_replace( $match[0], '.' . $match[1], $filename ); } return $filename; } /** * Sets a NGG image as a post thumbnail for the given post * * @param int $postId * @param Image $image * @param bool $only_create_attachment * @return int */ public function set_post_thumbnail( $postId, $image, $only_create_attachment = false ) { $retval = false; // Get the post ID. if ( is_object( $postId ) ) { $post = $postId; $postId = isset( $post->ID ) ? $post->ID : $post->post_id; } // Get the image. if ( is_int( $image ) ) { $imageId = $image; $mapper = ImageMapper::get_instance(); $image = $mapper->find( $imageId ); } if ( $image && $postId ) { $attachment_id = $this->is_in_media_library( $image->pid ); if ( $attachment_id === false ) { $attachment_id = $this->copy_to_media_library( $image ); } if ( $attachment_id ) { if ( ! $only_create_attachment ) { set_post_thumbnail( $postId, $attachment_id ); } $retval = $attachment_id; } } return $retval; } /** * Uploads an image for a particular gallery * * @param int|object|Gallery $gallery * @param string|bool $filename (optional) Specifies the name of the file * @param string|bool $data (optional) If specified, expects base64 encoded string of data * * @return array|array[]|bool|int $image */ public function upload_image( $gallery, $filename = false, $data = false ) { // Ensure that we have the data present that we require. // // Security::verify_nonce() is a wrapper to wp_verify_nonce(). // // phpcs:disable WordPress.Security.NonceVerification.Missing // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( isset( $_FILES['file'] ) && 0 === $_FILES['file']['error'] && isset( $_FILES['file']['tmp_name'] ) && isset( $_REQUEST['nonce'] ) && Security::verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ), 'nextgen_upload_image' ) ) { $file = $_FILES['file']; if ( $this->is_zip() ) { $retval = $this->upload_zip( $gallery ); } elseif ( $this->is_image_file() ) { $retval = $this->import_image_file( $gallery, $file['tmp_name'], $filename ? $filename : ( isset( $file['name'] ) ? $file['name'] : false ), false, false, true ); } else { // Remove the non-valid (and potentially insecure) file from the PHP upload directory. if ( isset( $_FILES['file']['tmp_name'] ) ) { $filename = $_FILES['file']['tmp_name']; @unlink( $filename ); } throw new \E_UploadException( __( 'Invalid image file. Acceptable formats: JPG, GIF, and PNG.', 'nggallery' ) ); } } elseif ( $data ) { $retval = $this->upload_base64_image( $gallery, $data, $filename ); } else { throw new \E_UploadException(); } // phpcs:enable WordPress.Security.NonceVerification.Missing // phpcs:enable WordPress.Security.NonceVerification.Recommended return $retval; } /** * Uploads base64 file to a gallery * * @param int|\stdClass|Gallery $gallery * @param string $data base64-encoded string of data representing the image * @param string|false (optional) $filename specifies the name of the file * @param int|false $image_id (optional) * @param bool $override (optional) * * @return bool|int */ public function upload_base64_image( $gallery, $data, $filename = false, $image_id = false, $override = false, $move = false ) { $temp_abspath = tempnam( sys_get_temp_dir(), '' ); // Try writing the image. $fp = fopen( $temp_abspath, 'wb' ); fwrite( $fp, $this->maybe_base64_decode( $data ) ); fclose( $fp ); return $this->import_image_file( $gallery, $temp_abspath, $filename, $image_id, $override, $move ); } /** * @param int $gallery_id * @return array|bool */ public function upload_zip( $gallery_id ) { if ( ! $this->is_zip() ) { return false; } // Security::verify_nonce() is a wrapper to wp_verify_nonce(). // // phpcs:disable WordPress.Security.NonceVerification.Missing // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( ! isset( $_REQUEST['nonce'] ) || ! Security::verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ), 'nextgen_upload_image' ) ) { return false; } // phpcs:enable WordPress.Security.NonceVerification.Missing // phpcs:enable WordPress.Security.NonceVerification.Recommended $retval = false; $memory_limit = intval( ini_get( 'memory_limit' ) ); if ( ! extension_loaded( 'suhosin' ) && $memory_limit < 256 ) { @ini_set( 'memory_limit', '256M' ); } $fs = Filesystem::get_instance(); // Uses the WordPress ZIP abstraction API. include_once $fs->join_paths( ABSPATH, 'wp-admin', 'includes', 'file.php' ); WP_Filesystem( false, get_temp_dir(), true ); // Ensure that we truly have the gallery id. $gallery_id = $this->get_gallery_id( $gallery_id ); // The nonce was already checked above, by Security::verify_nonce(). Also PHP-CS still flags this particular // line when using phpcs:ignore, thus the disable/enable pairing found here. // // phpcs:disable WordPress.Security.NonceVerification.Missing $zipfile = $_FILES['file']['tmp_name']; // phpcs:enable WordPress.Security.NonceVerification.Missing $dest_path = implode( DIRECTORY_SEPARATOR, [ rtrim( get_temp_dir(), '/\\' ), 'unpacked-' . I18N::mb_basename( $zipfile ), ] ); // Attempt to extract the zip file into the normal system directory. $extracted = $this->extract_zip( $zipfile, $dest_path ); // Now verify it worked. get_temp_dir() will check each of the following directories to ensure they are // a directory and against wp_is_writable(). Should ALL of those options fail we will fallback to wp_upload_dir(). $size = 0; $files = glob( $dest_path . DIRECTORY_SEPARATOR . '*' ); foreach ( $files as $file ) { if ( is_array( stat( $file ) ) ) { $size += filesize( $file ); } } // Extraction failed; attempt again with wp_upload_dir(). if ( $size == 0 ) { // Remove the empty directory we may have possibly created but could not write to. $this->delete_directory( $dest_path ); $destination = wp_upload_dir(); $destination_path = $destination['basedir']; $dest_path = implode( DIRECTORY_SEPARATOR, [ rtrim( $destination_path, '/\\' ), rand(), 'unpacked-' . I18N::mb_basename( $zipfile ), ] ); $extracted = $this->extract_zip( $zipfile, $dest_path ); } if ( $extracted ) { $retval = $this->import_gallery_from_fs( $dest_path, $gallery_id ); } $this->delete_directory( $dest_path ); if ( ! extension_loaded( 'suhosin' ) ) { @ini_set( 'memory_limit', $memory_limit . 'M' ); } return $retval; } public static function wp_query_order_by( $order_by, $wp_query ) { if ( $wp_query->get( 'datamapper_attachment' ) ) { $order_parts = explode( ' ', $order_by ); $order_name = array_shift( $order_parts ); $order_by = 'ABS(' . $order_name . ') ' . implode( ' ', $order_parts ) . ', ' . $order_by; } return $order_by; } /** * Gets the id of an image, regardless of whether an integer or object was passed as an argument. * * This method is, as of 3.50's release, used by EWWW and WP-SmushIt * * @param object|int $image_obj_or_id * @return null|int * @deprecated */ function _get_image_id( $image_obj_or_id ) { $retval = null; $image_key = $this->_image_mapper->get_primary_key_column(); if ( is_object( $image_obj_or_id ) ) { if ( isset( $image_obj_or_id->$image_key ) ) { $retval = $image_obj_or_id->$image_key; } } elseif ( is_numeric( $image_obj_or_id ) ) { $retval = $image_obj_or_id; } return $retval; } } PK!RޕDataStorage/EXIFWriter.phpnu[=' ) ) { require_once NGG_PLUGIN_DIR . 'lib' . DIRECTORY_SEPARATOR . 'pel-0.9.12/autoload.php'; } else { require_once NGG_PLUGIN_DIR . 'lib' . DIRECTORY_SEPARATOR . 'pel-0.9.9/autoload.php'; } use Imagely\NGG\Display\I18N; use lsolesen\pel\PelDataWindow; use lsolesen\pel\PelJpeg; use lsolesen\pel\PelTiff; use lsolesen\pel\PelExif; use lsolesen\pel\PelIfd; use lsolesen\pel\PelTag; use lsolesen\pel\PelEntryShort; use lsolesen\pel\PelInvalidArgumentException; use lsolesen\pel\PelIfdException; use lsolesen\pel\PelInvalidDataException; use lsolesen\pel\PelJpegInvalidMarkerException; class EXIFWriter { /** * @param $filename * @return array|null */ public static function read_metadata( $filename ) { if ( ! self::is_jpeg_file( $filename ) ) { return null; } $retval = null; try { $data = new PelDataWindow( @file_get_contents( $filename ) ); $exif = new PelExif(); if ( PelJpeg::isValid( $data ) ) { $jpeg = new PelJpeg(); @$jpeg->load( $data ); $exif = $jpeg->getExif(); if ( null === $exif ) { $exif = new PelExif(); $jpeg->setExif( $exif ); $tiff = new PelTiff(); $exif->setTiff( $tiff ); } else { $tiff = $exif->getTiff(); } } elseif ( PelTiff::isValid( $data ) ) { $tiff = new PelTiff(); $tiff->load( $data ); } else { return null; } $ifd0 = $tiff->getIfd(); if ( null === $ifd0 ) { $ifd0 = new PelIfd( PelIfd::IFD0 ); $tiff->setIfd( $ifd0 ); } $tiff->setIfd( $ifd0 ); $exif->setTiff( $tiff ); $retval = [ 'exif' => $exif, 'iptc' => null, ]; @getimagesize( $filename, $iptc ); if ( ! empty( $iptc['APP13'] ) ) { $retval['iptc'] = $iptc['APP13']; } } catch ( PelIfdException $exception ) { return null; } catch ( PelInvalidArgumentException $exception ) { return null; } catch ( PelInvalidDataException $exception ) { return null; } catch ( PelJpegInvalidMarkerException $exception ) { return null; } catch ( \Exception $exception ) { return null; } finally { return $retval; } } /** * @param $origin_file * @param $destination_file * @return bool|int FALSE on failure or (int) number of bytes written */ public static function copy_metadata( $origin_file, $destination_file ) { if ( ! self::is_jpeg_file( $origin_file ) ) { return false; } // Read existing data from the source file. $metadata = self::read_metadata( $origin_file ); if ( ! empty( $metadata ) && is_array( $metadata ) ) { return self::write_metadata( $destination_file, $metadata ); } else { return false; } } /** * @param $filename * @param $metadata * @return bool|int FALSE on failure or (int) number of bytes written. */ public static function write_metadata( $filename, $metadata ) { if ( ! self::is_jpeg_file( $filename ) || ! is_array( $metadata ) ) { return false; } try { // Prevent the orientation tag from ever being anything other than normal horizontal. /** @var PelExif $exif */ $exif = $metadata['exif']; $tiff = $exif->getTiff(); $ifd0 = $tiff->getIfd(); $orientation = new PelEntryShort( PelTag::ORIENTATION, 1 ); $ifd0->addEntry( $orientation ); $tiff->setIfd( $ifd0 ); $exif->setTiff( $tiff ); $metadata['exif'] = $exif; // Copy EXIF data to the new image and write it. $new_image = new PelJpeg( $filename ); $new_image->setExif( $metadata['exif'] ); $new_image->saveFile( $filename ); // Copy IPTC / APP13 to the new image and write it. if ( $metadata['iptc'] ) { return self::write_IPTC( $filename, $metadata['iptc'] ); } } catch ( PelInvalidArgumentException $exception ) { return false; } catch ( PelInvalidDataException $exception ) { error_log( "Could not write data to {$filename}" ); error_log( print_r( $exception, true ) ); return false; } // This should never happen, but this line satisfies phpstan. return false; } // In case bcmath isn't enabled we use these simple wrappers. static function bcadd( $one, $two, $scale = null ) { if ( ! function_exists( 'bcadd' ) ) { return floatval( $one ) + floatval( $two ); } else { return bcadd( $one, $two, $scale ); } } static function bcmul( $one, $two, $scale = null ) { if ( ! function_exists( 'bcmul' ) ) { return floatval( $one ) * floatval( $two ); } else { return bcmul( $one, $two, $scale ); } } static function bcpow( $one, $two, $scale = null ) { if ( ! function_exists( 'bcpow' ) ) { return floatval( $one ) ** floatval( $two ); } else { return bcpow( $one, $two, $scale ); } } /** * Use bcmath as a replacement to hexdec() to handle numbers than PHP_INT_MAX. Also validates the $hex parameter using ctypes. * * @param string $hex * @return float|int|string|null */ public static function bchexdec( $hex ) { // Ensure $hex is actually a valid hex number and won't generate deprecated conversion warnings on PHP 7.4+. if ( ! ctype_xdigit( $hex ) ) { return null; } $decimal = 0; $length = strlen( $hex ); for ( $i = 1; $i <= $length; $i++ ) { $decimal = self::bcadd( $decimal, self::bcmul( strval( hexdec( $hex[ $i - 1 ] ) ), self::bcpow( '16', strval( $length - $i ) ) ) ); } return $decimal; } /** * @param string $filename * @param array $data * @return bool|int FALSE on failure or (int) number of bytes written */ public static function write_IPTC( $filename, $data ) { if ( ! self::is_jpeg_file( $filename ) ) { return false; } $length = strlen( $data ) + 2; // Avoid invalid APP13 regions. if ( $length > 0xFFFF ) { return false; } // Wrap existing data in segment container we can embed new content in. $data = chr( 0xFF ) . chr( 0xED ) . chr( ( $length >> 8 ) & 0xFF ) . chr( $length & 0xFF ) . $data; $new_file_contents = @file_get_contents( $filename ); if ( ! $new_file_contents || strlen( $new_file_contents ) <= 0 ) { return false; } $new_file_contents = substr( $new_file_contents, 2 ); // Create new image container wrapper. $new_iptc = chr( 0xFF ) . chr( 0xD8 ); // Track whether content was modified. $new_fields_added = ! $data; // This can cause errors if incorrectly pointed at a non-JPEG file. try { // Loop through each JPEG segment in search of region 13. while ( ( self::bchexdec( substr( $new_file_contents, 0, 2 ) ) & 0xFFF0 ) === 0xFFE0 ) { $segment_length = ( hexdec( substr( $new_file_contents, 2, 2 ) ) & 0xFFFF ); $segment_number = ( hexdec( substr( $new_file_contents, 1, 1 ) ) & 0x0F ); // Not a segment we're interested in. if ( $segment_length <= 2 ) { return false; } $current_segment = substr( $new_file_contents, 0, $segment_length + 2 ); if ( ( 13 <= $segment_number ) && ( ! $new_fields_added ) ) { $new_iptc .= $data; $new_fields_added = true; if ( 13 === $segment_number ) { $current_segment = ''; } } $new_iptc .= $current_segment; $new_file_contents = substr( $new_file_contents, $segment_length + 2 ); } } catch ( \Exception $exception ) { return false; } if ( ! $new_fields_added ) { $new_iptc .= $data; } if ( $file = @fopen( $filename, 'wb' ) ) { return @fwrite( $file, $new_iptc . $new_file_contents ); } else { return false; } } /** * Determines if the file extension is .jpg or .jpeg * * @param $filename * @return bool */ public static function is_jpeg_file( $filename ) { $extension = I18N::mb_pathinfo( $filename, PATHINFO_EXTENSION ); return in_array( strtolower( $extension ), [ 'jpeg', 'jpg', 'jpeg_backup', 'jpg_backup' ] ); } } PK!er??DataStorage/Sanitizer.phpnu[loadHTML( $data ); $el = $dom->getElementById( 'ngg_data_strip_html_placeholder' ); $parts = array_map( function ( $el ) use ( $dom ) { $part = $dom->saveHTML( $el ); return $part instanceof \DOMText ? $part->data : (string) $part; }, $el->childNodes ? iterator_to_array( $el->childNodes ) : [] ); return self::strip_html( implode( ' ', $parts ), $just_scripts ); } else { return \wp_strip_all_tags( $data ); } } // Remove all HTML elements. if ( ! $just_scripts ) { return \wp_strip_all_tags( $data ); } elseif ( class_exists( 'DOMDocument' ) ) { // Remove unsafe HTML. This can generate a *lot* of warnings when given improper texts. libxml_use_internal_errors( true ); libxml_clear_errors(); $config = \HTMLPurifier_Config::createDefault(); $config->set( 'Cache.DefinitionImpl', null ); $purifier = new \HTMLPurifier( $config ); $default_return = $purifier->purify( $data ); return \apply_filters( 'ngg_html_sanitization', $default_return, $data ); } else { // wp_strip_all_tags() is misleading in a way - it only removes PK!t>t>(Admin/Views/onboarding-wizard/step-2.phpnu[ PK!  Admin/Views/notifications.phpnu[

' . absint( $notifications->get_count() ) . '' ); ?>

' . absint( $notifications->get_dismissed_count() ) . '' ); ?>

    get_active_notifications(); foreach ( $active_notifications as $active ) { $notifications->get_notification_markup( $active ); } ?>
    get_dismissed_notifications(); foreach ( $dismissed_notifications as $dismissed ) { $notifications->get_notification_markup( $dismissed ); } ?>
PK![ Admin/Views/ecommerce.phpnu[

', '', '', '' ); ?>

Ecommerce Options

Good work. Keep making the web beautiful.

General Options

USD
 

SALES TAX NOTE: Sales tax is complex. CLICK HERE to learn more about sales tax and how NextGEN Pro calculates it. Because we use a third party service (TaxJar), an active Pro license is required to enable sales tax.

 
 

E-mail

 

Payment Gateway

 
 
 
 
 
 
 

Print Lab Integration

DO I NEED THIS? A credit card is needed only if you want to use automated print fulfillment.

WILL YOU CHARGE ME? You will not be charged now. Your card will only be charged if someone submits a print lab order on your site. At that point, you will be billed for print and shipping costs from the print lab. You would pay those costs yourself if you worked directly with the lab. We're just automating the process for you.

IS THIS SECURE? Assuming you've enabled SSL on your website, then yes. This form sends your card information directly to Stripe, one of the world's leading payment processors. It is stored securely at Stripe, not locally by WordPress or NextGEN Gallery. Note: Without SSL, this form is not 100% secure. You should also enable SSL before receiving payments from your own visitors.

AGREEMENT: By submitting your card here, you authorise Imagely to bill your card for the cost of print lab orders.

No card on file.

Proofing

 

PK!:mM9K9KAdmin/AMNotifications.phpnu[option && $cache ) { return $this->option; } $option = get_option( self::$option_name, [] ); $this->option = [ 'update' => ! empty( $option['update'] ) ? $option['update'] : 0, 'events' => ! empty( $option['events'] ) ? $option['events'] : [], 'feed' => ! empty( $option['feed'] ) ? $option['feed'] : [], 'dismissed' => ! empty( $option['dismissed'] ) ? $option['dismissed'] : [], ]; return $this->option; } /** * Fetch notifications from feed. * * @since 1.8.7 * * @return array */ public function fetch_feed() { $res = wp_remote_get( self::SOURCE_URL ); if ( is_wp_error( $res ) ) { return []; } $body = wp_remote_retrieve_body( $res ); if ( empty( $body ) ) { return []; } return $this->verify( json_decode( $body, true ) ); } /** * Verify notification data before it is saved. * * @since 1.8.7 * * @param array $notifications Array of notifications items to verify. * @return array */ public function verify( $notifications ) { $data = []; if ( ! is_array( $notifications ) || empty( $notifications ) ) { return $data; } $option = $this->get_option(); foreach ( $notifications as $notification ) { // The message and license should never be empty, if they are, ignore. if ( empty( $notification['content'] ) && empty( $notification['type'] ) ) { continue; } // Ignore if notification is not ready to display(based on start time). if ( ! empty( $notification['start'] ) && time() < strtotime( $notification['start'] ) ) { continue; } // Ignore if expired. if ( ! empty( $notification['end'] ) && time() > strtotime( $notification['end'] ) ) { continue; } // Check that the license type matches. if ( ! in_array( $this->get_license_type(), (array) $notification['type'], true ) ) { continue; } // Ignore if notification has already been dismissed. $notification_already_dismissed = false; if ( is_array( $option['dismissed'] ) && ! empty( $option['dismissed'] ) ) { foreach ( $option['dismissed'] as $dismiss_notification ) { if ( $notification['id'] === $dismiss_notification['id'] ) { $notification_already_dismissed = true; break; } } } if ( true === $notification_already_dismissed ) { continue; } $data[] = $notification; } return $data; } /** * Verify saved notification data for active notifications. * * @since 1.8.7 * * @param array $notifications Array of notifications items to verify. * @return array */ public function verify_active( $notifications ) { if ( ! is_array( $notifications ) || empty( $notifications ) ) { return []; } // Remove notifications that are not active, or if the license type not exists. foreach ( $notifications as $key => $notification ) { if ( ( ! empty( $notification['start'] ) && time() < strtotime( $notification['start'] ) ) || ( ! empty( $notification['end'] ) && time() > strtotime( $notification['end'] ) ) ) { unset( $notifications[ $key ] ); } } return $notifications; } /** * Get notification data. * * @since 1.8.7 * * @return array */ public function get() { if ( ! $this->has_access() ) { return []; } $option = $this->get_option(); // Update notifications using async task. if ( empty( $option['update'] ) || time() > $option['update'] + DAY_IN_SECONDS ) { if ( false === wp_next_scheduled( 'nextgen_admin_notifications_update' ) ) { wp_schedule_single_event( time(), 'nextgen_admin_notifications_update' ); } } $events = ! empty( $option['events'] ) ? $this->verify_active( $option['events'] ) : []; $feed = ! empty( $option['feed'] ) ? $this->verify_active( $option['feed'] ) : []; $notifications = []; $notifications['active'] = array_merge( $events, $feed ); $notifications['active'] = $this->get_notifications_with_human_readeable_start_time( $notifications['active'] ); $notifications['active'] = $this->get_notifications_with_formatted_content( $notifications['active'] ); $notifications['dismissed'] = ! empty( $option['dismissed'] ) ? $option['dismissed'] : []; $notifications['dismissed'] = $this->get_notifications_with_human_readeable_start_time( $notifications['dismissed'] ); $notifications['dismissed'] = $this->get_notifications_with_formatted_content( $notifications['dismissed'] ); return $notifications; } /** * Improve format of the content of notifications before display. By default, it just runs wpautop. * * @since 1.8.7 * * @param array $notifications The notifications to be parsed. * @return array */ public function get_notifications_with_formatted_content( $notifications ) { if ( ! is_array( $notifications ) || empty( $notifications ) ) { return $notifications; } foreach ( $notifications as $key => $notification ) { if ( ! empty( $notification['content'] ) ) { $notifications[ $key ]['content'] = wpautop( $notification['content'] ); $notifications[ $key ]['content'] = apply_filters( 'nextgen_notification_content_display', $notifications[ $key ]['content'] ); } } return $notifications; } /** * Get notifications start time with human time difference * * @since 1.8.7 * * @param array $notifications The array of notifications to convert. * @return array */ public function get_notifications_with_human_readeable_start_time( $notifications ) { if ( ! is_array( $notifications ) || empty( $notifications ) ) { return []; } foreach ( $notifications as $key => $notification ) { if ( empty( $notification['start'] ) ) { continue; } // Translators: Human-Readable time to display. $modified_start_time = sprintf( __( '%1$s ago', 'nggallery' ), human_time_diff( strtotime( $notification['start'] ), time() ) ); $notifications[ $key ]['start'] = $modified_start_time; } return $notifications; } /** * Get active notifications. * * @since 1.8.7 * * @return array $notifications['active'] active notifications */ public function get_active_notifications() { $notifications = $this->get(); // Show only 5 active notifications plus any that has a priority of 1. $all_active = isset( $notifications['active'] ) ? $notifications['active'] : []; $displayed = []; foreach ( $all_active as $notification ) { if ( ( isset( $notification['priority'] ) && 1 === $notification['priority'] ) || count( $displayed ) < 5 ) { $displayed[] = $notification; } } return $displayed; } /** * Get dismissed notifications. * * @since 1.8.7 * * @return array $notifications['dismissed'] dismissed notifications */ public function get_dismissed_notifications() { $notifications = $this->get(); return isset( $notifications['dismissed'] ) ? $notifications['dismissed'] : []; } /** * Get notification count. * * @since 1.8.7 * * @return int */ public function get_count() { return count( $this->get_active_notifications() ); } /** * Get the dismissed notifications count. * * @since 1.8.7 * * @return int */ public function get_dismissed_count() { return count( $this->get_dismissed_notifications() ); } /** * Check if a notification has been dismissed before * * @since 1.8.7 * * @param array $notification The notification to check if is dismissed. * @return bool */ public function is_dismissed( $notification ) { if ( empty( $notification['id'] ) ) { return true; } $option = $this->get_option(); foreach ( $option['dismissed'] as $item ) { if ( $item['id'] === $notification['id'] ) { return true; } } return false; } /** * Add a manual notification event. * * @since 1.8.7 * * @param array $notification Notification data. * @return bool */ public function add( $notification ) { if ( empty( $notification['id'] ) || $this->is_dismissed( $notification ) ) { return false; } $option = $this->get_option(); $current_notifications = $option['events']; foreach ( $current_notifications as $item ) { if ( $item['id'] === $notification['id'] ) { return false; } } $notification = $this->verify( [ $notification ] ); $notifications = array_merge( $notification, $current_notifications ); // Sort notifications by priority. usort( $notifications, function ( $a, $b ) { if ( ! isset( $a['priority'] ) || ! isset( $b['priority'] ) ) { return 0; } if ( $a['priority'] === $b['priority'] ) { return 0; } return $a['priority'] < $b['priority'] ? - 1 : 1; } ); update_option( self::$option_name, [ 'update' => $option['update'], 'feed' => $option['feed'], 'events' => $notifications, 'dismissed' => $option['dismissed'], ], false ); return true; } /** * Update notification data from feed. * * @since 1.8.7 * * @return void */ public function update() { $feed = $this->fetch_feed(); $option = $this->get_option(); update_option( self::$option_name, [ 'update' => time(), 'feed' => $feed, 'timeout' => strtotime( '+2 hours', current_time( 'timestamp' ) ), // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested 'events' => $option['events'], 'dismissed' => array_slice( $option['dismissed'], 0, 30 ), ], false ); } /** * Dismiss notification via AJAX. * * @since 1.8.7 */ public function dismiss() { // Run a security check. check_ajax_referer( 'nextgen_dismiss_notification', 'nonce' ); // Check for access and required param. if ( ! $this->has_access() || empty( $_POST['id'] ) ) { wp_send_json_error(); } $id = sanitize_text_field( wp_unslash( $_POST['id'] ) ); $option = $this->get_option(); // Dismiss all notifications and add them to dissmiss array. if ( 'all' === $id ) { if ( is_array( $option['feed'] ) && ! empty( $option['feed'] ) ) { foreach ( $option['feed'] as $key => $notification ) { array_unshift( $option['dismissed'], $notification ); unset( $option['feed'][ $key ] ); } } if ( is_array( $option['events'] ) && ! empty( $option['events'] ) ) { foreach ( $option['events'] as $key => $notification ) { array_unshift( $option['dismissed'], $notification ); unset( $option['events'][ $key ] ); } } } $type = is_numeric( $id ) ? 'feed' : 'events'; // Remove notification and add in dismissed array. if ( is_array( $option[ $type ] ) && ! empty( $option[ $type ] ) ) { foreach ( $option[ $type ] as $key => $notification ) { if ( $notification['id'] == $id ) { // phpcs:ignore WordPress.PHP.StrictComparisons,Universal.Operators.StrictComparisons.LooseEqual // Add notification to dismissed array. array_unshift( $option['dismissed'], $notification ); // Remove notification from feed or events. unset( $option[ $type ][ $key ] ); break; } } } update_option( self::$option_name, $option, false ); wp_send_json_success(); } /** * Delete the notification options. * * @since 1.8.7 * * @return void */ public static function delete_notifications_data() { delete_option( self::$option_name ); } /** * Get the license type for the current plugin. * * @since 1.8.7 * * @return string */ public function get_license_type() { if ( defined( 'NGG_PRO_PLUGIN_BASENAME' ) ) { return 'pro'; } elseif ( defined( 'NGG_PLUS_PLUGIN_BASENAME' ) ) { return 'plus'; } elseif ( defined( 'NGG_STARTER_PLUGIN_BASENAME' ) ) { return 'starter'; } return 'lite'; } /** * Helper Method to get icon * * @since 1.8.7 * * @param string $type Icon type. * @return string */ public function get_icon( $type = 'gear' ) { switch ( $type ) { case 'info': return ' '; case 'percent': return ' '; case 'check': return ' '; default: case 'gear': return ' '; } } /** * Helper to get notification marketup * * @since 1.8.7 * * @param array $notification The notification. * @return void */ public function get_notification_markup( $notification ) { $type = ! empty( $notification['icon'] ) ? $notification['icon'] : 'gear'; $allowed_html = [ 'svg' => [ 'class' => true, 'aria-hidden' => true, 'aria-labelledby' => true, 'role' => true, 'xmlns' => true, 'width' => true, 'height' => true, 'viewbox' => true, ], 'g' => [ 'fill' => true ], 'title' => [ 'title' => true ], 'path' => [ 'd' => true, 'fill' => true, ], ]; ?>
  • get_icon( $notification['icon'] ), $allowed_html ); ?>
  • ngg_condition_check_to_display_tooltip(); if ( ! $display_tooltip ) { return; } $url = admin_url( 'admin.php?page=ngg_addgallery' ); ?>

    ngg_condition_check_to_display_tooltip(); if ( ! $display_tooltip ) { return; } ?> count(); // Check if there are any galleries. if ( $gallery_count > 0 ) { return false; } // Bail if user is on manage galleries screen. $screen = get_current_screen(); if ( false !== strpos( $screen->id, 'ngg_addgallery' ) || false !== strpos( $screen->id, 'nggallery-manage-gallery' ) ) { return false; } // Bail if the user is not allowed to save settings. if ( ! current_user_can( 'manage_options' ) ) { return false; } // Bail if the user has dismissed the tooltip within 7 days. $show_tooltip = get_option( 'ngg_admin_menu_tooltip', 0 ); if ( $show_tooltip && ( $show_tooltip + 7 * DAY_IN_SECONDS > time() ) ) { // Dismissed less than 7 days ago. return false; } return true; } /** * Store the time when the float bar was hidden so it won't show again for 14 days. */ public function mark_admin_menu_tooltip_hidden() { check_ajax_referer( 'ngg-tooltip-admin-nonce', 'nonce' ); update_option( 'ngg_admin_menu_tooltip', time() ); wp_send_json_success(); } } PK!Legacy/css/nggallery.min.cssnu[PK!6SLegacy/css/nggallery.cssnu[/* CSS Name: Default Styles Description: NextGEN Default Gallery Stylesheet Author: Imagely Version: 2.13 This stylesheet is provided to allow users the ability of overriding the default styles for all display types */PK!Legacy/ngg-config.phpnu['9.)^Irsknr|x5PeVf^E=]6NYL6?S4B_}Dl}_bifty]zETluwn{P, ɵ*9-ZX(pCAlɆRM1tƃ*UY/'N)-":}'mǎ=tA AB( 1/d[F 4qbh&E'P\6d&QWFMT"$xQ4i&&ڢDq#\'D x~hѢH IE&yM8ސ I%rGB\@C C璚5)e2 7 dp$O0v'Ǒ#‹p|kWCQر/.%?$z taJ| ;_>@P` SC3T!V0!(cᆼ hc +@,/"h I A9HOrqJrIdO &3/.EjkfpPlhm駛q2 h_-",zkj Z> H  gYPʀ4 *4r @iZ𨩨 4@:jYX L`B`+sab[6Zj<VnުF 2M%Xj. 80 %;PK! ~ޤLegacy/images/loader.gifnu[GIF89aBBLLLzzzܠ! NETSCAPE2.0!Created with ajaxload.info! ,BBIT̻qֱUalK'eޠar,+0X4^epX!Gw@YfT1xRNJ*;gh%]~[5LIXLs{_}Rrul_^Ld!;a|]_k,qMmn8i-9~oi.)^)M.^?xmip-p%PX_ +O]{ XP A0B9F@!)N\ɲK?b6$89zlr ͜8m JhŒV YcL-"M&m:US7UQ8b~(`)+դԔ"UN'ֶN]q@Rkjkgoq1>uGu|f!xXR֙Ipaoʣ2xC _LPr`Dz/8͘BfIeY5E^%Gߜ}^8 }Nzczi$0Y@MR BT<! ,BBIT̻!qXalKfyV&ޠaTd0 l*VBAp@T |QNJTJ`Y%` slGI[GpkV~zet"G/,cz5awo8S)A!&hTdj7kAgBsj&aˀ#ԭ9/\훷 u}K8x `@['eq]>!]o\dC8sɳJ{JB@躟 Tg(FPJF96cT4Q<&\S*F"pT5eg]bcCo.V`Kx&#խUì@I/5GNtqhi-` UZqHZz'낗.d>N!UwWU59##/p/r7ڙ$JǍ{B_)E#+M:4R`OVW K4J\! ,BBIT̻!qX`lKVA8h|Un*R8 ,' %ep8Ni'bBIXrM^n5&4r`MqIMRl&W{x[{[1.di"S0no&,Ubm8U9"ASf&ȹIɌhơ)׾dD`ϰ-ÍT\sdX@@~* naxD˰=`aE-ԫD 0pE I͛8P)1g@FI͂H!ɴӧֲd(9$jHS*])jNe| *nIw({AD׾!(l .XvE#5o@s,F/L&F>Yz\j3f3ش+ѿ#LGY//DfZh_ 4[E1~Rқ/'z|y㾿GKw?u: |RzQ{_zy)( u_E! ,BBIt̻! pX`lK[%ĔI8hk}PR(X4M8 Pag'QTHRzz*0PiS1 eUK\)t0k)sZ);_`XpNv,od",vY)B~*Bgn.@RqdƟ&M-YCXY&bS^:ftU7NȦ+uk""FdGCs e >UBH!y_ʜI%5ֻ9!ϜO҄s ϣH*52fÌ!(bgȕW,0GQ+X"4dpUW eiNw]i#ykw-^SmT vwb )gߊ|f7FƳi!iͰjn\I֒T﹄"Kڷ A, jJ/Ro]\h@-q q\/wwk-8.|t+|x'9ן 1UimGN! ,BBIt ̻1 X`lKV@8( +E^nX U DAPaG4P6Qo2HVLi 1lMЇrm0 ys0*HvXh^fHYn]29)/C|lO8sHp9TfCeSRŪbécU{qdRNᚢS:ȹZC~A7)l">&DGc1"^G @8Œ.OʜIEF,rsBʐ"FS А}*]ʴ)=-c93Sb1ej6MwإRҺtb3պYcۓ"BrdL!^ikjp Ve O3RfH& iI$Y!J ̊$ՙu`@q_ Y3_ʾ{yᩮ79-oHx~*kƝԖT&|مLY^Ez! ,BBIt ̻1 f!,EU@8(<2Un@*Q'A (6I'N&*%3@F nb./<`J[LYm_sjvxdOu+YVc|6!r+uR(9Nn8ufmD9¦s|!{uRTN޺5dÚtOUXHWd#I JHpmaC/'Eo;hN\ɲ˗+IAき67賨ѣHyRgG:ٱz%Qx3#FN&G 0M#Zp"֚4r@eRDגօ"ԉ:)fhPyX,1@AIwtl V3:#?jwc[rA^\Lܼ|ͣVjbk8 ryd}'8K>x dD|,E'wC܂QL ӡ<! ,BBI̻Q 0X`lKV@8(IUn@*FIɚO"FTb=@)!|RB# ea ^-؎sdM[QNnV~iI/huQfU9c?u8_@:cp8v?.,s~l_!&a^ ~!#.)S޶6#"ئr^&++bG.F'F1tqE1$(S\r0[8 eΠS=: J#Icj$3xTXҟŞ^jS3\e.,h,CJG25[oIe+[y-VvWV9{[q ~֚\MR9Ϧbj%@u]]zْ*|@p|1*Ʊ3*>@ O|c@E ] *|-Ȭ$¦\Nȿ拜B/cHk썭pQ} v]|OPBd㛫egw6fDV\UW Ĝ=! ,BBI!̻VQXDalK[ޠhSE<n *Q ٳhpIL# Ti&&mSfO=pRZnP`{/!J3Ve.{bA!&9_HC8#`]v7wfl&C):D)eU-@{"ڱIT.a7FF3Fϋȭ=rŋ3j%G#' cȇTI˗0cA - 8@h){г\m2uX)x2;U6D (alDu]۔Kʧ1.VxB Yx/ps/Wvq'X0eW  )YCh[[a'U eTYxI=-?3sN5;38>]zSb'i (Xpb+Hfyy/lX_oi>WF]! ,BBI!̻f,%njko=!EX@;!J7Ś@(\<2o TptmNyiM Otysc'}sxQYr"T+D.S`X R#P][+RDd-Rj^G4m.^P?> HפvHP0 J%Ǐ CHRd SxHI3)c~yI͛0j#y`Zyv @KwфmםU]! ,BBI̻Yb,%nzm 4Ujщ2XF ļCC2&@ўtՆ$5! w"2QL)\5yD"_lQ5Ws@zPXe/Zx<{+y5Pz,qc-qn!`!"M([ѪAۈ˼΄+f$U-:rE[xg7z2nA]aȱǏ,\ē" (9!ڀ/_6cI͛]ȉe$Kde@J~XB 1z疨V;jkt<Xh\H;ςE;;')(K@8脽2 \=t@Y*4F m옂љ@نF(v5Е< a +3&|5䤏) eH7hE%ƌWV0z$cCžf}g5B\D`:! ,BBI̻qf,GUHޠϓI60XO =$p(CկPZY{(0DF>A{54:,F=KfY{kw(h8Uz}-vz\7HdCz+hCULlQƤHLy7'Lv_ּԺvA7=  S #( _:L0->4S^2ֈwaEiH\ɲ˗8$˜s8s>' U0o xѣHZU}zZ 3UP\H0N3xRNN1\Th_nޞ*}妉ȓP sK`9{C > 2Y2zq耴PjլIo(j6vDxPdM%=G s}K168v#qGq" hfU="ޱ\H5ßR1D^TQ#3q7]8_S N4O5&BQ;PK!'ErLegacy/images/mrss-icon.gifnu[GIF89a' dQa#h8- $t8xw.,.;L~AL!4&FL<=_=KLXBeQGq^FT[XnbKT[ofhDr{vt~l~¡ϴؾ! ,' &:B?;?CCDID>(RR?5;BBDQUI(KK;1005:>OQ$++?%%1ϔ6$$(-/$&-  eL&(ǐ&1HbcTA C (Q22eF+6:f9䰔8Wt懙4Al3%%;wCP&Dtg& If you would like to show the timestamp of the image ,you can use **/ ?>

    alttext ); ?>

    href_link; ?>
    number; ?> total; ?>

    description ); ?>

    PK!ffLegacy/view/album-extend.phpnu[ If you would like to show the timestamp of the image ,you can use **/ ?>
    <?php echo esc_attr( $gallery->title ); ?>

    galdesc; ?>

    counter > 0 ) : ?>
    PK!( !Legacy/view/imagebrowser-exif.phpnu[ If you would like to show the timestamp of the image ,you can use **/ ?>

    alttext ); ?>

    href_link; ?>
    number; ?> total; ?>

    description ); ?>

    PK!%b  Legacy/view/gallery-carousel.phpnu[ If you would like to show the timestamp of the image ,you can use **/ ?>
    <?php echo esc_attr( \Imagely\NGG\Display\I18N::ngg_plain_text_alt_title_attributes( $current->alttext ) ); ?>
    PK!&1>I I Legacy/view/album-compact.phpnu[ If you would like to show the timestamp of the image ,you can use **/ ?> PK!.}Legacy/view/singlepic.phpnu[ If you would like to show the timestamp of the image ,you can use **/ if ( ! defined( 'ABSPATH' ) ) { die( 'No direct access allowed' );} ?> target="" thumbcode; ?>> <?php echo esc_attr( $image->alttext ); ?> description ) ) : ?> description; ?> PK!V$Legacy/view/imagebrowser-caption.phpnu[ If you would like to show the timestamp of the image ,you can use **/ ?>

    alttext ); ?>

    href_link; ?>
    number; ?> total; ?>

    description ); ?>

    PK!Qw%%Legacy/view/gallery.phpnu[ If you would like to show the timestamp of the image ,you can use **/ ?>
    show_slideshow ) { ?> hidden ) { continue;} ?> columns > 0 ) : ?> columns ) == 0 ) : ?>
    PK!yxxLegacy/view/gallery-caption.phpnu[ If you would like to show the timestamp of the image ,you can use **/ ?>
    show_slideshow ) { ?> hidden ) { continue;} ?> columns > 0 && ++$i % $gallery->columns == 0 ) { ?>
    PK!?bb&Legacy/fonts/YanoneKaffeesatz-Bold.ttfnu[ FFTMhx<,GDEFJ HGPOSpy 0GSUB*2tOS/2k˄A7`cmapDE8T>cvt X|8fpgm zAX gaspXtglyf۫<head(:X6hhea#:$hmtxě&:loca$B\maxp F4 namezFT`postPXL prepD"bH=9696~CDDEjkklqrrsvwwxz{{|~'()**+12 |DFLTcyrl(grek8latnFCAT "MOL "ROM "cpspkern mark&mark,  (&vv"~(*z  %&'()*+,-./0123456789:;<=>  #%234589:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgBBLRXR^djpzjjpjXXBBRBBRRdXS\S\SWSS@SR  H ~;FHKMX[\X&2   (        dddd   ~ ~% " #  !$  %  $$$$$     $$$$  $  %%%   # ! $ $$  % %.''00, /+00#  -  !1*)%++++#######   1111###             !!!+1+1+1+1!-&"$ #(    !- '' '' )  D%*,,.>EEGGIOQT!VX%Z^(-9@X^_mnvwxyz}!#'8:=CEEGHJJMMOQSZ\]_`bimnvvxy{}"$ ~  i   ;;<< DDFF IIKKLLNNRR[[ ^^aajjkk oorr ttzz               #! "       ;<DFIKLNR[^ajklortz~, y(  ##??AAdd ~~%                              #?Ad~. :@FLRX^djpv|WZ>KMOPR[kmopr{Dkrw{()+,-/01:@FLRX^djpv|}F -"(.4:@FLRX^djpv| $*06<BHNTZ`flrx~ &,28>DJPV\bhntz "(.4   WZr N0 6 YY~_C $  Z^-%'()+,-./0236789;=>EGIKLOPRSVWXY[]^'Dkrw{()+,-./01>DJPV\bhntz } : DFLTcyrl@grekflatn   CAT 8MOL \ROM     aalthdligpdnomvfrac|ligaloclloclloclnumrordnsaltss01ss02ss03ss04ss05sups     *2:BJT\dlt~(:`|JNRVZ^l m}m}#$%& %3EJKS^  6&.|uv #$%&  #$%&   PzP 0z0|uv, %E3S^X6 "(JPJMPMJJKKJ   ^ zz0Pm}m}%3ESrXKX^2,UKWN 8   4 ~#+37IM[ek7&_    " & 0 : D t !!!"!&!.""""""""+"H"`"e%  "*.69LP^jn7&    & 0 9 D t !!!"!&!.""""""""+"H"`"d% baS zw8 |sD ߽ߺ߲߱߯߬ߩߝ߁jg   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`absefjyqlwkthx7m}5do"n~cz(/r+,-{0.) $@!BS CSD##!+>3#632#"&5=J*1' F%!'  b*H)#$G 0@- BOQE   &+.547632.547632- !H !G00k/3R@O$ Bk  Y Z D3210//.,)('&#"###++#7##7#4>;7#4>;7>337>33+'#3 &'8J'8/ 7 (&9K&9- [JK *5I5I*T*3G3G*TTT$e0,@) &BWSD)(+$#5.54673254&/&54675463.#"ev/614 %BDp+?;0520  5)) vEQt ?<!{389E R{ ,  %2?8@5 B[[SCSD$&%#$&%,+.532#".53254.#"32#".53254.#";!1/:FG19j  /:FG19h "  f   NFb[PM,,g+)): NFb[PM/,g+)):7@I@F,;9' BSCSCSD888@8?&+'(")+#"'#"5467&54632.#"654&'632+7&'33  36W=0JSTFU 5 "U< \#33*"!+7NB8 )88;b H?K.#&VGP( $BR'H"'G #@ BOQE &+.547632- !G0;?"@BSD&$+6#".54>327+ K>=Kb2,(q婙r(?"@BSD&#+'>32#"&'6ubJ=>K b\(mٞ~(,   +6x@  $5/BKPX@%h`fiS D@&hhfiS DY#.$.#!+#"/&326&54?#"/&632547'&32#"&'7 *" %w0!v9D; N * z /)  W#(1VY |!$ *okw%@"O[SG"!++#5#46;54633wk'8l&9'k9'k@ BOSG%!+>32#"'>7&5%"%#- #_%%#'G.+J@OSG"!+6;+#'9' @SD#!+>32#"&5' F%!' ^*H)#$ e @jD!+#>3,=-;   |X @[SD$&%!+632#".532654&#"V]^W PGFNy  !&xKGfUT%oWShk|X1@. BjjT D%"'+&54>323267#!&5463{7Md 8% 9G  & 1)&# |X%"@B[S D%'&++6546767>54&#"&546323265#! !J0+ PoERG5:?L3U  :`=H" 2!FG6_KR1 4,!qX%6@3%Bh[OSG%)%$+654&#"&54632#"546732654&'? @7aMGDa7A~eg <55UDHJ'2 B7oEKC{6 ,JA4+C_ /@, B[S D''+$67+#5#&54>7632&37T# (=&O\&zJ a!+G g&D~٨1sX#=@:!Bhf[OSG&&$"B+#"&'632#".54732>54.#"!sl Lhzn&2 7)967-,2-'}Mt6$1L&56 ;~"C@@B[S CSD"!$%#+#".54632&#">3654&#"36HMJull (*AA7* '*(M^dKyѬ(+#brO76=0 $X@kMSG7+".54>7#"5!&g008R%Vchs JAc~$23@0, BSCSD%%%2%1$#*$+#"&547&'&54632654&#654&'&'3~'O8aYb._J3-(*A#)#&+ K2W5lUuG%%6T\7&5& G&!'$"%#- #*I)#$%%#'G.+!Op@  @a!+$#"/&547%o #4i#+|)SXw!@[OSG"""!+63!#!63!#!JJ&8''9&&@u@  ?a!+632&'4?''  $%u5i"*}$%RY *58@5% BhSCSD31.,*)" +#"'.54767>54&#"&5463632#"&5F"!  7   #T0U' F%!' L==L/$   $0%* /**H)#$(ACPKPX@93  (B@93  ( BYKPX@5   [S C S C S CSDKPX@?   [S C S CS C S CSD@= [   [ S CS C S CSDYY@DDDPDPMKGE@>#%"%%%&$"+$3254.#"327#".54632#"'#".5463276#"&567632.#"326? :NLSa.%VK\xiOcF]D!P)5:,$'' (Z84i ej,;= *!#Bƾ;v֕ECZK:$ (2?1$02(d(@% BZ C D##1+$#"/##"'632&'3 #!##)"  ]  XPHu>^\ ;@8B[S CS D %(0+;2+654+3654.+3b7%s\_$ GT k4+TF>,,;+@(BSCSD%%%+&#"327#".53%2<"2A954.+3S*Ze`4~ʷ+xVW".@+[S CS D####+%+46;+3+   z hc(0 &0 %1")@& B[S C D###"++3++46;" z h^ . %1]!6@3!BYSCSD"&%& +#".54>32&#"3275#54;-[MP!2^L3:.26 /~ 9<"(4pefe" Hl_ @Y C D###!+$###4>334>3_ 7/b 7/ 7/b 7/ A   X @ C D#+>3# (> 8/X  @ B CSD%#+>3#"&54732>5 (?FPA.')VT$#'(u@B C D#)) +32#"'.'&'#4>3 #2t77&*' 70 70o2Ć n,   @ CT D#!+%+4>33 '= .'@$* Bh C D#+*#!+6;#7>7'+'&'#46;>?R ] 80 %0 ./#  6, TP  EX GT '* SH  &88$@ B C D"("!+>3+&'#4;&=! 6.Vj  7.Xi" X I|l ?ye@SCSD&&&"+>32#".532>54.#")SCCL#(QDEL#   B>D3232732>54.#?#:H8@)SCCL#,0!  :"@EDB> #u3reU^-2i^ab.c$;@8 BYS C D#!$$##*+#"'&'##46;2654&+T,FP&< 6. ^$ZP7k X 6I62I&%@" BSCSD&)%$+&54632.#"#"&54732654&/'\V 4P`#@C3("[D$FS8! 4&{-I-'*&(&.#y r@S C D"#"++##543!r k 6.zTh  TT}$@! B CTD&#$!+63274>3#".54>3&% (?\:JO )@, ? `4V@ @B CD(' +#"'&'&54;67>;01 Q ]3, b;cJ a{* D.-@*Bh CSD%5((!+!#"/&'#"'&'&546;367>;367>;5,.  19* H  ]2+ H4 + a?o`J>eI |z  b* @B C D($'"+$+'&'+&>36?>3{&'`m D7  70p| u:=E2ggB i#PD/W l@ B C D*$!+6#&>3>?>3 7/} @7 70z  #z$#{$n j e%@" BS CS D%#% +3!327#!&547#"5, Ԝ+ ϝ XRX8W5@[SD$#"++3+4>;W n "+'7'   ] ,BKPX@ jD@ jaY$#+#'4>3]7)6(  86@YSD$#"+>;#4>;+ n "+'.7' " % @ @a +6#"&'7'b ]#~E8 h@OSG"!+63!#! JF'9&1 @ BkD +#.'>3mb  oU!M37):@7 )B[SCSD$$'$%"+$#".5463254&#"&547>32#"3276576Z+=&@4)?: R6E9y `J EA^GE# 7C/o#.% k#Y3@0BCSCTD$#%"+>3632#"'32654&#"#(6#3<59S5P%y \o-WqC9%@" BSCSD&%%"+&#"327#".54>32 !!' $ =06?3M2%. Dh3#".546325#"327)5DN2E+K?%  5!hdMLWB 8D ;@8B[SCSD %%+67#"&54>32327654&#: Q=KP/L59u#+8b,!gr~,W7 3*;5432&#"3++#  !d ))+I 4 [<" 94 (E-$ | <y)4@@! 8BKPX@*[SCSCSD@([SCQCSDY@**><*4*3%+-%" +#"'#"'#"547&547&546323654&#"3.'3265y# MU CA^`D6?3>32#4&#"#!)557% 8.  6/3!q 8/*5* )(-$, ; *@'BS CCSD%$$!+632#"&5#"&54732654>3%s3632#654#"#654#"!)538S$I >4,  60 U2M4!! 7+|  ~0#e! @C D!+6#4>3 6/)4 5!(,@)("BSC D$#6#&" +32632#4&#"+4&#"#hS59=11 7- !1  6.81 s  x !L$@!BSC D$#%!+632#4&#"#;]$NB 9/  6.8I Z) V @SCSD&&% +32#".532>54.#"8C!QS;B!z   -nd|'pnJIKHIEDb!;V7@4  BSCSCD&$#% +32#"'#"&532>54.#"`UOR"9(,!}  Xs2 k^Y01 :M7@4BSCSCD$###"+"'5#"&532#"327M 69D<-z  "`'4UnM9$!#@  BSC D$% +32&#"#eG'  70! 2%@"BSCSD$)$"+5432&#"#"5473254/{'00JZMv)/4WJ8|?K"5&CM;!+\  VBKPX@ CSCTD@jSCTDY@ $##"+>;54>33+327#".5#  &)4R <[+,=$ /#  !6 <1H$@!BCTD$#%!+$#"&54>33274>3-O*UB 90 7/ KLS  ~ (C@hC D"&#+54>33>?>3#"'<-   )?d4# V 66z  2 4KPX$B$BYKPX@CT DK.PX@CCT DK2PX@CC CT D@ hC CT DYYY@ 6&9"!+>3##"&/&'#"'&'&>3376?>;36? &8R$ !   >" = -B  8" NZB1oe;o1J63 =B4fbwt! @ BC D((#+$+'&'#/4636?>3t$F  8,vg(O8/om 1WY  7Z;/$ ?O!@ BCTD$$#+54>3>?>3#"547327 5)   )>p#4)\-) n67 CH2%T #%@" BSCS D%'%&+327+.547#"&546; 87"  R'  % :k3@ BSD32+#"547654&'&547>54'&5467.  TG&!B6K+) *+F2+(!(4D%"% #&F>;<X8/ 'K PX@ SD@ SDY#!+#4>3 (? +<  #k3@ BSD32+547654'&5467.547654&'&54632#.  UFw'!B6<#,) *+!84*(!D4)&!$ "R6:= P,@)BO[SG""$"#!+632327632#"'&#"#"&'P+" K,%# )' ((' ; $@!BSCSD$#!+#"54632#>3& G&!'=J*1*H)#$ SIMc$6@3$BhiOSG&$+&#"3267#5.5475463M !! ) &/6.,u053 KHC>(Mz fx)CkHS0@-B[[S D"%!""+$+&'#46;632&#"3+=/ 3 *: ")mZ~L3q9& &3>8'XNP++7z@ *& +B @ ?K2PX@j[SCD@jk[SDY@,,,7,620#/#!+$#"/#"'.54?&547'>326327&654&#"30 U.NR/b!] h! K/]Y-W X m)'.6.,4Ub! ^/JG.h!K%#W  X&AV2m^FQG36?>33+3~S 7/|Sj$O @7 70PSE|' 5&74' ZIH\n 4'0:: *@' BSCSD$%$"+#"'4632#"'4632"""Xtv+6D-@*?86/' BS CS D*(!'$+%#"&'&5473254''&'&547'&54632&#"'&>54'&'ZB-3&3.1ZC,2&3- 0^  .);C$  %2*);' .);C !# # / $:(T  "   & #@ S D   #+#"&54632#"&5463l:'Q"*"(''*"*"( ? /j!BKPX@"[[WSD@([[[OSGY@ $%%$#$$ +32#"&532654#"6&#"327#".5432 j`lhhdQ>?7Hy   "#[cslvnqMEEPP2  ./  #8@5#"B[WSD##$$&!+&#"&547632#".54325#"3275&1 b49>I#1e & Q &7574~ "f0 S/F@ '# BKPX@CSC D@[C DY+>72#.5>72#.5?D /23/ D@>C ,00, C>ohVJ GS gpd\MB =J[d"fhB DBK PX@_OQE@kOQEY$!+%#"&=#&5463!h $o QJ#@OSG""+ ? ,5*BK PX@4  ` ^ f   [ XS DK PX@5   h ^ f   [ XS DKPX@6   h f f   [ XS D@=   h f f [   [ O THYYY@'-- -5-5420.,*'%"!   $+#"&543654#"3#'&'##546;3254+``lhhd/Hy>?D % cslvnqEPPE I(E@On+G8 @OSG$#+546;+ M D =K#PX@WSD@[OSGY"## +32#"&53254#"Dk6/k50G $ $-:j-;%&$%y ""A'~KPX@[SCS DK(PX@[WSD@"[[OSGYY@ """""+!P !@ BWSD#%)+54767>54#"&546323#!9$ /%3g:G:5/"2#;%*$$#*44/Q48D*4@1 * B[WSD&$$&$+#"'&5473254'&#.5432654#"&547632$ dMH ,,G-, ! /.* (lx00KJ #( &    #Y801% @ BkD &+.'>32O 94q %7)3L<P"61@. BCTCD$#$#!+ "?@< "!B[ CSC D"#$$"# +#"'5#"532#"'4632#"327Y5$-J4%!!B;  %| zE C/U @OSG#!+632#"&5/&!F& ' +*I)#$A#@   BK PX@`[TDKPX@h[TD@!h[OTHYY@+2#".'>763254#"731)  8 9$#'6(  p;!F@BXD$$%+547>323#!&546;5""_ KG[S% !+ @WSD%%$ +32#".532654.#"/8-:\$[Q&\PH14C/25A/@+@ ?a$#+$.54>7.54>7.54>72'&54>7@D %/32/  D??D !,0M D?pgSG JV hoe\I<!j# ^f#>C@" < C.BKPX@% \   [C SD@* \  M  [C SDY@BA>=;9"&$#$$% +547>323#!&546;5#"&'632$+#"'5#&547>7>323&37""^ KG[T- *":J"0/0 OQ% %j( B%6%rS's#Ct@ "0BKPX@#[\CS D@'[\C S CDY@ CA%,$#$$% +547>323#!&546;5#"&'632654767>54#"&546323#!""^ KG[T- *"/$ /%3h:G:5/ #Q% %j#'/%*$&#*44/Q4 8 5PU@(2"N U@BKPX@1 [ [   \SC S D@6 [ [  M  \SC S DY@TSPOMKBA?=*&$$&%# +32#"&'#"'&5473254'&#.5432654#"&547632+#"'5#&547>7>323&37!)$-dMG *.F,, ./) (mx0E:J"0/0 P%jJ %( &    #Y80/( B%6%rS'< 36@3.BhSCTD 3 2+)#!+#"54632&546767654'&5763232>7#' G&!' F"!  6   ?T0*H)#$L==L/$  $0%*7 /*""%DY>@;$ BjjZ C D'&##2 +""%wY?@<% BjjZ C D(('##2 +""%(O;@8.( BjjZ C D'!##2"+~""%/O@;*  BKPX@)  O [Z CS DKPX@*  [ [Z CS D@1  h  [[Z CS DYY@8642&"#"##2 #+""%kOC@@ B  [Z C D&&&1&0,*%$$##2 +""%-O<@9 B[[Z C D"##!##2 #+=#E@B B[YS C S D#"##### +%+5##"'63!+3+36 0##  z go$_c(0 &0 %1i[#;5@ 54)&BK PX@$`[SCTDKPX@%h[SCTD@"h[XSDYY@ ")$'%%$+.532&#"32732#".'>763254#"7m;:%2<"22. 1)  >}!"sW`'#%0$#'6(  f""")DG@D"B jj[S CT D%$###$ +""")wH@E#Bj j[S CS D&&!###$ +""")(F@C,&Bjj[S C S D+)"!###$ +""")kJ@G [[S C S D$$$/$.*(#"###$ +""-D*@'Bjj C D  #+""-w+@(Bjj C D  (#+""-('@$Bjj C D'"#+""-k-@*[ C D !   %#+^#;@8[S C S D#"!"& ++#46;4;>54.+3+3T*'TD"`3 3yR;9' +xVW9'~""2/K@ =, BKPX@[ [ C DKPX@&h[ [ C D@-h  h [[ C DYY@ :8#&"#("("" #+""3DK6@3*BjjSCTD!!!-!,&&&#+""3wK7@4+$BjjSCTD!!!.!.*&&&#+""3(A3@04.BjjSCSD'$&&&#!+~""3/AA0BKPX@'[ [SCSDKPX@.h[ [SCSD@5h  h [[SCSDYY@ ><#&"#%&&&# #+""3kA9@6 [SCSD,,!!,7,620!+!*'&&&# +5\ @ Bja$!+632#"/V ! !&/@+&% BKPX@SCSDK&PX@CSCSD@ CSCSCDYY@ '''/'.$)&+#"'&'&7&54>32672#">=630 (QDT% ,.(QCS( c- ApD- oMB0* Z3se<1+mm?I }""9DL:@7" Bjj CTD%$&#$"+}""9wL;@8# Bjj CTD&&(&#$"+}""9(C7@4,& Bjj CTD'"&#$"!+}""9kC?@< B [ CTD$$$/$.*(#"%&#$" +l""=w66@3#Bh CS D&&)*$"+S 9@6[ [ C D  $#% ++#4>;332654#"#T,kS 6- "# - :$ZP|dx  9O`A/@,@:BS CSD75/-!+632#"&5473254&'.5467>54&#"#".'>54'$XNhg)/OE;>3"#*'!(sNQA %1X;CS* 35'-?$"*&,V)  7""ED'S@P4 *Bh[CSCSD+++7+6$$'$%# !+7""Ew'T@Q5. *Bh[CSCTD+++8+8*$$'$%# !+7""E(P@M>8 *Bh[CSCSD'$$$'$%# #+A""E/+@K:  *BKPX@1   [[ S CSCSDKPX@5   [[ C S CSCSDKPX@< h  [[ C S CSCSD@?h h  [[ S CSCSDYYY@HFDB?="#%$$'$%# #+7""EkW@T *B[S  CSCSD66++6A6@<:+5+4'$$'$%# !+7""E-Q@N *B[[ SCSCSD;9##$$$'$%# #+1=HKPX@#4H- G B@ #4H- G   BYKPX@+  [[ SC SD@5  [[ SC SC SDY@22FD@>2=2<7510$"(#%"&+$7#"'#".5463254#"&5467>32632#"'3327654&##"3275: 'B%7,G-;&?0.0C0Q?A!H)+-. " $ bD HI^R:&* %%W71-<:@%.Z"! #7@ 76+(BK PX@-`fSCSCTDKPX@.hfSCSCTD@+hfXSCSDYY@ ")$!%%%%+6&54>32&#"327+32#".'>763254#"7>*3M2%. !!' $ =01)   lwpx' Dh@;% *BCSCSD&&&1&0/-&#+#".54>32&'&54?&'>327654'&#"3mFa?N%&C+& [ 1 .; J" =ʎ3udOr;))#?  ?  ^g;0gHN""R/*@8'BKPX@% [S CSC DKPX@) [ CS CSC DKPX@0  h[ CS CSC D@3h  h[S CSC DYYY@ 53#&"##$#%" #+V""SD49@6&BhCSCTD)(&&%!+V""Sw4:@7' BhCSCTD**)&&%!+V""S(*6@30*BhCSCSD'#&&%!!+V""S/*=,BKPX@) [S CSCSDKPX@- [ CS CSCSDKPX@4  h[ CS CSCSD@7h  h[S CSCSDYYY@ :8#&"#$&&%! #+V""Sk*;@8S  CSCSD(((3(2.,'&&&&%! +<w %@"[WSD#""$#!+632#"&563!#!632#"&5 >"!sJs >"!$>$'9'V$?# #-=@:("B@ ?SCSD$$$-$,)+%+#"'.547&53267&#"7>=35QSH! (/ J"  H / a+E|%  Q6\'"  MBaKH0VH""YD2=@:!BhCCTD$#$#%"+H""Yw2>@;"BhCCTD%%($#%"+H""Y((:@7+%BhCCTD'"$#%"!+H""Yk(A@>BS  CCTD###.#-)'"!%$#%" +?O""]w(;@8+$ BhCCTD!!!.!.)$$$+!8V =@:   BCSCSCD$"#$ +32#"'#"&54>33254.#" ORM6,*)4- Ws EX40?O""]k>@; BS  CCTD,,!!,7,620!+!*&$$$ +h""%rO2@/ B[Z C D$$##2!+7""ErD@A *B[[SCSD$'$$'$%#"+""%+Oo@% B.@KPX@"^\Z C D@!j\Z C DY@ ##"##2"+7""E+R@O5 *B>@\[CSCSD##%$$'$%# #+=&7@4!BZ C CSD#$) +32327#"547'##"''3')" 2 GY1!##>  ]e  .))Y>- u>^^=7-9P@M,7B[SCSCSD...9.8'%#&)'! +&#"&547>32327#"547#".54632532765&#?: R6E9& 3Y%+=&@4)-  # 7C/J= Y4,EA^GE#.% k ;""'w?C@@&BjjSCSD))$"%%&+""Gw?@<(! BhCSCSD++)&%%#+;""')5C@@%BjjSCTD/." %%&+""G)l@ '  BK2PX@#hCSCSD@ jjSCSDY@ 10'&%%#+^""() E@B!BjjS CT D +*    & + ,D@A,+BCS CSCSD%'$$%"+>3#".546325632#"'>7&5#"327)5DN2E+K?%%F#, #  5!hd&H'H.*MLWB 8^h""(r 7@4[S CS D #!    &+ ,A@>,+B[CSCSD%!$%"# ++#".546325#&546;54>33#"327'DN2E+K?%R.)5E   !hdBIMLWB 8)h"")r:@7[[S CS D$"###$ +D""Ir G@DB[[ SCSD-+'%! %& +"""),:@7[[S CS D" ###$ +D""I, I@FB[S C SCSD+)%#! %& +="&:@7 B[S CQ CSD###$'+$327#"547#46;+3+3  FY/  z h=. .)Y;/&0 %1=D'1N@K Bh[ SCCTD(((1(0+*'&#&)" +327327#"547#.54>327654&#D9u#0:  4YIN/L5%8W7 3*,< Y2.hr~,`AG %."""))H@E"Bj j[S CT D,+###$ +D""I) @ +$BK2PX@- h[C SCTD@*j j[ SCTDY@"""5"4(&! %& +c""++M@-"B6@KPX@+^\YSCSD@*j\YSCSDY@ ###"&%&! #+ <y" "K+3@L " 9BU @KPX@7  \ [ CSCSCSD@5  \ [ CSCQCSDY@++OMJHEC?=+5+4%+-%# +]""+1ED@A"0-BYWSCSD$#"&%&!"+ <y9DP@ 1H- BKPX@5  [ SCSCSC SD@3  [ SCSCQC SDY@::NL:D:C@>9875*($ +54>32##"'#"'#"547&547&546323654&#"3.'3265v!+ !## MU CA^`D6?3 / D\ (> 2&)U 0X= "+@(BS CCTD$'$!+632#"&5327#"54674>3!q / D\ (>* )(-$, 2&)U 0 ""-,@[ C D$##+! @C D!+6#4>3 8/*5  ""-.CBKPX@ CS D@ C CSDY%##+!;L !36@3(BS CC CTD%"$$$$! +632#"&5>32#"&5#4>3#"&54732654>3!G 8/*590+)4* )(-$,$* )(-$, # ,u""/16-@*.+BW C D$$#))! +!]"!"O1)C@@)( 74BhWCSC D$$%%#*""+ " "0w1@.Bjj CT D  '#"+""Pw+@(BjjC D  ("+""01 (@%BW CT D$"#"+""P1"@BWC D$#"+F NBKPX@ CS CT D@[ CT DY$"#!+%+4>33632#"'>7&5 '=[$G#- # &I&H.,!"!P@C D"+. "@[ CT D$"#!+%+4>33&632#"&5 '=z&!& %!'  *%#)#$!- @[C D##!+6#4>3632#"&5 6/)4& G&!' 5*I)#$/#@  B CT D*"+%+&54?4>373/ % % '=R S* 9 A @ BC D'+#&54?54>37 # 6/ )4"  t7""2wU4@1'  Bjj C D**-"(""+!L"!"Rw3>@;"BhCSC D%%($#%"+""21K+@( *'BW C D$("("" +!L"!"R1)2@/%"BWSC D$#$#%" +""2)K4@1& Bjj C D0/+"(""+!L"!"R))j@!BK2PX@hCSC D@hSCS DY@ +*&$#%"+!L "!"R3@0&#B[SC D%#$#%" +h""3rA(@%[SCSD$'&&&# +V""Sr*(@%[SCSD$&&&%! +""30Q%@"70*#@SCSD&&&#+Y""S09%@"3,&@SCSD&&%!+"2KPX@ B@ BYKPX@#[SC S DKPX@-[SCS C S D@9[SCS C S C SDYY@###2#1+)""##"&"# +%+5#".54>326;+3+&>54.#"3 &BDM#(RB=$ z g  c(0 =D&0 %14l^bf27weU`0)8KPX@ B@  BYKPX@$[ SC SD@.[ SC SC  SDY@** *8*720 ) (#""$"& +$7#"'#".532632327654&#>54.#"3: 'B%G"&?;B!I!&K9u 8  bD ""'pn$%W7 )' 763254#"7.54732654&/.54632.#"0 1)  :<3("[!\V 4P`/I-2$#'6(  d&*&(&.#y+D$FS8! 4&{"2:@3$BK PX@,`^SCSCTDK PX@-h^SCSCTDKPX@.hfSCSCTD@+hfXSCSDYYY@ $'$")$&+$32#".'>763254#"7&5473254/&5432&#"C< 0)  f)/4W1{'00J5&:I 2$#'7(  d6!+\28|?KI""7) <@91* BjjSCTD(((;(:+&)%%+2""W)l@ *#BK2PX@#hCSCTD@ jjSCTDY@ !!!4!3)$)$#+ #r*@ "BK PX@*`fS C CTDKPX@+hfS C CTD@(hfXS C DYY@ "")$!" ++32#".'>763254#"7##543!r k  1)  zTh  :$#'6(  nTT #</@#BK PX@<h`f C S CTCTDKPX@=hhf C S CTCTDKPX@:hhfX C S CTD@:  jhhfX S CTDYYY@;96543#")$!$! +6327+32#".'>763254#"73.5#4>;54>33+[1)   = &)4R 5.$ /# r" "8)23@0BjjS C D$#%"##+ ]0@ &BKPX@& CSCSCTDKPX@)hSCSCTD@'h[SCTDYY@ $##)$! +632#"'>7&5>;54>33+327#".5#%F#, # &)4R <[+,=&I&H.,$ /#  !6 <1}h""9rC.@+ B[ CTD$%&#$" +H""Yr(.@+B[CTD$%$#%" +}""9-B8@5 B[[ CTD"##"&#$""+H""Y-':@7B[SCCTD"##"$#%""+}""90R+@( B/("@ CTD&#$"+W""Y07+@(B.'!@CTD$#%"+=}%5@2%B CTCSD$#&$$#+$327#"547#".54>33274>3`% FY#JO )@&% (?C)Y-54V@ 4, ? `=H&5@2 &BCTCSD$#%$&#+$327#"547#"&54>33274>3.) 4Y&UB 90 7/B Y6+KLS  ~ ("";(A@>C=Bj jh CSDB@!%5((" #+ ""[({KPX@ IC %B@ IC %BYKPX@#   hCCT DK.PX@'   hCCCT DK2PX@+   hCCC CT D@.   hhCC CT DYYY@HF?>$6&9"" #+l""=(,2@/,&Bh CS D'#*$" +?O""](7@44. BhCCTD'#$$$!+l""=k,7@4B[ C D$$$/$.*(#"&*$" + e" ">w:<@9# BjjS CT D&&)%#%!+ #" "^w?@<+$ BhCSCT D!!!.!.'%'%'+ e" ">,0/@, B[S CS D$$%#%! + #" "^, 1@. BS CSCS D$"%'%' + e" ">)0<@9" BjjS CS D,+'%#%!+ #" "^) l@ *# BK2PX@#hCSCS D@ jjSCS DY@ !!!4!3%%'%'+K@BSCD%&!+632.#"#".'>5Z\3C'&& H"!! 11 3 ;'8@5BSCSCSD"%#"%!+632&#"3+#"&5473265#46;5aL=' )*)obL=' )**lXJ (H9&XhJ (8'<I""71 3@0 52BWSCSD$(&)%% +2""W13@0.+BWSCSD$&$)$# + r" "812*@'BWS C D$""## + " "X1l@ /,BKPX@#W CSCTD@#jWSCTDY@ $"$### #+;@BCSD%!+#"&54732654>332>7#Y  #,08 Q,!$ <48#8r@OSG$$+@ B@XD##!+3267632#".5467E( !*f>' * %q!4 S" @S D$!+632#"&5S* )(-$,$ @WSD"## +32#"&53254#"$l6/k51L -:j-; ! !=3 >BK PX@^TD@jTDY&'+4852327#"54>3 & 4Y#41 Y$?'"$ BKPX@WS DKPX@W CS DKPX@hW CS D@"hhWS DYYY"#&"#!+632327632#"&'&#"#".' G    &4  *  '!     (+.'>76.'>7_( P  A ( O  ? (\"a)]"aK@ BOSG$!+632#"'>7&5K%F#, #K&I&H.+-)"-K@S C D##"+ @S CQ D +32!#3>&wyHAR|O;-d"-W@S C D#3#+&"@SCS D$%$$+>54&#"#&546;.546323+ - $(Yf>G(9 {hat [V"&fAqk!!<P1@.BCTCD$#$# +#"'#"'46323274632V >!!( # .' b%%@" BSC D####++#"'##"'#&543! 'D%# "V :""")DG@D"B jj[S CT D%$###$ +""")kJ@G [[S C S D$$$/$.*(#"###$ + )q@ BKPX@$hS CSCD@(hS CSC CDY@ "$%%%"!++632#"&547326=4&#"##543!r k&4C(0'$   6.zT\a =F^b( +:)} TTT-)"-"Kw=1@.BjjS C D(##"+F"2@/B[SCSD#%&%!+6327#".54>32&#"3+%$$0?2>N+0N675!( n[%"(;9#&VX%1I"7%@" BSCSD&)%%+ @ C D#+>3# (> 8/X ""-k-@*[ C D !   %#+ " .@ B CSD%#+8(KPXBBYKPX@ [S CS DK&PX@*[S CS CS D@([S CS CSDYY@(&   +2+##"&5472>7>;32>54.+YK^M: !9/#&%  &/ W_u~T}"#l :7'$-/'8@5'B [ CT D&$###$ ++##4>334>3332>54.+K^Mb 7/ 7/b 7/W_u~A   97&$  2@/ BS CSC D#"$#% +32#4&#"##543!+NA 9/  6.uO k8I Z) TTT Y-v"-"RwOG@D2+  Bjj[ C D(((5(5*!##%+! !+-|"-"PDZ3@0) Bjj C D , +#)#"+r""[-;@82, B4@j[ CT D$##((%#!+-cf@W C D##!+>3+#.'#4>33 7. I  m 7.[X }9=' @"%(@% BZ C D##2+-`.@+B[S CS D&!#$!"++32+463!32>54.+C YK^M 3 W_u~97&$-k!;@8B[S CS D! &(0+;2+654&+3654.+3-b7%s\_ GT k4+1#F>,,-)@S C D##!+6;++-  y ]&. c!0@-BKS CQ D5$+#&'#".=32>>;33#   #2x9c:'=9D <"").@+[S CS D###$+.B;@8-) '! B [ C D?=#$+$!#$, +32#"/.+##"#"&?67&/4632;4>3326?#&(D"& ! 4- ! '!D('"!! 4-! D' L4 ;4L 'D #% %#\)6@3B[SCSD4%)'"+54#".54632#"&54732654&+"=31,8IKLLU^FO,I' '#$a36?>3#547 #53- $Q !0 3)&T  M!p8 W `fo-|"-"PD6@30* B2@j[ C D$#(#)#"!+-v&0@- B[ C D!##%+ +32#"/.+#4>3326?$#( *C $*  70 70  B' 68  $"{DKPX@S CS D@S C CSDY&#!+$###"&5472>7>;{ 6/: !9/#&%  &/ T"#n X-.'@$* Bh C D#+*#!+6;#7>7'+'&'#46;>?a ] 80 %0 ./#  6, TP  EX GT '* SH  &88$-m @Y C D###!+$###4>334>3m 7/b 7/ 7/b 7/ A   X@SCSD&&&"+>32#".532>54.#")SCCL#(QDEL#  B>D;## 7. 6. 7.Y  X TS"4/@,[S C D#&+;"'+@(BSCSD%%&+ r" 8@S C D"##+r "@ B CT D((%"+6#"&547327&'&546;6?>;.+&0#[ O(Ou\<%$03aa# YM$@$# BCD+#5.546754>3654&'_dd (>k]af (>*&#.(T}~(Kx'V#jOTbumR"<@B C D($'#+-c"@L CR D##+#.'!4>334>33   7.[ 7.29=' @ D(@%B\ C D$"%"!+$##"&=4>33274>3D 6.+>5 5.$ 5.  Se a 5 X-@ CT D$##!+>334>334>3#!- 7/L 7/K 7/ )@@ @ x-cC&@#L CR D###+#.'!4>334>334>33C  K 7/L 7/K 7/29=' @ @ 6@3B[S CS D "$++#54;332>54.+YK^MeW_u~TK97&$-"-"d>r8@5B[ CT D#! +-^ 2@/B[ CT D   +2+4>332>54.+YK^M 7/W_u~ 97&$:!2@/B[SCSD!%&%"+.#"&54632#"&547327#".53%#576M/,P>-D-&Ip V&#9;&!,1%-8,^KPX@YSCSD@'Y CSC CSDY@ &###&"+>32#".'##4>3332>54.#"*MD3  ܤ^-2i^ab/3seQ';@8'&B?[S C D%#!%##+".5#"#"'7>7.54>;#"3275J/7 ! #%! -0-VA^i.5 X E !+_?PZ$``|7"E:@7 *B[SCSD$$'$%# + `+/@,B@SCSD+*$"$%+>32#".=4>?32>54.#&3+A>QR?C52"o   9)C9<.j0wrTiyEE: )KHHFOOAB!L(K@H(Bh[S CT D'&%# & +2+4;32654&#"#3254&#"#76!6VY|Z / s;8*9E["!uT*@SC D##!+6;+#* ^ '> .# ~ c!*@'KSCQ D&+#.'#".=3>7>;33#    )2_49=''=9# t'0D"I;@8B[SCSD! %&+C0@-+ B [C DA?##,%!#%, +32#"/.+#5#"#"&?67&/&54632;54>332?%$>  %   4-   & >%%# % 4-&  0o{ %% %% {o0 . 0,'6@3B[SCSD4%'&#+54&#"&54>32#"&54732654&+"=3!&4*~-$5B3.!LI$!"pF3;/"'#%!?*`#@ BC D#+#!+>3#54767#4>3>? - '7 ' K- 2(   I  @D j  Q&%S*`"*"p-6@35/ B7@[CC D$#+#+#"!+*U%0@- B[C D!##%+ +32#"/.+#4>332? " ";  '  5. 5. # .mz '$  -hDK&PX@SCS D@SC CS DY&#!+$###"5472>7>;h81/8-<$"  &.QAC  *,(@%%BhC D)#-'"+%#547+'&'&'#46;&?>; 1* "-" 0& h7 1nmJ+Zbf4: -K& ) =*U @YC D###!+$#5##4>3354>3U 71I 80 71I 7/ ˷  ʶ  V"S@SCSD&&%!+*Q@SC D3#!+$###4>;Q 6/I 6/ )<    !;V"!T7@4  BSCSCD&$#%!+"G%@" BSCSD&%%#+3@SC D##!+6##4>3!+ 7/_  G .# .$ ~ <O @BCTD'!+#"547267&54>3>?>3;1=%% o5)   )>ptPA$3 67 :!(,@)('!  BACCD(+#"'5.546754>3654.'TVa @K%S]%/*  (w}{ 0nbt bNP:?'DLOSK Ot"\ @! BC D(($+*c"@LCR D##+#.'#4>334>33   6/I 6/29=' tx t#J(@%B\C D$#&"!+$#5#".=4>332754>3J 7/ !,3 6/   6/ =7 !  *@CT D###1+$#!4>334>334>35/ 7/M 7.L 7. tx tx  *cB&@#LCR D###+#.'!4>334>334>33B  I 7/M 7.L 7.29=' tx tx t;@8[SC S D#$ +##4>;33254.#"#?Lb]kY ! /  <333254.#"# Ljf[ (7"! /  <;' /)7I,!D81; 4m W^5 !&xtap/ 5B/$ *'eKPX@ YSCSD@(YCSC CSDY@'&&##% +32#".'##4>33654.#"3ԓ8C!QS5>#1 4. 4-1-nd| ]Y  EhIGFcMJF(~K&PX@('B?@('BYK&PX@[SC D@[SC C DY@&$!&##+".=#"#"'7>7.546;#"3275?-6  0 !0a`\g 1   ')\ z 'J8LD[!I{D""ID*U@R+Bh\ C SCSD"""."-('! %& +D""Ik Y@VB[S  C SC SD--""-8-731","+'%! %&+HP6@$6BK&PX@,h [CC CTD@)h [XCC DY@ 53$$&%&! +632#"&54732>=4&#"##&5&6;54>33+52*!LC,+ !"!  6/8)5{ \8Jl~;* NO$ ;K`*"*"kw4@1BhCSC D(##"+!2@/BYSCSD#$&%!+6327#".54>32&#"32#(" ="@G!2G.^ !W m4$-upmn : 25 $/2"W%@"BSCSD$)$#+!"!M@S CC D$$"+""k/@,S CC D !   %"+;"N*@'BS CCSD%$$"+ 'K&PX&BK.PX&B&BYYK&PX@" [SC S DK.PX@) h [SCS D@* [SC S CS DYY@''%#  +2+##"5472>7>;3254.#"SLjfa/7-=$"  &/ /  <3354>333254.#"#Lkf]X 7/61X )9"! /  <33+57% 8.  6/8)5{ \334>3Q; ,  ` 6/I 6/ } tx #-)1>K PX@^S C D@jS C DY##&+72++46;# y ] @ U&. *u>K PX@^SC D@jSC DY##'+72+#46;  ^ '>h8=V.# ~  -c*3@0B[W C D!##$ +323#&/.+#4>3326?$#((F @ V  70 70  C)k`;68  $#*c~*5@2&Bh[ CTD$!###+#./4.+#4>332>76323~  8  70 70  #" D ! ?5mZ   JV 334>33  @b 7/ 7/b 7/29='A   *c)@&YWC D###+#.'#5##4>3354>33  BI 80 71I 7/29='˷  ʶ tl'*@'%B\ C D*$$##+$+#5#&546;5&>3>?>33F* 7/O*} @7 70zI  #z$#{$n jBE*2@/(Bh\CD&&$##++#5#&546;5&54>33>?>337.5/N)i;-   )?fM B V  66q  "";DC@@9B jjh CSD000<0;%5((" "+ ""[DKPX@ ? %B@ ? %BYKPX@# h  CCT DK.PX@' h  CCCT DK2PX@+ h  CCC CT D@. hh  CC CT DYYY@666B6A6&9"" #+"";wD@A:3Bj jh CSD000=0='%5((" "+ ""[wKPX@ @9 %B@ @9 %BYKPX@#   hCCT DK.PX@'   hCCCT DK2PX@+   hCCC CT D@.   hhCC CT DYYY@666C6C*6&9"" #+"";kH@EBh  [ CSD;;00;F;EA?0:09$%5((" "+ ""[k{KPX%B%BYKPX@#  S  CCT DK.PX@'  S  CCCT DK2PX@+  S  CCC CT D@.h  S  CC CT DYYY@AA66ALAKGE6@6?'6&9""#+l""=D65@2"Bh CS D%$*$"+?O""]D(:@7* BhCCTD!!!-!,$$$+|J@OSG"!+63!#!J#'9'J@OSG"!+63!#!d#'9':@ BOSG$!+#"54>32$G#- "`&I&H.*; @ BOSG%!+632#"'>7&5%"$#, #&&#&H.,q@ BOSG%!+>32#"'>7&5%"$#, #K&&#&H.,:G %@" BOSG$(%!+#"&54>32#"54>32G%"$#, #$G#- "`&&#&H.*&I&H.*;G  %@" BOSG$(%!+632#"'>7&5>32#"'>7&5%"$#, #$G#- "&&#&H.,&I&H.,Gq %@" BOSG$(%!+>32#"'>7&5>32#"'>7&5%"$#, #$G#- "K&&#&H.,&I&H., &1m@ +BK#PX@"hCSCSD@%hhSCSDY#,+###+54632#"/32'&54?#"&547#"'632&% qcr f$) %( !u$(!    &1>KW@ +80QLEBK#PX@9hf  h [CSC S D@<hhf  h [SC S DY@ US-+##,+### +54632#"/32'&54?#"&547>32#"'5#"&547$32'&54?#"'7632&% qcr fi#rqdrfP&% !%( !u$(!   &( !t#(!  y @OSG$!+632#"&50)0(/)1(D5.-&3,-""#t@SD#$#$#" + %2?LYC@@ B [   [SC SDWUQOJH&%$%#$&%, +.5 32#".53254.#"32#".5$32#".53254.#"3254.#";!8/:FG19j  /:FG19'/:FG19 ! ' !   f   NFb[PM,,g+)): NFb[PM NFb[PM,,g+)):,,g+)):@ BC D+>72#.5?D /23/ D@ohVJ GS gp(+6.54>7.54>7?D %/32/  D?pgSG JV ho/ @ BCD$ +#"&'632-)$ %jhQ@  BKPX@[SD@M[SDY)"#++#"'5#&547>7>323&37h:I"0/1 O( B%7$rT& _1E@B B[ [  [SD1/-,*(&!""%! +6327#".'#46;57#46;632.#"3+3+!3A24B)V)S5$8."@v[i<" (!TN5'.5'1 Z5'' 5'!"!P)+""2} 1*#)+}'84)(+;#7>5+/#46;46?$6;+##5y*  %% 8Fl&J5=@T G!d6p/h&&"5 )+Fm-(  (+32673#".54>32!$'.#"3!2='k32.'>32654'&#"3G`?N%&B+'<4 /" =SΎ3udOr;=[0{^g@+gH  (+32#!"''3')" ##>  55Z u>>(++#"'##"'#&543! 'D%# "V :"B> (+!+3+# icf $|6wJ(+63!#!J#'9'/")+y#)+&;(+6323+#"'=(*H 2TI "_!6 g0". '#(+#"'#"&543263654&#"37&'&#"3Hm V0A>@G.>;D  " MIGELF$&J)  ;(+632&#"#"&5473265aL=' )*)bL=' )**J (hJ (Om6*(+32327632#"&'&#"#"'6323276#"'&#"#"&5LI!"  J') C$$" L+')$)  Bz" 5).w!(+%+#"'7#46;7#46;76323+w#*BM" !,FQ#9&O$A8'h9'[$S9'h#r (+$#"/&547%63!#!q  #8ȵ4i"*|(RY&8'#r (+632.'4?'63!#!$  $64i!+})SX&8'(+ 7'MMMd#Q @ TB*(+#".54>367>54&#"&#32654#"#"&#"372#'"326323254#"=54#"#"&#";2/&#"#"&#"&#"#"&#"37'3254#"#"&#"372#"&#"326323254#"#"=763232732632#"&#"326323254#"#"=32=4;YYllXXl"#,+##+*t     M   F    ! 9  9   D YmlXXllY!(%"(!,,'   p    p  b  8^"$[  q  a{,v   *2@/ BSCSC D"##%#" +>;54632.#"3++##4>3  !jW ?-*5  [<n 8/*5" 9iL?" /=-$ |q  #4@1"BSCSC D####"!+$+&#"3++#4>;54632 [ ?; & [< !cC*OFO-$ |0" 9hM\8Q$ (+#"&547326=#".54632#"32=Q\Q;54632&#"3++# !@8." I 4 \<" mH; c-$ |{;$(+$#"&54732654'&'7##".'>54632.#"!),X@63(!5/"*V% Y] 6 '*9T:>h= %+<5E3(3MF  2? !& {>!(+>3!#"&54732654'&'7#   :7),X@63(!5/ ,W-  )T:>h= %+<5E *41-(+32632&#"3++#+#4>;567&#";5F3-)F6- ))*H 3 [P [< ! 4/!  (E-$ ||0" @)>O9C)2< :50,(+32632&#"3++#+#4>;567&#"35>3#A7+-R 0C-)4  [P \< ! 4P*5 8/?"/=-$ ||0" @$#>O9Q <.751*(+#&#"3++#+#4>;54326327&#"35< 6/?3  [P \< !3.(>TB 4P[ |CI-$ ||0" @)a#>O9 {0&(+$#"&54732654'&'7+##4>;54>33!)Z^+,(/ ,WP< (=< %*4 :T:c'):7E .$  ) ?" "X^?/ )+sX#"(+#"&'632#".54732>54.#"!sl Lhzn&2 7)967-,2-'}Mt6$1L&56 ;F(+547>323#!&546;5""^ KG[0% P(+654767>54#"&546323#!9$ /%3h:G:5/ ##;%*$&#*44/Q4 8C*%(+$#"'&5473254'&#.5432654#"&547632$dMG *.F,, ./) (mx0/KJ %( &    #Y80h(+$+#"'5#&547>7>323&37h:J"0/0 O( B%6%rS'!F(+547>323#!&546;5""^ KG[Q% !P(+54767>54#"&546323#!9$ /%3h:G:5/ #2#;%*$&#*44/Q4 8C*%(+#"'&5473254'&#.5432654#"&547632$dMG *.F,, ./) (mx0/KJ %( &    #Y80h(++#"'5#&547>7>323&37h:J"0/0 O( B%6%rS'J#)+8$(+3267#5.5467.54675463.#"27=+)"H=+/6KF8,"KA/6$78()/= ?4% .7&!BiMI9I0*?U Bk 5!%6hf>GD?8(+#3267#"&54632754>3>73267#".=&#"765t7  I )G+QJO]9L{/'9 %$3:',:t//!##qC@1* ./{,,""?:040I /! (+3267632#"&'47U   ,>=6JA%!&!428)*E`D1K[_< ee8/M $";" o !$!&& (gEi-(r- +]mX| px _Xg _%r 1Sn#$gY ~ j!!i!!!j!jk!l!? gJ|U-  !X  I[W:F 4" WDl]1o/A`F8GE----i5p]SSSSSS$YYYY jjjjjjggggUm!USSSE$E$ii-Y-Y-Y-Yr~ r~ !o!i!+ +>!E!>j!j!j!j!jj%*m!mmX?X?X?|  | N ggggpUpx - x - x -  X?|  S$K3--o-- 3-PX- B9- --w-v--3--Mk------]E| w;-r?-R- -r-XV-~St a!*Y/@**i***j{*k!$;T |*t#:*Q**d*' *pYYs*%?!"!*ni**T {*3-*-}**pJpUdd_1} !)F+s"&L ##   sM  R] I `k]|`k]|Xl1 8|NJvbT4,XL v p  B ~ > v  *  B >h8~Nz> \<Rp2~66zPdR B v \ F !.!d!!"#0#$d$$$%`%%&&&''R''''( (r()),)V))***++.+^++,L,,,--..//00:0v00011x22,2X23 3:3|344>4j4455F5p556"6z67$7T7788f889 9T99: :z:;;X;;<<<=$=n===>D>j>>>??0???@@<@r@@@AABAAAABB>BCCCD4D\DDEE6F FGGFGHHIIIJJ,JRJxJKKPKLL0L\LLLM M8M~MN N6N`NNNO(OfOOOOPBPPQ$QX~XXYJYYZZJZnZZZ[:[V[[\\D\\\]D]^^:^^__h_` `\``a ahaabb>bfbbbcFcbccddRddee\efFffgJgtgggh"hDhiliij&jRjjkkhkllHllm"mmnjno&oRo~ooopp@ppqqrlrrsRssst.tttuu"ujuuuvv0v@vPvvvvwDwxwwwyyhyyz"zzzz{X{{||@|j||}}:}n}}}}}~H~~~V"/n >v ;HY} 6 K ~   "e  @ ,  R *-  o l ) \ * 4Copyright (c) 2004-2010, Jan Gerner (post@yanone.de). Copyright (c) Huerta Tipogrfica (info@huertatipografica.com.ar)Copyright (c) 2004-2010, Jan Gerner (post@yanone.de). Copyright (c) Huerta Tipogrfica (info@huertatipografica.com.ar)Yanone KaffeesatzYanone KaffeesatzBoldBold1.100;UKWN;YanoneKaffeesatz-Bold1.100;UKWN;YanoneKaffeesatz-BoldYanone Kaffeesatz BoldYanone Kaffeesatz BoldVersion 1.100;PS 001.100;hotconv 1.0.70;makeotf.lib2.5.58329 DEVELOPMENTVersion 1.100;PS 001.100;hotconv 1.0.70;makeotf.lib2.5.58329 DEVELOPMENTYanoneKaffeesatz-BoldYanoneKaffeesatz-BoldYanoneYanoneYanone (Cyrillic: Daniel Pouzeot & Huerta Tipografica)Yanone (Cyrillic: Daniel Pouzeot & Huerta Tipografica)http://yanone.dehttp://yanone.dehttp://yanone.dehttp://yanone.deSIL Open Font LicenseSIL Open Font Licensehttp://scripts.sil.org/OFLhttp://scripts.sil.org/OFL  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~CR softhyphenAmacronamacronAbreveabreveAogonekaogonekDcarondcaronDcroatEmacronemacron Edotaccent edotaccentEogonekeogonekEcaronecaron Gcommaaccent gcommaaccentImacronimacronIogonekiogonekIJij Kcommaaccent kcommaaccentLacutelacute Lcommaaccent lcommaaccentLcaronlcaronLdotldotNacutenacute Ncommaaccent ncommaaccentNcaronncaron napostropheOmacronomacron Ohungarumlaut ohungarumlautRacuteracute Rcommaaccent rcommaaccentRcaronrcaronSacutesacuteTcedillatcedillaTcarontcaronUmacronumacronUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentlongs Scommaaccent scommaaccentuni021Auni021BdotlessjfirsttonechinesecommaaccentcombGammaPiuni0400uni0401uni0402uni0403uni0404uni0405uni0406uni0407uni0408uni0409uni040Auni040Buni040Cuni040Duni040Euni040Funi0410uni0411uni0412uni0413uni0414uni0415uni0416uni0417uni0418uni0419uni041Auni041Buni041Cuni041Duni041Euni041Funi0420uni0421uni0422uni0423uni0424uni0425uni0426uni0427uni0428uni0429uni042Auni042Buni042Cuni042Duni042Euni042Funi0430uni0431uni0432uni0433uni0434uni0435uni0436uni0437uni0438uni0439uni043Auni043Buni043Cuni043Duni043Euni043Funi0440uni0441uni0442uni0443uni0444uni0445uni0446uni0447uni0448uni0449uni044Auni044Buni044Cuni044Duni044Euni044Funi0450uni0451uni0452uni0453uni0454uni0455uni0456uni0457uni0458uni0459uni045Auni045Buni045Cuni045Duni045Euni045Funi0490uni0491uni049Auni049Buni04A2uni04A3uni04B0uni04B1WgravewgraveWacutewacute Wdieresis wdieresisYgraveygrave foursuperiorEurouni2113uni2116Ohm estimated increment divisionslashbulletoperatorg.ss01f.ss02germandbls.ss05z.ss05f_ff_f_if_f_lt_z.ss05t_zfive.001one.dnomtwo.dnom three.dnom four.dnomone.numrtwo.numr three.numr four.numrsofthyphen.001 uni00A0.001 uni00B5.001ampersand.ss03ampersand.ss04 breve.cyr .ttfautohintz\z\;8;8, `f-, d P&ZE[X!#!X PPX!@Y 8PX!8YY Ead(PX! E 0PX!0Y PX f a PX` PX! ` 6PX!6``YYY+YY#PXeYY-, E %ad CPX#B#B!!Y`-,#!#! dbB #B *! C +0%QX`PaRYX#Y! @SX+!@Y#PXeY-,C+C`B-,#B# #Bab`*-, E EcEb`D`-, E +#%` E#a d PX!0PX @YY#PXeY%#aDD`-,EaD- ,` CJPX #BY CJRX #BY- , b c#a C` ` #B#- ,KTXDY$ e#x- ,KQXKSXDY!Y$e#x- , CUX CaB +YC%B %B %B# %PXC`%B #a *!#a #a *!C`%B%a *!Y CG CG`b EcEb`#DC>C`B-,ETX #B `a  BB` +m+"Y-,+-,+-,+-,+-,+-,+-,+-,+-,+-, +-,+ETX #B `a  BB` +m+"Y-,+-,+-,+-,+-,+-,+- ,+-!,+-",+-#, +-$, <`-%, ` ` C#`C%a`$*!-&,%+%*-', G EcEb`#a8# UX G EcEb`#a8!Y-(,ETX'*0"Y-),+ETX'*0"Y-*, 5`-+,EcEb+EcEb+D>#8**-,, < G EcEb`Ca8--,.<-., < G EcEb`CaCc8-/,% . G#B%IG#G#a Xb!Y#B.*-0,%%G#G#aE+e.# <8-1,%% .G#G#a #BE+ `PX @QX  &YBB# C #G#G#a#F`Cb` + a C`d#CadPXCaC`Y%ba# &#Fa8#CF%CG#G#a` Cb`# +#C`+%a%b&a %`d#%`dPX!#!Y# &#Fa8Y-2, & .G#G#a#<8-3, #B F#G+#a8-4,%%G#G#aTX. <#!%%G#G#a %%G#G#a%%I%aEc# Xb!YcEb`#.# <8#!Y-5, C .G#G#a ` `fb# <8-6,# .F%FRX ,1+!# <#B#8&+C.&+-?, G#B.,*-@, G#B.,*-A,-*-B,/*-C,E# . F#a8&+-D,#BC+-E,<+-F,<+-G,<+-H,<+-I,=+-J,=+-K,=+-L,=+-M,9+-N,9+-O,9+-P,9+-Q,;+-R,;+-S,;+-T,;+-U,>+-V,>+-W,>+-X,>+-Y,:+-Z,:+-[,:+-\,:+-],2+.&+-^,2+6+-_,2+7+-`,2+8+-a,3+.&+-b,3+6+-c,3+7+-d,3+8+-e,4+.&+-f,4+6+-g,4+7+-h,4+8+-i,5+.&+-j,5+6+-k,5+7+-l,5+8+-m,+e$Px0-KRXYc #D#pE KQKSZX4(Y`f UX%aEc#b#D * **Y( ERD *D$QX@XD&QXXDYYYYDPK!%|TTLegacy/fonts/arial.ttfnu[pDSIGqlXGDEFQDQ`GSUB[JSTFm*iLTSHsE?Vt,OS/2 2kVPCLT{>C(6VDMXPj[cmapgM.@cvt pv~0fpgmyYx4ngasp Pglyf~G&hdmx.oQt|(head |6hheam$hmtxʢs@kern7a96`loca xAmaxp  name (`+post;U\2prepRm4 Q_<'*!g: >NC3:((?c/V 33f zMono@ Q3>@FN ^ t~&h   b f< \V16/=l q}b E a> 1 3 Z.]       ^  G Q i w &; a  b f   u \')  ' '  ' ''' '' '(( ( (+$(7*(E-(S  (a (m  (y  (Typeface The Monotype Corporation plc. Data The Monotype Corporation plc/Type Solutions Inc. 1990-1992. All Rights ReservedArialRegularMonotype:Arial Regular:Version 2.98 (Microsoft)ArialVersion 2.98ArialMTArial Trademark of The Monotype Corporation plc registered in the US Pat & TM Off. and elsewhere.Monotype TypographyMonotype Type Drawing Office - Robin Nicholas, Patricia Saunders 1982Contemporary sans serif design, Arial contains more humanist characteristics than many of its predecessors and as such is more in tune with the mood of the last decades of the twentieth century. The overall treatment of curves is softer and fuller than in most industrial style sans serif faces. Terminal strokes are cut on the diagonal which helps to give the face a less mechanical appearance. Arial is an extremely versatile family of typefaces which can be used with equal success for text setting in reports, presentations, magazines etc, and for display use in newspapers, advertising and promotions.http://www.monotype.com/html/mtname/ms_arial.htmlhttp://www.monotype.com/html/mtname/ms_welcome.htmlNOTIFICATION OF LICENSE AGREEMENT This typeface is the property of Monotype Typography and its use by you is covered under the terms of a license agreement. You have obtained this typeface software either directly from Monotype or together with software distributed by one of Monotype's licensees. This software is a valuable asset of Monotype. Unless you have entered into a specific license agreement granting you additional rights, your use of this software is limited to your workstation for your own publishing use. You may not copy or distribute this software. If you have any question concerning your rights you should review the license agreement you received with the software or contact Monotype for a copy of the license agreement. Monotype can be contacted at: USA - (847) 718-0400 UK - 01144 01737 765959 http://www.monotype.comhttp://www.monotype.com/html/type/license.htmlTypeface The Monotype Corporation plc. Data The Monotype Corporation plc/Type Solutions Inc. 1990-1992. All Rights ReservedArialRegularMonotype:Arial Regular:Version 2.98 (Microsoft)ArialVersion 2.98ArialMTArial Trademark of The Monotype Corporation plc registered in the US Pat & TM Off. and elsewhere.Monotype TypographyMonotype Type Drawing Office - Robin Nicholas, Patricia Saunders 1982Contemporary sans serif design, Arial contains more humanist characteristics than many of its predecessors and as such is more in tune with the mood of the last decades of the twentieth century. The overall treatment of curves is softer and fuller than in most industrial style sans serif faces. Terminal strokes are cut on the diagonal which helps to give the face a less mechanical appearance. Arial is an extremely versatile family of typefaces which can be used with equal success for text setting in reports, presentations, magazines etc, and for display use in newspapers, advertising and promotions.http://www.monotype.com/html/mtname/ms_arial.htmlhttp://www.monotype.com/html/mtname/ms_welcome.htmlNOTIFICATION OF LICENSE AGREEMENT This typeface is the property of Monotype Typography and its use by you is covered under the terms of a license agreement. You have obtained this typeface software either directly from Monotype or together with software distributed by one of Monotype's licensees. This software is a valuable asset of Monotype. Unless you have entered into a specific license agreement granting you additional rights, your use of this software is limited to your workstation for your own publishing use. You may not copy or distribute this software. If you have any question concerning your rights you should review the license agreement you received with the software or contact Monotype for a copy of the license agreement. Monotype can be contacted at: USA - (847) 718-0400 UK - 01144 01737 765959 http://www.monotype.comhttp://www.monotype.com/html/type/license.htmlNormaloby ejnnormalStandardTypeface The Monotype Corporation plc. Data The Monotype Corporation plc/Type Solutions Inc. 1990-1992. All Rights ReservedArialRegularMonotype:Arial Regular:Version 2.98 (Microsoft)ArialVersion 2.98ArialMTArial Trademark of The Monotype Corporation plc registered in the US Pat & TM Off. and elsewhere.Monotype TypographyMonotype Type Drawing Office - Robin Nicholas, Patricia Saunders 1982Contemporary sans serif design, Arial contains more humanist characteristics than many of its predecessors and as such is more in tune with the mood of the last decades of the twentieth century. The overall treatment of curves is softer and fuller than in most industrial style sans serif faces. Terminal strokes are cut on the diagonal which helps to give the face a less mechanical appearance. Arial is an extremely versatile family of typefaces which can be used with equal success for text setting in reports, presentations, magazines etc, and for display use in newspapers, advertising and promotions.http://www.monotype.com/html/mtname/ms_arial.htmlhttp://www.monotype.com/html/mtname/ms_welcome.htmlNOTIFICATION OF LICENSE AGREEMENT This typeface is the property of Monotype Typography and its use by you is covered under the terms of a license agreement. You have obtained this typeface software either directly from Monotype or together with software distributed by one of Monotype's licensees. This software is a valuable asset of Monotype. Unless you have entered into a specific license agreement granting you additional rights, your use of this software is limited to your workstation for your own publishing use. You may not copy or distribute this software. If you have any question concerning your rights you should review the license agreement you received with the software or contact Monotype for a copy of the license agreement. Monotype can be contacted at: USA - (847) 718-0400 UK - 01144 01737 765959 http://www.monotype.comhttp://www.monotype.com/html/type/license.htmlNormalNormaaliNormalNormlNormaleStandaardNormalNormalnyNormal1KG=K9NormlneNormalNormalNavadnothngArruntaNormalNormalNormalNormal R X 688~Y #~ O\_ :Rkmq~    " & . 0 3 : < > D o  !!!!"!&!.!T!^!!"""""""")"+"H"a"e###!%%% %%%%%$%,%4%<%l%%%%%%%%%%%%%%%&<&@&B&`&c&f&k:1 6<>ADOY}b? Y #~Q^ !@`mq~   & * 0 2 9 < > D j  !!!!"!&!.!S![!!"""""""")"+"H"`"d### %%% %%%%%$%,%4%<%P%%%%%%%%%%%%%%%&:&@&B&`&c&e&j: *8>@CFVz^>/wkri+*)(|zvlhL>i3][w}ujy,ߨߖޖޢދަq_0@3$FE<9630)"ۿ۾۷ۥۯEBA$"!>c6dNNR`b^ffPPRN&($ L^bcdefghjikmlnoqprsutvwxzy{}|~      !"#$%&'()*+,  -   ./0 !"12#3$%&'()*+   4NORPQUVWXST~?Avw|qrsYZ[\]uwvyx}56  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 688~Y #~ O\_ :Rkmq~    " & . 0 3 : < > D o  !!!!"!&!.!T!^!!"""""""")"+"H"a"e###!%%% %%%%%$%,%4%<%l%%%%%%%%%%%%%%%&<&@&B&`&c&f&k:1 6<>ADOY}b? Y #~Q^ !@`mq~   & * 0 2 9 < > D j  !!!!"!&!.!S![!!"""""""")"+"H"`"d### %%% %%%%%$%,%4%<%P%%%%%%%%%%%%%%%&:&@&B&`&c&e&j: *8>@CFVz^>/wkri+*)(|zvlhL>i3][w}ujy,ߨߖޖޢދަq_0@3$FE<9630)"ۿ۾۷ۥۯEBA$"!>c6dNNR`b^ffPPRN&($ L^bcdefghjikmlnoqprsutvwxzy{}|~      !"#$%&'()*+,  -   ./0 !"12#3$%&'()*+   4NORPQUVWXST~?Avw|qrsYZ[\]uwvyx}56llllb z @ . ( T0Z4N$d 4 !*"$%'^()*+Z,-./12|57P89;~=@ABBfCFI$JL LtLMBMMNzQLS*TVXPY[]8^,_DabefhjTklpqsZuxy|~^FD2~0F|` `*j V^F\jdH*6fD&nt2PL0b¸f Ĭ~`Dz$~bBt4Ъ(dNҚ ^ӎTԒՂh֤$X؂z,\ܠޒ:tp,fL| <pDp&VpNJ v"xF>|D   p t:<|v\>^&Nv,XDnJz$V> $ @ \ x  "$'^'z''''((`())*n+D+,L,-R--.T./n0,0X002d3X33344N4445"5R555666f667767f7799:(;x=.=^===>>H?v@@BDB|BD>DlDDDFNGHH^HHHIIDItJdKKL6LvLLMNPPQQHQRrRSTT6TfTTUU6UfUUVV>VtVWXY[z]_aabzbcefBghj"l<nhoZojozpppppprrr rrststtttv$xxDxzxxyydy{|^}Vf&Z&,dTd.V*:4D4Bt~ 0Xr.d:J0VFVƆƖƦfv\lʢ˰\T ^@ּؠ$\lf.N :vV0z0r@t:x0Px(p`|pv\>2H6lT4(X    4 l  @ : j<|HF@x \*hH !&!p"z"#$B$%&'(()*+p,X--/00<012`3f4P4z4445"6667 7J7t7778&8P8z8::.;P;`;;;<=?@A BBCEFH0IKMNO0PtQQQR RJRtRRRSSFSpSSSTTBV~WY>[&\n\\\]"]r]^^t^_&_|__`:```abTeeeffBflfffgg>ghggghh:hdhhhi i6i`iiijj2jjkmnop<qzrtbtruwxz{{|r}~~~~(Xh6F$vjz0pXhpFV(82BTdzJ|VfT.&6HXfvbr>N^L´n<LǬ|hծhג׼0ZjzؤBl|ٌٜ٬ټ@jڔھ<fېۺ8b܌ܶ 4^݈ݲ0Zބޮ,V߀ߪ(R|$Nx JtLvHrDn@j<pj.t(F.H~6t.>Lh 2DVhzV 2DTfxnt  F p   @     Z  " z 6ZjX :j*Hj <vJz2BRV2b :d*f6p  @   !,!d!!!"&"V""##D##$0$d$%^&,'L(():+&-".013r4Z56789;X<>\?@AC$D`EG&(% >u&5#'eS79]9q7$5S+7Ƥc  ) R M_c  S>+. . -%&%&.. ' '9%.7.7$..+.7.7cc0 -&&22222+11%&. . ' ' 'SS.7.7>>>>9]9.7$$.+.7.7.7.79%& ) %% .>u..M'> &)))$1$$$)(*)$)* % >>17 1%$%  u..11M+%11.&1$&'( 77 77$75 11,1$*1%'7&1+9$$7 71    ,    , , ,, # #+ ,,,,,,,,,))))++++22222222##22,,,,#### +9%&%&%&%&%&%&%&%&%&%&%&%& ' ' ' ' ' ' ' '>>9$$$$$$$77ĖĖ%&>9$77777%&.    !" # $!%"&"'#($)&*&+',(-(.*/+0-1-2.3/405061738494:5;5<6=7>8?9@:A;B<C<D=E>F?G@HAIBJBKCLDMFNFOGPHQIRISJTKUMVMWNXOYPZP[Q\S]T^T_U`VaWbWcYdZe[f\g\h]i^j`k`lambncocpdqergsgthuivjwjxkymzn{n|o}p~qqstuvvwxyz{|}}~   !" # $!%"&"'#($)&*&+',(-(.*/+0-1-2.3/405061738494:5;5<6=7>8?9@:A;B<C<D=E>F?G@HAIBJBKCLDMFNFOGPHQIRISJTKUMVMWNXOYPZP[Q\S]T^T_U`VaWbWcYdZe[f\g\h]i^j`k`lambncocpdqergsgthuivjwjxkymzn{n|o}p~qrstuvvwxyz{|}}~   !" # $!%"&"'#($)&*&+',(-(.*/+0-1-2.3/405061738494:5;5<6=7>8?9@:A;B<C<D=E>F?G@HAIBJBKCLDMFNFOGPHQIRISJTKUMVMWNXOYPZP[Q\S]T^T_U`VaWbWcYdZe[f\g\h]i^j`k`lambncocpdqergsgthuivjwjxkymzn{n|o}p~qrstuvvwxyz{|}}~ɱTA"/O__o@3@3@jl2@a3@\]2@WY2@MQ2@DI2@:3@142@.B2@',2@%2 2Ap@$&2d 2A d2AJ?/?_?Ӳ792Ӳ+/2Ӳ%2Ӳ2Ӳ2Ҳ) +A0 P`p`p   0@Pв +ϲ&BAƲA /$A/?O_"dA @j@&CI2@ CI2@&:=2@ :=2 &@&2@ 2@&2@ 2@&2@ 2@&z2@ z2@&lv2@ lv2@&dj2@ dj2@&Z_2@ Z_2@&OT2@ OT2$'7Ok Aw0w@wPwwww**@+)*Re~<^+@8@@89@s&%$ 7@!I3@!E3@!AB2@!=>2A!?!!!!!@! "2@!2@"*?2@!.:2oAH/`?_"""/"?"_"""!!o!!!/!?!O!""!!@+HO7 A &A9&%8s542V&, /& 8ʸ&~&}Gke&^s@R&ZHDb@s?^<&50+*V)#U7h@,XO62,!  @+JKKSBKcKb S# QZ#BKKTB8+KR7+KP[XY8+TXCX(YYv??>9FD>9FD>9FD>9FD>9F`D>9F`D+++++++++++++++++++++++KSXY2KSXYKS \XEDEDYX>ERX>DYYKVS \X ED&EDYX ERX DYYKS \X%ED$EDYX %ERX% DYYKS \Xs$ED$$EDYX sERXs DYYKS \X%ED%%EDYXERXDYYK>S \XEDEDYXERXDYYKVS \XED/EDYXERXDYYKS \XEDEDYX ERX DYY+++++++++++++++++++++++++++++++++++++++++eB++;Yc\Ee#E`#Ee`#E`vhb cYEe#E &`bch &aeY#eDc#D ;\Ee#E &`bch &ae\#eD;#D\ETX\@eD;@;E#aDYGP47Ee#E`#Ee`#E`vhb 4PEe#E &`bch &aeP#eD4#D G7Ee#E &`bch &ae7#eDG#D7ETX7@eDG@GE#aDYKSBKPXBYC\XBY CX`!YBp>CX;!~ +Y #B #BCX-A-A +Y#B#BCX~;! +Y#B#B+tusuEiDEiDEiDsssstustu++++tu+++++sssssssssssssssssssssssss+++E@aDstK*SK?QZXE@`DYK:SK?QZX E`DYK.SK:QZXE@`DYK.SK=<;:987543210/.-,+*)('&%$#"!  ,E#F` &`&#HH-,E#F#a &a&#HH-,E#F` a F`&#HH-,E#F#a ` &a a&#HH-,E#F`@a f`&#HH-,E#F#a@` &a@a&#HH-, <<-, E# D# ZQX# D#Y QX# MD#Y QX# D#Y!!-, EhD ` EFvhE`D-, C#Ce -, C#C -,#p>#pE: -,E#DE#D-, E%EadPQXED!!Y-,Cc#b#B+-, EC`D-,CCe -, i@a ,b`+ d#da\XaY-,E+#Dz-,E+#D-,CXE+#DzEi #D QX+#Dz!zYY-,-,%F`F@aH-,KS \XYXY-, %E#DE#DEe#E %`j #B#hj`a Ry!@E TX#!?#YaDRy@ E TX#!?#YaD-,C#C -,C#C -, C#C -, C#Ce -,C#Ce -,C#Ce -,KRXED!!Y-, %#I@` c RX#%8#%e8c8!!!!!Y-,KdQXEi C`:!!!Y-,%# `#-,%# a#-,%-, ` <<-, a <<-,++**-,CC -,>**-,5-,v##p #E PXaY:/-,!! d#d@b-,!QX d#d b@/+Y`-,!QX d#dUb/+Y`-, d#d@b`#!-,&&&&Eh:-,&&&&Ehe:-,KS#KQZX E`D!!Y-,KTX E`D!!Y-,KS#KQZX8!!Y-,KTX8!!Y-,CXY-,CXY-,KTC\ZX8!!Y-,C\X %% d#dadQX%% F`H F`HY !!!!Y-,C\X %% d#dadQX%% F`H F`HY !!!!Y-,KS#KQZX:+!!Y-,KS#KQZX;+!!Y-,KS#KQZC\ZX8!!Y-, KT&KTZ C\ZX8!!Y-,KRX%%I%%Ia TX! CUX%%88Y@TX CTX%8Y CTX%%88%8YYYY!!!!-,F#F`F# F`ab# #ŠpE` PXaFY`h:-,B#Q@SZX TXC`BY$QX @TXC`B$TX C`BKKRXC`BY@TXC`BY@cTXC`BY@cTXC`BY@cTX@C`BYYYYY-,CTXKS#KQZX8!!Y!!!!Y-&iiiD|ZRRD/W~ "APoLu\7LnpX cc-\ @Wr]g!wM+Le|C]h5G!\M-x ,I?)9Io#o 2@z1UW~~FB/OV)or,11di+ &  sC_a^m8Q[h|ATkhqBBSsX2Q|  !U{{~!""#rw"+5<Yoq22 *<Qaajx *>LQ_jqx !".5BOO^eq *G]ety "&+G_u\ m6>PQ]`E3-_dM?}$x;;N&;MKSj1<ex ~ 90+ P >X!q}E +NT2N7kwdg3|)n*i9$]u MRhm}qyXgV%|2!r\/AMrLjUxiWnTgeRZgn-|{pLFF-S%F>S?("bJmH3NFpyQ hlOa+999^ssIwVXZ||@r9A99sUss<sVssUsMsasSsU99prpsZoVVfV9m97Vs9cV9XV\0V V V)999'6sYsJsPsFsK9sBsssDssH?9$s!(9/WVVhV9csJsJsJsJsJsJPsKsKsKsK99#99 ssDsDsDsDsDsssssI3skssQmL=dN9SdNdMdMs8zd1/-%DrdTs.d3ssVV9cRsSGldN/!VV9s\\sI9lG%VVVVV99999c9c9c9.k:(sV\?)(sIV!Vsrk!kk!s9msB9V\?fPfPsFkVsJVsJGVsKVsKsBsUsss9csD<V\?09$0#ss)()(h9`bUHtHbD).0HkR3OOOjrq"~~~~~~f0 0 *+kUo@:@7?@%UapVsJfPfPVsKVsKVsK9msB9msB9msBss9999999f7Vsss9csD9csDkV\?09 ssssV!VsJD9S9V!sZk""JkWF2xVVXV)9VX 3m9cV0VV a9VHbsk`Hss\\sDV`3z?W`sH`?WW2UdV\997u 1 V@VUkVcN@9cVf0 RV UWUU@UsJ[@sKZ2xxksDUsP&!K+Ek(+0UsKsK?9 @s!kJA-11~~!}3 9iV21-_(P<P<Z<n_s f(d$(ZVZ((WWH-ddddiiiV21-KJK(P<P<Zn_s f(d$(V2P_s<%QCMyFFFFHFFQF5|5.555,5555555B6555F656==ZvZ'ZvZ'2j0FF@FQ sJ]My"VVuxux-Y2jYB=656==656==656==????Z*65'Z*65'OmOm$$ss''  ii''55B6='uxux2j2jZ@@Z&0ZSAZSAFFQFFHFFFFF@0FFc?D[/Ts) grksSrj}_vlX,VsJVsJVsJVsJVsJVsJVsJVsJVsJVsJVsJVsJVsKVsKVsKVsKVsKVsKVsKVsK9c9|9csD9csD9csD9csD9csD9csD9csDc?Dc?Dc?Dc?Dc?Dss[[[[[V!V!V!VsJ99csDsssssU cZkssV UW+EU+csU9`sD,                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "                                                                                                                                                                 "                  &                                                                                                                                                                  &                          *                                                                                                                                                                    *                                   0                                                                                                                                               0                                          6                                                                                           6   :                                                                                          :       @                                        #    !"                  "      "                    ####          @    !B    " "          ! !  !!!                 $!!! !!!!!"#       "! """      #!!   !#              !   $$$$         !B    %J !   & &         % % ! %%#%    %           (%%%$%%%%%&'" !       &%! &&&      '% ""#!% "%(                ##%      ))))       %J               "*T %   +! #!!*    $  ! **!#  %*!*(*  + !!!    ###!   ! !".***)*****+,'  %!!!   !! * *%! *** ####!#!#  #!#   ! !$ ,*$'#! ''!%*#"#  &"*-      %              "'"' *       ####..$$..$$!!         *T$$##  !!!!!!!$$$$$$$$$$ !' !.\# )    /!!$! %!$$!!.   & ! !!$! ""..$!!&#).$.+.  . $$$!!!    !&&&$ !!!!  !!$!! !!$%2...-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"...../0*###" )!!$$$!!   !!$$! !!!!.! .)$ .!.!.! &&&&$'$&# ! %!$!&"   !$ $(! 1.'!*!!%!$!!#"*+$)!.! &%&!# *%.1        %       ## ###### ###########!! ####%+%+################ ##.#############################   !! !! !! &&&&33''33''$$     ## ### ## ### # ##############################################################################.\''&&  $$$$$$$'''''!!''''' $!!!!!*!#$2d&,! 3!!$$!'$!)$'!'$!$!2!!  (# !!$!$'$%%22'$$)&,2!!'2/2 ! 2!!!!!'''$$$ ! $!!***'!$$!!$$!! $$'$$! $$'( 62221$##############################################$2111135.&&!&% ,!$$!!!'''$$  ! $$''$!$$$$2#! !2,' 2#2#2#! ****!'*'*& !!!!$!!)$!'$!!!*%!  $' '!+$!53+ $!!!"!.$$!)$'$!$ &!%!./(,!$3$!")()$&  -)26#    #  * #####  &&&&&&&& &&&&&&&& &&&$$ &&&&)/)/ &&&&&&&&&&&&&&&& &&2&&&&&&&&&&&&&&&&&&&&&&&&&&&&&   $$ $$ $$ ))))77**77**''       && &&& && &&& & &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&2d+!+!** !!!!!!!!!!!!!!!!!!!!  '''''''+!+!+!+!+!$$+!+!+!+!+!!!!! '$$$$$.!$!!!&'6l)0$   7$$''$!*'$-'*$*'$!'$6##!  -' $$'$'*'!((66*'',)0!! "6$$*636 #  5$$$$$***''' $!'#$ ---*$''$$'!'$$ ''*''$!!''!!*+!#;6665' ! !!&"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'!65555!!!791))# )(! 0!!$''$$$***''  $ ''**'$!''''6'# $60*!6'6'6'#  ----$*-*,) $$$$!'$$-'#*'$!!##-(#  '* *$/'$97-"'$#$%$2!''#-'*'$'!")#($13+0#'7' $%,+,"')  1,6:% !   &# * &&&&!  &#  )))))))) ))))))))")))'' )))),2,2" )))))))))))))))) ))6)))))))))))))))))))))))))))))!  " '' '' '' ,,,,;;..;;..++   " "     )) ))) )) ))) ) ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))6l.#.$-- $$$$$$$$$$$$$$$$$$$$  *******.#.#.#.#.#''.$.$.$.$.$###$ *'''''2$'$$$)*:t, 4' " """ ;''**'#-*' /*-'-*'$*':%&#     1  )"''*'*-*    #++: :-) !)0 -4##" $ :''-:7 : &   9'''''---*** '#* &' ""000 - '** ' ' *$*' '  * * - **'$$* * ## -." $& ?:::9*"#"##)$)))))))))))))))))))))))))))))))))))))))))))))*#:9999###;=5,,&",+# 3##' **' ' ' - - - * *   ' * * - - *'#* * * * :)& ' :4-#:):):)&  #0000'-1-0, ''''#*''/*&-*'$$&%0+&" ! ! ! )- -'2*'=;2"%*'&'''6#**"&/*-*'*$%,%+'56.3&*;* !" ' "(  0!/0$*,   5/  :>(!##"##!!  (%.((((!!!#"#!!  (% !  ,,,,,,,, ,,,,,,,,%,,,)),,,,!/6/6%",,,,,,,,,,,,,,,, ,, :,,,,,,,,,,,,,,,,,,,,,,,,,,,,,$  %" ))))))!!!0000@@11@@11""""""""  ..""## %"%" # # # #,, ,,, ,, ,,, , ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,:t2&2'00 ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '   - - - - - - - 2&2&2&2&2&* * 2'2'2'2'2'&&&'  - * * * * * 6'""*  ''', - C2%%<- '%%%%%%%%%%'''%D--00-)40"-%704-40-)0-B+-)%%%"%%%%"9%%%%"%!/ !!'--0-040%%%%%%"%%%%%%%%%%%%%%%%%%$)11C%C40%%%%'!07%3<))'%%%)%%C--4C?%C%!!- %""%C-----444000%-")!0%-!-%''888%4%-"0"0"%%-%-%0)0-%-%%%%0%0%4%00-"))0%0%)!)!%45'%)+%"IC"C"C""B0'('((/*/////////////////////////////////////////////1(CBBBB(((DG=22$,(""21( ;((-%0"0"-%-%-%4%4%4%0%0%"-""%0%0%4%4%0-")0%0%0%0%B/-!-%C<4)B/B/B/-!%(8888-58482----)0--70,40-))-+82-'%%'"%%""'!%& %#04%%%4-:$0-"GD9'+0-,-$-->(00',7040-0)+3+2-=?5;,0D0%&$'%-%%'.%%$%"!7 C*0#"2$%%""=6%!%!CH.&$"((("((&#&% %"/+"""7""$////&&&$"(("(&&% %"/+$%'    ############222###2222222222222+222002222&#$$!!6>"6>"+'222222222222222222%C22222222222222222222222222222)+'000000&#$$&#$$&#$$!!!!77$$77$$JJ99JJ99''''''''$#$#55''((""##+'+'$($($($(22 222 222222 222222222222222222222222222222222222222222222222222222222222222222222222222222C9,9-"88-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%4%4%4%4%4%4%4%9,9,9,9,9,0%0%9-9-9-9-9--!-!-!-%4%0%0%0%0%0%$>-''0%%"%"-"-#-#2%4%K8**C2,**********,,,*L22662.:6&2*=6:2:62-62K11."***&****&?****&*%5$%%,22626:6******&******************(.77K)K:5)))*+%5>):C..,)*).**K22:KG*K)%%1 *&&*L22222:::666*2&.%6*1%2*,,???*:*2&6&6&*)2*2*6.62*2****6*6*:*662&--6*6*.%.%):<+*!.1)&RK&K&K&&I6,-,--5/5555555555555555555555555555555555555555555557-KJJJJ---MOE88(1-&&87!-B--2*6&6&2*2*2*:*:*:*6*6*&2&&*6*6*:*:*62&.6*6*6*6*K51%2*KC:.K5K5K51%*-????2;?:>82222.622=61:62.-11?81+!*)+&!**&&+%"*+$)'5;)*);2A)62&OL@,06212)32E-66,1=6:626-09172EF;B16L6*+(,*2"**!,4)*)*&"%>$+'<>/6'&8)**&&D=*!%)%KP4*)&--,&##--+(*)#$)&40%%%<&&##(4444***)&-,&##-+*)$)&40)#)+ ''''''''''''888'''88888888888880888668888*'((%%=F'=F'0,888888888888888888*K88888888888888888888888888888. 0,666666*'((*'((*'((%%%%>>((>>((RR??RR??,,,,,,,,)"')"';;,,--&&''" 0,0,)-)-)-)-88888 888888888888888888888888888888888888888888888888888888888888888888888888888888888888 K@1@2&??2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*:*:*:*:*:*:*:*@1@1@1@1@16*6*@2@2@2@2@21%1%1%2*:*6*6*6*6*6*)E2,!,!6)*&*&2&2'2'8*:*S>..J7 0..........000.T77<<73A<*7.E>,61**>=%2I227.<*<*7.7.7.A.A.A.<.<.*7+*.<.<.A.A.<7*3<.<.<.<.S;6'7.SJA3S;S;S;6'.2EEEE7AF @D>77773<77E<6A<73468E>60%.-0*%..**0)%./(-,;A-.-A7H-<7*XTG05<767-87M2<<06E-..**KC.$'.)"SY9 /-!*2 21*&&220,/-&(.*:5)))#C**&&,::::///-!*2"1*&&20/-(.*:5-&-0",,,,,,,,,,,,>>>,,,>>>>>>>>>>>>>5>>>;;>>>>/,,,))CM!+CM!+51>>>>>>>>>>>>>>>>>>.S>>>>>>>>>>>>>>>>>>>>>>>>>>>>>3"$$51;;;;;;/,,,/,,,/,,,))))DD,,DD,,[[FF[[FF00000000-%,!-%,!AA0022!!**!!,,%!$$5151-2-2-2-2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> SG6G8+EE7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.A.A.A.A.A.A.A.G6G6G6G6G6<.<.G8G8G8G8G86'6'6'7.A.<.<.<.<.<.-M80$0$<..*.*7*7+7+>.A.\E!33R=$633333333336663]==BB=8HB.=3KBH=HB=9B=[>=8)333.3343/M3334.3-A---6==B=BHB333333.333333333333333%333 18DD\3\HB33335-BL3""GR886233933\==H\W3\3--=3..3]=====HHHBBB3=.8-B3=-=366MMM3H4=.B.B.33=3=3B9B=3=3333B3B3H3BB=.99#B3B38-8-3HI53)9$<3."d\.\.\..ZB68688A:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8\[[[[888^aTEE1<7/.ED)8!Q8!!8!=3B.B.=3=3=3H4H4H3B3B3.=/.3B3C3H3H3B=.8B3B3B3B3[A=-=3\RH8[A[A[A=-37MMMM=HM#GME====8B==KBME=5)325.)33..5-)34,20BH232H=P2B=.a]O6:B=<=2>=U8BB6D=TVIQ*33(6?3323.*-L-50JL:B0/E233"/.SK3(-3-&\c?#42%/7#76/*+77 5142*,3/@;...&L//++1@@@@4442%/7&6/*+7 542,3/@;2*25!&000000000000EEE000EEEEEEEEEEEEE;EEEBBEEEE4011--KV$/KV$/;6EEEEEEEEEEEEEEEEEE3\EEEEEEEEEEEEEEEEEEEEEEEEEEEEE9&((;6BB#BBBB401140114011----LL11LL11eeNNeeNN666666662)0$2)0$II6677$$//$$00#)$((;6;627272727EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE \O/MM=3=3=3=3=3=3=3=3=3=3=3=3=3=3=3=3=3=3=3=3H3H3H3H3H3H3H3OO>O>O>O>=-=-=-=3H3B3B3B3B3B32"U>6(6(B33.3.=.=0=0E3H3dK$88YC!!':!8888888888:::8fCCHHC=NH2C8SHNCNHC>HCcBB=+8!88288782T8887!281G111!!:CCHCHNH8888882888888888888888(888#6=JJd!!7dNG7778:1GR7%%MY==:787=88dCCNd^8d!!711B8!!228!dCCCCCNNNHHH!!!!!!!!!8C2=1H8B1C8::!!!SSS8N7C2H2H287!C8C8H=HC8C8888!H8H8N8H!H!C2>>&H8H8=1=17NP:8->(A72$md2d2d22bH:<:<>BBTKB:-87:2,8822:1-89074GN787NCV6HC2jeU:@HCBC6DC\@LBJC\^OYBHeH895$:8C.88,:E78682.1R194PR?H43K688$32[Q8,171)dkE!!!!!!!!!!!!!&!!!86(3<&<;3..<<#9597.073E@111*O33..6EEEE8886(3<);3..<#997073E@6.7: $)55555555555 5KKK555KKKKKKKKKKKKK@KKKGGKKKK855511Q]'3Q]'3@;KKKKKKKKKKKKKKKKKK8dKKKKKKKKKKKKKKKKKKKKKKKKKKKK K>)++@;GG&GGGG855585558555""""1111RR55RR55nnUUnnUU::::::::6-5'6-5'OO::<<''33""''55&-'++@;@;6<6<6<6>  %@9Ou!  %9  h+]+]+<<<<<<?<<r 88)^  1^ j7q+]]]]]]??.+}<<<10]]]]]]]]]]]]]]]]]]]]]]]]]]%#"'&5467&&5463267&6654&#"326YzkcBϝ-0ReymuE_GIa##MfQcc|SrBøєXt(|[FEh?K_^D"K*5WIYeZ'&@ jq+]?991053.0|Q`=@ '33@^ +]?|G_<DZCTX@  U U @ U @UUU U@    9/9//++++?+++210CTX@  U @ U @ UU  U@ U  9/9/++/++?++210@6;;I Y Tk dzz  @  O @ s@!#4 8@ ?_o$+]+<?<c`Ҋ~K|]Ya p@    @0 s@!#4O_os O__?_o+N]q54'#"5432#"&4&#"326p|aS}P66mƏ{z˥tx|}SznLp Vk4Ĝ&8@  << 54&#"'6632531$8wsZX6i$jM:;+b:i`tNJ`loQGW@W! !!%5 3EID!F$FIGVTz)%)& *&)569C%VY[!V)VIYVee%f)vzr$!&PS@ '0 P  HCKC: : +p++M'/H$@P>$$0p?8*$+ #@ 55XW+N]M]]/]???]99910]]%#"&&5463273327654$#"3 $73#"$$'&547!2#"&'&32>54&#"AQYirW9")5Vr}bX3CTdz@ra̶EU T8|qHa@qj@K[h؁?[]a'=P "g~ir啽 ɭ*'LCfAYgUU U@Y U U U/0gh ` YVPh         @ U   @ U   p@  @  @ eRP@ P    @+]q]q]q?<?<<.++}ć.++}9999ć10K SKQZX8888Yrq]++++++#3#!!&'3XݫF"3FDZw*@G UF#V#f#s iup s  ' '* **))& U@3U U U U U UT%& U U @ U ,   UU U U U@ U]+;\+++++++]<54&&#!&sfgW=8JKFm^&CZ:TYe^3'g`1RfMIo) 8kFRy1fvӵcj U@_ U 2 cpt  *(* G VWVhk{޲(9@-(9  &J& &  Uc\+N+]MN]M??910++]]q]++r#"$54$32&&#"326=כC,;3“\m憣1nU-銼Z@/ C& @ U U U  U @ U    UU U U U@ U];\+++++++]<<+++++]?<?rs^sg0pMQOa7" ع @4    U@ U U@ U U]    @ 4 UU U@ U U U@ U]  P ` p ;Y+]q++++++++]<<]+++++<<?CTX@  /33???910@$/*(% / 0 `  P  CTX  ??99@$     ee@ (9P@ @(9_@ P0` `+]q]q+]q+?<?<.+}ć.+}K SKQZX 888888YK(SK6QZX8YY10]q]]Y!3673A}."-׀pxx)Fv@&)&)&9696IGIGXWXWCTX@3+44 DD KTT [dd ktt { ?????9]99@  < <  <@Z         A Q QQ@Q +N]MNEeD?<<(7-@, * *) **9 67:*I*] ]*j i*`0 ) ( U'@ U((((D@ U U U5@U U+,*499,IH,VY+fi+v +74/$42!_)o))/? UU@U UU@ UE' 2 )aa U%!$U$@ U$ U$ U$ U$@ U$U$ U$[@'@&& &0&&9U&ֶU&19@ #409999@AU%"/$?U U U U U U U18+++++++]q+]q+++]++++++++<+??+?9/+++++]qq999910]++++q]++q%#"&546676767654'&#"'>32#&326765ZCTX@4 @Pp  U U U U/++++??]2]210@G CCSS``    jiju p  "_o@y0@P`p    $ U"$ +@ U@UH U UI$? U U U14++++]q++++]rKS#KQZX8Yr+r??9/9/]]10]q]qY#"4632&&#"326<r鉭Zj kl‚FU@  % 4 D 55WT RSgde c`+<<Kp.$ .:5 KE FIW V g     3%%@`@ U@ UU@UU U@ UU U@B Ut$?O U U U U U U4P+N++++++]qM++++++++++]q<<??S@U]] U eko e  U@R U U'1:1AMAQ\Ramaxx P`p U@U @ ܴ U U U @ '*4  %&4@A#403$@$*4?O U U U U U U47+N++++++]+MNq++q++++M?]++?9/]*o@` , %L E , &,#9 6J FVX h .#,'>#>'L',,6!6)?,F F!E)T!T)ic!c)`,,'!#'(@ 0`p}@2 E" 3%3 %@`,@ U,@ UU@UU U@ UU U@J Ut%"$?O U U" U U U U+,t!4P++N++++++]qM++++++++++]q<<??]??<10]q]q32676'#"5463253#"&32654&#"f 2Ct}vnэze۠Ꙧ}|zxXQ%2dZ7<ݘjx*a4@ U%5E @:4  % @364  @ U@U (U U @ U  U  U @ U U @ U U U N@464p%@364 U@U U U U@U U UNGP+++++++++]q+<<]q+++++++++++++]q+?#ǹ U U @M 4%    #  # # %%%%%UU@ U U@ U U UU U U]@ %U@ U U@ U U U@ U U U]@3#%?O@U U U U UU@U U U$%x!GP++N+++++++++]qrpXdL:&N_bX'l_:xxP>}@@< 4y   $@U@ U (U U @ U  U " U @ U U @ U U @ U @364   N@464p3%UU@U U U U@U U U@364 N]q++++++++++<<<]q+]q+++++++++++++<<? k U U@s U U  GHVYgi4::5EKKE\\ R]]Rmm dmmdw  [TT [ lee l  $@ U@ U@U U U U UU U@$%40 1@I#40$ U U U U U U U U@$%4?147+]+++++++++q+]]]++++++++++??10q]qC\X@ SS bb ]Y++++7632#"32654&#"D{'v i!>b@ -=K?  ) #22Bp ::JJY[ \\jk imk  #++5:FJZ   $  @ `  @ U @ U @ U  U U U U @# U t33%?O@U U U U UU@U U UG7+N+++++++++]qr6@ +*;Ky ??K44?DDSScc` )" +95 IF Zi    3%@`@ U@ UU@UU U@ UU U@? Ut$?O$ U U" U U Ut!4P++N+++++]qM++++++++++]q<<????9910]]qq#"466325332654&#",*Uo~q!xsvui;N.C>@;/#4CSft      (" "%@364 U@U U UU@U U UNG+++++++++]q+<]r???999999ɇ}10]r]336632&#">i?[^>BB;^&qH:'G?`r?>0@{"": J D$V"e"| $, 0K,U2 \\ \ \ \ \ jj j j j j &''&$'$)6$Z Y d&d(t#t$$ (,0 '(&&( U" U# U$ U( U" U# U$ U@9Z'%  & .@", U?O_oU@ U@4@4.\l UU@U. $@42@/UU U U U U U U[$*9** U*U* U* U*2@!'*4`22?222$ U U U U @U $ U U U@ U U U"?O147+N]qM+++++++++++rN]q+++++q+M+++++++++r?+++?q9/++]qr+]qr+99910Cy@@'-#,&"  (- !#"# ) (' +++<<+<<+++++*++++++++++]q]rq]732654'&'.54676632&&#"#"&?{|x5%ƙOA8*S}Z si|j/Vi}=kreD=#%2INGy(+H{gR\R7# $3A|\ZW$*ع #&4 @A#&4  +  "" % E E`p UUU U UU@ U U Uj6f++++++++++]q<<<??<<993310]++%#"&&5#5373#32LeclM,&O@ 4 4@34+$    3%@364@U(UU@ U U@ UU@ U U@ UN@464p % @364   U @U  U U @U  U  U NGP++++++++]q+]q+]q+++++++++++<???<99910Cy@    ++**]+++!5#"&&'&53326653?|^O nQQ;HmO5s1GQS9& CTX@   $U/+33???9105"9 @ 9 4444 @ !4(!4 @ "%4"%4 @~(.4 (.4 )( & 95 HG VVYX ffii xwwyx w   ,   (& 7 O@ @4@ 4CTX@  @ U U @ U U 9/++++/??910@7 %  %  /  "@@@  @@ @" +]]]9999?<<!4@J!4)( /99 IFFI O\TTZ Plccj {t{  &)+ 94,9 @#9:  % a+ a @ U + [@ U" @`@$ Ut ~Oo Ut!|++N+]q!4++++qY]C\X޲9 ޲9 9 = 9 @ 999++++++++Y35#!5!63!(sXOdoyjw^{ 9Q|*{@MG(44 4% 4')** %  %   %:%&:*':&**_i+ph+]<<<<<??9/9910++++q>7>7633#"33#"'.&&'9Ma  1H8&V8hD W]ncA_8b,@T aMdON5Tf= KEkt-.%D6ghPQY2~@v +N]2!)d+CTXA+@ @4 dH+++Y55Y&$?@ h+)++q55f[v&&"@0 0O0/0000H+)++]q5,&(Tj(@/H+!)++]]q5&1QKU@ UoO_zH+!)d++]]qqq++5c&2,#!)+CTX A+  dH++]Y55"&8@  A!)++55J&D@/;?;;H+;")++q5J&DC@999 H+9")++]5J&D6@&: :0:p::::::::@.24:=A>")+++]qr5J&D'@<@ Up<<<<bH+?")++]+55J&D8@I@ UI@ UI@4I@ 4IIIдH+G")++]++++5J&D@AAAh+A")++q55Po>&F7@U/0 H+)++]]qr+5K&H@!!! H+!")++]5K&HC&@ 4p H+")++]q+5K&H'@ @;5 @-24  # A$")++r++5K&H#@"@ U"" dH+%")++]+55.&2@ U4@"%4/ZH+")++]+++5#&C(@@4@"%4 H+")++]++5h&@  A ")++5 :&@ UH+ ")+++55&Q5&")+CTX# A+("$4O((H++]+Y5D'&R@H+")++]5D'&RC&@ 4pH+")++]q+5D'&R @@.24A ")++r+5D'&R*@ @U@ UnH+!")++++55D'&R0@/+?+++O++/+?++H+)")++]]]q5&X!@@4O p+]<<<<<<<<?<<<:+N]M<]]{?{@{AsIsJ->?@AHIJ)) )$)"1HC EB?9% ":/'<HCB?:9/'% 6'@-' <>+^2><)O++L"^><8E)OKq+N]MN]M??999910]]732654'&%.5467&&54632&&#"#"&6654'&'&'zifs$>uJxiG:ȥiY\q$87GCI*pPOdm3JI45CQE..FihF3+K[gL`DsAz`c<4,D`-54&#"YЂ$\d-@͠~/2d7Ll ['(g m[kpr3l?  AY6MiƇjH]HhF8(>r99<'PX">_!6@@6,-&')-)0+1 +++ e01/d/t//г&-4/b@.,..,-,+*).012601(3-,+*/))5b77 !@?b@!""".//6O  o   b b;b&T/b.@756!6b J bBb Az+NMNM<<<<??]q<<<]<<9/9/999.++q}910Cy@J<>%$%=&%&%&& %&%>#;,!! !!<%?, !! !!++++++++++++++++++++]q]2#"$54$"32$54$!2#'&'&##32654&&##jjӪ,,Li+1GcHU4$EMrS(G`hk}Ѥէ+/,-p?Y0q&D8$9:3@  036p !$/0..`+8b@O$$o$$$$2b@ ++++b b/b. b!5b'd b<b ;z+NMNM??]]q]10Cy@T37%*)&%&%&& %&%3*57%5!! !!4(26&8 !! !!+++++++++++++++++++++]2#"$54$"32$54$#"&546632&&#"326jjӪ,,T{Ëdw wuOspZhk}Ѥէ+/$}ʄcmJOh@] 95JF  i b@  b;;b b@ 0`ٹ.+]<<<<?<<<<<<999910]]!5!!!33##e|{yyJ/uTJOeȳ44@&4oooOP`S٧+NM?]<10]]]]+++3ޅ=nH@#<<<_o$p+N]M<<<<?<991053353=N@         ?  %  0   %   U >q+<<<<<<9/9/?TX8'l@Owvx % &D dsy%{&%& Uk:%E/)6#  =) &i(h+??9910]]]]]'6632#"&5476%.#"3276F^L{/-ڎ(`A>v}fDKUur@"#l vy+<<?<IlUk{`0H8 F0#A<"Yw=>w=2(,&):N9- C/| |@)ip) ih+]]??10]2#"&546"32654&uQceOPdeȰįȅr~uuzt*Y@%99EJJF%YVif|zt%&;. H@) +;::+';'''':*:)((::'(@ U( U/Ox@ & J(U U U@ Uj, (@((x)$&J)U)U) U)@ U`)) ))++]q++++]]++++<]++<<?<<<<]q]q?10Cy@ # "%& %&!$ #  ++++++++q]%&'&54$3 %!567>54&#"!5l9W^/PlW5`lP,Hd3cɏiC?`I]:?(&=gxHD>5<J{@5=9=HL)O9Z)^9z(@0"4%LCB%DH[VVS%iged#wt&$ U=U=@. U====F6....2: :'' F 2}@ 6%3=%.7@. U.@ U. U. U..?...ĵ+5$3+U+ U+޴ U+@ U+0+@+++@; %"C$  U " U  U  U  U  U  ? O  K47+N]q++++++M]++++M]q++++?<]?<9/]9/]+++10]]#"&'#"&5466767654&#"'>326632!3267!&&#"326762Mh{c–fiWx9iăf;(@sbCXgHz~Om,;jesE`ff`VN~e*MUuN2@FI}*Wvk"'"/LGarU4dg!+@", %FTdU(!"FI LLEK&Zfdf""+,+/"; =8&T-X \^&" !"!!|y!y"#j!i#z zlfm&u;"EJ&-,"9M CIF'z"v#"d mmh"""#@7 !}!#"(-(,  % [[% ($U U U U U@UU-4-@5 4---- ----$U U U U U@U,3+N]q++++++MN]q++]+++++++M??999999999.+}<<<<<<<<10C\X޲ 9!޶9""9#@ 9"%9@9++++++Y]]]]qq]]]]]]]]]]]]qqC\X@)"#"#$ ""-]q]qY]q+q]7#"''7&'&532&#"32654'&c`k?zi^l;(&R[d4?Nb FVFdԍqPGDDm- *Fʖe?L9*SO&"@7|k|`k]]KRLK:D ')"@!<^l $$<"^"^ v#+]<]?<71$7wrYY6&"nM:;+b:jatOJ`ll& vCTX@ <:<:/?/10@#< :8 8:<<  !++]<?/10KSX <F&7igq3x2*-@c$ #+$""%+-// "%!"%&!!5656EFEFVVeevv )-  )-$ #' p    : + p  '>$ >$##> > i/+>>>>i.+<<<<<<?]]10]]]]56323267#"&&#"56323267#"&&#"3j<{EE#A6@R .5@m&W DD#K&K*D-K2D4WWS#_&_*S-gh`$l&l*c-\2T4R[23#;&:*3->224 (% 53/+ 3 %}@& /@(@@3 U U U?IJ0@UUִ Uд Uִ UUU U˴ U U 4@@!$U U U U U U( U U?O647+N]q++++++++M+q++++++++++]q+++?<]?<9/]99999910]]]]]%#"46326632!3267#"&32654&#"!&&#"Lzu3@|c +볆G\WM-K vxcd sX]nӦooiĺa~bo[@5 z+N]/M105!sʑ[@ 5 z+<]</105!ʑSZ @\~~llZZ      < < P@/o8< <@4u8<<q+N] @4 u<8' jq+]<<+<<?<?<9910qqqqqqqqqqrq]53'667353'667W+[,65+[,65ѥ;Q)G_Sѥ;Q)G_SQ ~@6{ Zl  <8oP@8'<  y+N]º(z-Q0X[RM`Eb:xLl*1FXQe\H,L9@ 9@uu< 0jKZ+]/10]++#3# ;9\H!4@uup+]<<<<<<<<<<<<<<<</<<<<<<<MHDFJBM7!+5#2-)+/'2 T;QN?QGEILAI9 63$6,*.1&.  +++++++++++++++++++++++++++++++++]34632#"&7327654'&#"4632#"&7327654'&#"4632#"&7327654'&#"@YaOA; +,"<>!-BOA; +-";>!-OA; +,"<>!-6 ǵǺŘj-/.>ǵƹŗk-=>/.>Y,&$@j@oA!)d++r5,&(kj*@ @ 4 / _  H+!)++]q+5Y,&$?j!@ 4 H+!)d+++5&(lG@ U@4@ 4@4H+!)++]q++++55,&(Cj(@ o  @  H+ !)++]qq5,&,j+4@"%4/ZH+!)++]++5Y,&,j2 !)+CTX A+@@344@4aH++++Y55&,@ H+ !)++556,&,Cj9!)+CTX-A+@@4@"%4 H++]++Y5c,&2j$@4pH+!)++q+5c,&2j@ !A"!)++5c,&2Cj$@ 4PH+!)++]+5",&8j+@@ 4O/H+!)++]qq+5",&8j'!)+CTX A+5H'+Y",&8Cj#@@4H+!)++]q+5z&j @U% U U U U@ U U+++++++]<<+??<1033ƴ&I@d<=@ 4dd<h+NM+?<]<<<10#3#XqT@@ :??@  v Mv!z++NEeD?M910Cy@, %&22  222 2+++++<<+++]&763232673#"'&#":9Y>k;# "mT?gC"h>>6#4rr8$/_#@45h+N/M+105!p˔.} KU @ @@ A+]NM?<,+?:IjkLMjkO/@@--@?k[A : OZ@ : vM>Wy+? @^&>k U4Ks u:A@!<r<rp+NM]?<<M[4z-cxYKDT.w"xeV(H@d<=@ 4dd<z+NM+/<]<<<1073#3gn+ @     @$    T  e] U U U U U U  ;\+]++++++<<<<]?9/9/?<<10573!!Lf5{|ҭ @H p       E  @N 6 U U @U  U U  U U U @ U  N GP+]+++++++++]<<<<?9/9/?<10]5737#>nnss)\&&6(d@ 11H+4!)++]5?&V@ p11H+5")++q5)&&=d@ A!)++5(&])")d+CTXA+A+Y5QYOe~@# v  !++N]</l*Q {j=@ u  a '? a@:) )'h+NM<?]999CTX99Y10q]q676$7654&#"'6632!)? %FDBA;-S#99V)+0>/CoivUTK8s=$y!+v@##M'0a)@ '_o?a@) ')&)'),h+NM?]r]9/99910732654&#"#7654&#"'6632#"&! +;GVHW QK<;8?)}xGCYT<N72<n<+%4,:jTkP7VeD]ok *@/,3!?&D!T!(((@!(),+   @ :/?Ma(a)a@ **' 'c@)":**)i, )D+Wh+<<<<?<<]?<<<999999.+}ıCTX&*)99Y10]]q356673676$7654&#"'6632!M6fz>/l=*> %EEBA;-T#9 *Q {j=89W)+0=/BpivUTK8t=#yk @   )+::Vf fv@   @  :d@-' 5_5M  5 h+N]M<<<]<]<?<<<<<<<</lzhh9 *Q {j={l!-8;3/=@'=<% 23:% 1:20M @  0 @/?_o_oa a+@35449677/;9d0/.32@ 88.. 0@;1108:5363.)8N=)"" )0(((@ )")<|f+NM]<<?<<<<<<<<&V:2 )+CTX23..A+@ 3333343.&D@ 8'H'8 )++Z&&'d-@@U@U@ UH+!!)+++++5G (4@06'SS'bb'56-!: I CEI(Z j - # & C@4@@&H H @1#3   %U@UU U UU@ U U@> U@`t$ U U U U" U U?O)4+N]++++++M]+++++++++<<<<<&H='@`PH+ )++]]]5&&(3d*@ @ 4 / _  H+!)++]q+5K&H@  H'!")++*,&/Rj@  pH' !)++B&Od[<!)+CTXA+4@ "%4/ZH++]++Y5*  Q@3ee Q Ue    $U U @ U U @ U  ;\+N]+++++eclM,5F{"E*t0&&7d5 !)+CTX A+@ @%'4@ 4H++++Y5# "@*ol```ppr   !-@$@3 @@$+!  "0%EUU UUU U@ U#6f+N]+++++++M<<<??<<NM?<99993310]]53'667#"&&5#5373#32EHN-31LeclM,"+&8>;@:<4}?r+55CTX A+55h'+Y&X@ A"")++55",&8j3!)+CTX A+@ `UH++]]Y55&X1 ")+CTX A+4dH+++Y54),&=j(@@ 4YH+!)+++]]5(&]OiH+")d++]5)&=0j  H+ !)++]5(&].@@ U/H+")d++]q+58@  $UU U UUU U U;+N++++++++ @P "7GVVv u IFFI[TT[h h gy  %*5:o`  UU Uk@ U U@G UB7"@ U  U U  U % U  U? O  4!]++++++<q]++++++33????9]10qr]q]3#&'!"326%"32654&F;F;+S}D|&~d^,!eg#ĿH,@;X Z Uh h xEJJUZ '(78E3993[  ko c `coo`~ __ P PP_ZP+k j @3{0@[k@@!@ U!@ U@U U UU U@J$%40 1!@ U U U U U U U U?1 ]++++++++]]++++++++3/3/]99]r9]??3?3910q]]]r]]]q!!#"57&'32654&#"!dվ]Rzf@ Aʪܼ˼bc>$@7&_&}}&&!96"uy!!  @ 4? @ p  #@+  @ @"4  `&@@U U UO4%]+++]2/q3/+339/9??9/q3/]33/+3910]q]&#"327&#"327#"&547&54632={kXQxt# opM{h]^6F]nEGam~LSwD>$@=6699EEIISXTRT^ejdddm   $U UUUմ U U@! UP`p0@P`p @2 ?$ @$%4 U  U U  U U @U U  U U ?  1]++++++++++q]]q+++++++???9310]!#"32"32654&߅#K_&|}±.&@ P ` p O  p%U U U U@ UU U@- U p@p J/^]^rq]++++++++]]?L<;Ol#67!5!&&'VcM^g;L<;l%-0lea^vSh;5367#&&w^`elɐ/.%L;g^McVOn#67!#&&'56673!&'3^PE}}EP^^PE}}EP-++-,Ug3&'67#&&'5566-,,-+^PE~~DO^^OD~~EPg3&'67#&&'5566!!-,,-+3^PE~~DO^^OD~~EPbjk3!!jded#!F@  #!! "y+NM<32#4'.#"% D|wנE  5o\\s.mE}b]4t?rvLPh6r: j@< %?   %0%   WZ+N<<<<<<<<<</ON?2abu u??e!00!"//"!00!"//$$_dd #/! ! 4&#"326%4&#"3263267'#"'vu/"!00!"//"!00!"/2ba2?NOu u"//"!00!"//"!00_dd_$!FU/;3!!#&&''&&'!5!66776674#"32LfX"4I&P|9bkLpP3BD P BE0$e\$,-U?G5_J`]E2H9 Q>=3TjEjT9F=,-I '!!#!5!"&&546632"3254&&5;4gv~~n;I;yzzyoT&#"&&5432'"3254&&$93NXh v~~TfEK25yzzy:"#"&'!726'#"&54766766!lJ\N1K-TZ!-0IClE`a]c %%__[I;R6S73!!7676654'#"&54632&&5463267632#"&'&'J6Qg=[t^"#"3o|rvt3FG)rmYb(tx=3%X=)?&&'&'&&5463267632bsy.)mnQ=&!R>M[wh[|#N>CU.w=vgP~FfW@U6 UOp ~ E  E %U@U U U UU U@" U N]qr++++++++<<<M[uhet"N>CU.w&Q! A/+5]@^;4 ?A il{uru $$/q  /& $U Դ U U U @ U  V  UU U UU U U]+++++++<]+++++/]/?<@J$4Dr    %U@ U U U@ UU U@ U@364pE%@U U UU@U U U@364 N 9]q++++++++<<<]q+]q++++++++<<9?&U%/\&&6Ld@ 36A2!)++5?&V@ 36A2")++50@&  0  99   /@ UU U U U U@ U s+]+++++++<]<]<<<<??<<9/<<10]!5!!5!!!!#JHu #&4@[#&4/ + + 4 U 4 U   3  "" %EU@U U UUU@ U U@ UNG +]q+++++++++<<<<3/q3333++99??<<9/<<10]++#53#5373#3#327#"&&5%@ /I=jslU>Hu"&8d@ !A!)++5&X @@ST4%A")+++q5"&8d%!)+CTX A+H++Y5_&X@  A)++5"&8d@  A!)++5&X(")+CTX  A+ رH++Y5V""3XX"$@*4:;4!6"JJF!F"XV!f"v" " 4]  @  ]@ &U@ U U U@ U  P`p]$& UU U U U U UU 4]#;++]++++++++]]q+++++9/]q3//]?M[vebyIt۴NG*GT.w=xeFqPO^NW&%r "4'@ 4 4@@4 &5Dw*+ E #%   @pE %"!#0@%$@364'@U$(U$U$@ U$ U$ U$@ U$U$@ U$ U$@ U$$$N'@464''p'''''%U@U U U@U U U@364 N&GP+]q++++++++]q+]q++++++++++++<99/2//]<??L\uhbw|~;nS[0N>CU.wASPSS/SpSSS AAAA/qr55/]q5+55+5@,PDH+QRPSKO4S@``4S@884S`SSSSSS8?4S@ ,.4S)/4S'(4S#$4S"4S@4S@4S4S@+++++++++qr+++10+5Y,&j@ A!)++5D&X@ N%H'N")++S,&j@ 42H+4!)++5d&6@ ,H'/")++Y&$@<<+NM/<<1053Yv,&:Cj A!)++5&ZChA")++5v,&:j@ H+!)++5&Zh@ H+")++5v&:l+!)+CTX A+H++Y55&Z@ H+")++55F,&<CMj@ H'!)++!Q&\C@ UH+")+++5[ GP@ < i ? +N]J)yzk !-8@/:{wB\4@';4?%6a@ %/%?%%%+a@    }0a@  ")'.) @()'3)::9  )F9Wh+<<<99NM?<<<<99/]9/9/.+++}10]356673&54632#"&54732654&#"32654&#"M6fz7.l}F33IH67@GPVDFL9 *Q {m=/sPokVs-)j~d244-.7:E5:DE""6BMQ@/Oi&f*{&w*&*B\4@';4?!--:##Ka@ :/:?:::2@a(2a@ ! 0da!@/?_o_oa}Ea@2  7)%'C)5@/=)+'H)/OON)" )0(@' d)")N|h+NMr]9NM9?<l ` ٹ+9<</<<1053'67J^6]un&T(kk[K@ M   1@:M/8)j W+NM<]]10632#"'73254#"#|?M ,+2nHMt uLCO Z@8 @ P `  u@,/4_P/r]+q3/]3/?]q<<103#%3#%3#[u<֭[UUU U@e U U U/0gh ` YVPh         @ U   @ U   p@ RR@4@ 4T  @ eRP@ P    @ +]q]q]qr++?@'O_  b V b V ??9/]q10!!!!!!#^gyY&&c2" @4 U@ U U]   UU U U@ U U 4] @ U  P ` p ;Y+]q++]++++++]+++???10+3!#!~F 3 @< 66   &- 7:? I ij xx   U@ U  @6U U       1  ]<<<9??<<9.+++}ć.+++}10]qrq]!!!55y <!/07F< I;0 @J@O I@@`p  0@ 4 4## 44 ]  @ U   U U @ U 0 @ @ ` p  ]@ 4@ U UU U U ]]++++++]q]q+++9/+<<????9/<<10]++q]33663#$uO sb ;5 aw@[XYXW [TXXzu \P od v % KKFE   * ; --  ::@ U U/Ox@ & JU@ U U@ UU U@ Uj_ @x&JUU U UUU U@ U` ]q++++++++]]]+++++++<]++<<?<<<<<qui>)@Wrp %5F   %@ U U @ U  U  U @ U U @ U U @ Up  N%@U U U@U U U@364 N 9]q+++++++<<<]++++++++++<<9?9V=&L@ N% U U@ U U EG +]++++<<??<1033&& Z U U @> UD? ZYii   (8XYJ@  @R U%U U%  e     Pp % U @U  U  U U U U @364   N ]q++++++++</]9q?<RiE>  @dk jj`_bjl blP__ P_9579IFFIVWX Y h x    $@ $%4UU@ U0` 1@ #40 %@ U U@ U U@364 N]q+++++q+]]]++++3/???910]]]]]q32#"'"32654&s#i."}@VQ>"@K')69 FJ   & 7 G v  ! $ U U U U U @$%40    1$$@:#40$$$U U U UU U@$%4?1#]+++++++q+]]]++++++3/39/3??/10]]]&#"#"'732654&'&&54!2*pp‹|FަCU,:+`nO~Y${#t3%AsK S;69/d&@9DDTSP[cjs{ p  % @U U U @ U U U U @ U p  N%U@ U U@ U U@364 N]q++++++<<]++++++++<<?53#.5z05Mδȋ.&gYb ʗDW&$U@I&( &9H@&S\]Sdknavzuz$$&&& HH   00@#  P  0@ U #@ U@ U UU U@)$%4 0 0 @`1&&@ #40&&@#@ U#U#@U# U# U#@$%4#?##1%]++++++q+]]]rq++++++9/+qr99/9/????9/]910r]3326653326543#"'#"5c@p%%q@b۪ab&d~7{cհI"&( ")+CTX A+H++Y55&#@p A")++]54D'&R@H+")++]5&# ")+W&&@ %' A%")++5&(^  !)+2@*fv" ]J  J& д U U U U @ U 7 UUִ U U U U Uִ UUT+++++++++<+++++9/???<9/9910Cy@  66 66++++]!!632#"'732654&#"#!2hLR8c˲!%^X U,&=j@ H+!)++5dv@+;]o )) ) 5;5 ;GKE KVT V Tj wyx   `p T   &&b/ -& @U U  c\+]++]]q9/??9/9/9/]10]q]!3 ! 4$32!"Y ^Y 836S Kt1GJ23\6,5&,( !)+CTX A+H++Y557a- )&=@b&&  H@  U$U U U@ U U@UU!& U@$%40 1( @ U U:@J UU-'++++]]++9/]++++++++<???9/10Cy@,$&&%%#&, !6$!6, 6"%6+++++++++++!2#!!#"'73265!26654&&#!^bɾ+j@Z!0"BBjzW]ohM wc)w`[{&D@/+     U U U U@ U U@"UU& U U U U U U@$%40 1!  UU U U U UUU] ++++++++<]]+++++++9/++++++++<<?32"'&#"#&&##"#67&&'&'&#5632kS=OW_  ]-.;@^Y.by`b .OdE?--YN e`P?Ti~iwQ--s&(Rer' k((OwdN&@SN9Fe!uKZt( @P`p ?O_%0@P% H %HH@% & U U@UK&" U"@ U ""\(&b&1']++]+++9/??9/9/]9/]9]910Cy@#$6$66#6++++q]]q732654&##526654&#"'!2# N]mo32"'&#"#&&##…lT=OXp  ]-.;JfG.el~gĐwQ--a'{R  b H@  U@U& U U U@ U UU] U@U U U@ U U:@ J  U U U b+++++++++]++++++++???10Cy@ & ,,+++!#!#"'73265 +j@Z!0"BBF wc0"+c2! @ 4 U@ U U U@ U9    UU U@ U U U @4]  P ` p ]q+]++++++]+++++??<10+!#!#F 3fv&07 @fh@ U@ U ] J H@   \\9/]9999??<<<9.++}ć.++}ć10r]r]33#"'53267 g{KmNWGg>~ք#-[R@I !!O!p!!!%++%{ {0 o   ?p &U U@ U?oó &U@ U U0`p@   @   @ U U @ U  O  /]r+++D[D(@E9 5%9'I F%H'YYU[Q%\' = & #3  & $*@ U*@ U@U U U@ U U UU@$%40 1*@C#40***#$ U U U U U UU@$%4?1)]++++++++]q+]]++++++++++???9910q]#"6632#"&!264&#"326 IsߢGDrp(2kTVeeO$ P໹&#2@6%/%F#+##++ $ UUU$ U U U @ U U @$%40    1%%@#40%%% U U U@ U UUE$++++++<q+]]]++++++]+++??9/9910Cy@3!%% & !   " <+++<++++++++]!2#!326654&##32674&&##k??Kc Ļ!sVDwrBju&3_Lq&^gI3TBGW3W&d@ + %U@U U UU@ U U UE]++++++++<??10!!#cQ&ol& ;@ +  + @ U U U U@ U@    %@ UU+@UUU@ U U@ U U Uڴ UU@$U?ON+ U @U    <]qr++rq]+++++++++++9/]q++9/]]+++++?<H`&8@9' %%:/:?:`:p:: ::0:O:::::4;!!!533U3@JU3+)'))'U+% !!%"#""#53') %# "7 @?.3 0 H"!! %'5)3/#! " @  (@ %8 UU U U U@ U(@O//"""P"""p""""39]qrq]q++++++<<]qq9999?<<<=eI%W7 QD2b>& @] (U ;P`p    @HH H ! $!$U@$%40 1(@ U@[']q+]]++9/9??9/]q9/]9/q]910Cy@*$#&!$! "%<+++++++]]q5>54&#"'!2# 732654&&#"rrSJaM=P2~PPл:[[yLVq P\& R@Vg{@ U U@9 U U+ % @U @ U$UU@ U U UUU U@ U@364N @464 p  % U @ U  U @ U  U @364   N ]q++++++]q+]q++++++++++++CTX9999Y?@K>??DD /,//L^z KK ?{{@ U%   @* H    I %U@U U U U UUU@364 N]q+++++++++<]]99?<33'"#&&##VEC5BV_$2G+)DGtp;X=&5B~PmhP!Ic?#&F@+3  %@ U@ U(U@ U U@ U U U U@ UUU@364N@464@`p%U@UU U U U U U@UO_op | +9/]+++++++++]q+q+++++++++++++??10Cy@ &% ++++!#!#"'532665D#lf?RO80&vX2&  U@v U   FJEJ VZ      xx     @ U + U@' U+      %@ UU U U@! UU UN? %@ U U U@ U N ]++++<]]+++++++<9?<<R& @+ % @ U@U UU@ U U& U U@ UUU@364N @464  p  %UU@U U U UUU@364 N]q+++++++++]q+]q++++++++++++?SP>F&&@/ 0 @ _ + WW%@ U U U U U U@& UUPP`/]qr++++++++??<10]!!#!&_&o!Q&\KiJ)5D@bX  77[\ USY Y"Y&U,V.U4jj edj n"n&h(f,e.f4yvy vv #0'33!3-  U% U@ U$$ U U UU@$$%40 17@7P7`7777 707@777@4#4077*$ U# U UUU@$%4?16]++++++q+]]]]+++++9/++<+<???l&&aTYEl& @+  + $ U U U@ UU@7$%40 1?_ %@ U U U UUU@364 N]q+++++++<qr]]]++++++??9/10Cy@  ++++332#!732654&##>l&aTYEl+>S}@9@ UU U@UU7N+++++5>}@^ 4GZ_ PSS_[no eccon"+  $U U@ U U@ U0$ U U U U U @$%40    1!%UU@U U U U UUU@364 N ]q++++++++++<]]++++++9/]q+++++<????9/10]q336632#"'##"32654&yڴZ|{&D*˷̽& @& 4 D [T y $   U U@*U%    ++   %@ UU@ U U U U U@ UU"UN ($ U+++++++++++<9?<@:EUUk l ls s { tu_o "0@` @H 4+  $$7$U U U U U U@UU@$%4?14 +N]+++++++++MV<L :&@ UH+ ")+++55Q:M&" @$+"" ++ +  % @ U U U U ٴ U U @U@ `   $ U U@ UU@$%40 1$$@#40$$ %U U@" U U U UO_#]++++++q+]]]+++++9/]q+++++++<??<?9/10]32#!!#"'5326532654&##D> 'ohoG(?([k&a﯐G NnSZFk9&@(+ +  %U U@ U U@UU/ $ U UU@$%40 1@ #40 % @U  U  U U U U @364   N]q+++++++<q+]]]++++9/]++++++<99<?fkl)&FgOTBe@  %5Fz@2+4    %@ U@U (U U @ U  U  U @ U U U @364   N@464p%U@U U U UU@364 N]q+++++++<<<]q+]q+++++++++++/]/?@ + + U U U@U_o% @ U @ U U @ U U & U U U @ U U U @364   N @464 p  %UU@U U U UU@364 N ]q++++++++]q+]q++++++++++++9/]++++?<??<10!#!3!3.&nP@.U U U UU  UU U UU U U9+++++++9/+++++??/103!# @#+ %U U U UU@U  %U@U U U UUUE+++++++9/]++++++???103!#w0&o&A[@ /105!Aʑ@ !%:@'(/'  U@% U7fu8* f@(*M#"5$%u UU U@ U $%^ b@^ U>' UU U U&++++<<+9/++++<99?<<1_u=3oZ\%)gvۍG2)1v@,Tc   U U@ UU̴ 4 2/+3/++++2/?3//?<10]%3!5!4&&#"'63  BAjX1@V#/8 4K Y j {  #      @ @ U U/]++2}/]323/833/99?3??<<<|9/]399.+}ć.+}10]#"#76634&&#"'632bI{R;TKIVG=0Ca4o[VY6 f-%Q@   U U@U U̴ 0]]++++?1@ )6ZZij @K   U    U?_ @ U U U +++3/]+3/9?<<?B @*/7GSYY S S\\S  &@ U U@ U U@ U U U U UU@ & U@ U U U U UU+++++++++++++++++??10]432#"732654&#"Zؔpј6u1%@5 yyu u ;i@6U  U 3/]3/9/+3339/?<;+\%qHHn{mNL7YI(1h+ ; I @  / @ U UݴUU++++3/]3/?3??1088]63 #4&&#"(B>k \d*%!@F+/#15==1HHY\Zhjju r tvy! !@UU!U ! Ƶ# !"229/+++?<2 lg&&&&=3oZ\%)mpۜ>%%%%2)1& @ `A)++]51&F(@@$$ $P$$$$$A)++]q5-%&N @  A)++]5@1& @@pA)++]5%W ӷ  @U U@CD4@=5O@ /@4/+qqr++++??/10#2#"&5466š%&5&%%q&&+)%;%"@ $$Pb@ ' U  @+ UUU@4O@4̳$ /]+/]q++++3/+9/??/]10]"#54'&547!5!2#"&&546; %&%0TfjJ1q&&&#1@;&@ (!A)++5%f @  @"U U( U@CD4@=5O@ /  @4 /+qqr+++++?3/]9/10#2#"&5466š51#5&%%+)#1,(&(h1&@ A)++5PV7&("@ U"`"p"" A)++]+5<F&97!U! U!!@ 4!A)+++]++5P>1&?@ %A)++5<<1&b1 U 4A)++]++5Z>B (@!/*\\S 7GSYY S S"@ / @&O&_&&&&&&@ U U@ U U@ U U U U UU@ *& U@ U U U U UU)+++++++++++++++++9/]q??9/]qr10]]432#"732654&#"2#"&&546Zؔpј#%&%06u1Y&&&#1nh1(@ "4 4IK[)8=@!!l )  (4UӶ%U%@ U%@#&4%@4%%  U@ UU#U/@*  U U U )+++]++++9/+++++?3/?9/3/1088]]++327#"63 #4&&#"2#"&&5466&\-6D?~b %%&'z 5uN%%&%s7 -@MKz//==!@((l   #4>%+@ U+U+@!#4+@4++&UU U / @U U  U .+++]+++9/+++++3/3/?3/?3/9/3/10]]632!"'732654&#"327#"&52#"&546z8q.b¢TR{ 'Bb %0$#105G?Ĭ{I%$00$#1 f%&e+ U@ U AG )+q+++5h%&:@#U#@>C4#@374#@4#p##A)++]q++++5(1& @ UA)+++5d*%!.@Z/0 yjju r tvHHY\Zh+15==1"@((! !%Ӷo,,,@UU!U 0! Ƶ0 !/229/]+++9/]?<2 lg=3oZ5k%)mpۜ>$  ///10#$H %@ MM  4@   @ 4ض@??4@44 @4@[\4@&)4@4" 4 @+-4  @ @+-4   @+34 +-4+-4ַ"+34/3/+]+]+2/+]+]+/+3/++++<<3/+++<+</10]r#'7'77'$H1111m1111 _@6 rrr  "()4@ 4/++<<</<<9//10'7!#!'71GQ11b1Q# z@. @ 4r  r  r   ޳()4@ 4 @ 4  +++<<</<9//10+#!'7!#G11Q11C 4 4  4/3/+9/9/3?3/++310#"&54767P?MfX+V!;75Tkp7=76(G660] 4 @ 4 @  4/3/+9/9/33/?2/]3/++310#"&54767#"&54632P?MfX+V!;7C00GF11B5Tkp7=76(G660"/EE/0DBC'3̳4@ 4@4@ 4 %@ 41+(. @@4""(.$/3/3/]3/+9/9/?2/+?9/++10++#"&54654&#"'4774'&'&54632#"&54632$)@2Bn@4AS*@* =J~ KxI41HI43F>/5B,DD"*I51Lt"izBR 48BpYol3IJ24IJy3$ 4!@4@4# 4# #   @ ##&@ 44 /9/+3+3/3/9/9/9/?3/92/9/+9/+910++'6767'&54767632&'&#"60bq] t3(0>PQK1 (4%='0h0%P+(#FZ/:@ 9 %# -3 4339%%## @9 0%5)#0 4005@ )@ 4)) 44/++2/93/+2/+9/99999?2/9/9/2/+9/9910'#67654&#"6763267&'&5476324&#"6V.:GW(  ."&E?'+5&G %A"  /)C6$B % #F7B*/ //4&U&F[E  4 $/<3/<?3/3/+2/10%4764764Z,S4Z,S[/,#Q,(";/-#R+*#Fb1#$/3/?3/104764Z,S1.-#Q,(#H(' !@ 4!!' ' @  '$$ $4$4$4$/+++2/3/2/99?3/9/3/+9910'##6767&'&54632'4&#"6S2J2I5G@!M-*  K& ,}$27H83'Be8()7 ]."F#$/3/?3/10%4764Z,S0,#P+("F(@%&!&@ 4&&! &%%4 4/++3/23/299?9/3/]3/+9/999910#"&'#"&546773276773276573 #** +  &K06 $ 922 $ #8K1 2(+/FQ -  /3/?2/10#"&546324&#"326Q\C66P;6Jb<6MwZWD-# | @  4 /3/99+/3/10&'&'667U0 U#"89&Wle0"D[v_1,.%; @ 4 @ 4 /3/+9/9+??9/10#474'&'&'7":-O(J`O0D#*ZwsԸ~@Z_Qs%! @ @4@4 4@4@ 4/3/+9/9+3/++???9/9/+9CTX@4+Y10#"'#'&&'7327677!49h 8&L0BC4_jp+ nBHP/OԲCU_.TK)k#]%) 4$$ @ &A   !!'&@ 4&&  @ 4 4/+3/+9/9]33/+9/????9/9/]9/910+#"&'##4'&'73276733273_c9T"hI% (8D4I4!\UUeJ9mL]o%XKFGLD??DY ")=9<3B#W !-.LdMbDG)+$ !HBAM)0 !@@@4 4@ 44/3//2/10+++#"'&547676324'&'&#"326guyFP,2FV\vJPCe]/B,$E?|zq*0[Qbx9B7-)ZIHR&#I@G(o( 4' 4 4 @ #@4##/3/3/+993/??9/+9/9910++&'&'&54767#"'&5465732767G&A!8$0J/0&$.jOcU .$+%=[o:=  N!"7%g3WAnWH%@ 4&44 4@4@ 4   4 @    G/333/3/333?+??9/++9/CTX@ 4 4 @ 4+++Y10+++#'376)@ǣ$eb? 'YV^3=1@T4&44 4 4 4  4@   G/333/3/333?+??9/++9/CTX84j4 4+++Y10+++&'#6763$1+ *[tG[WFV]) [/@Z'*. 8 P@ 4    /9/3/9//3//3/10]+#"&54632%##"&54632L76ML77L>mDL87JK66N7NO65JHGz6LL66ON0"9 4 4 @  /3/9/9/3?33/+3/+10'6765&'&54632&;"J*E)1%)K69VUI;9!777-( $<6MP:dgs 4#@2 4 #0qe6kY 4B 4YBGN,9ak*qFU;`kGq 4qqTGkkkN@ 4\ 4 \_QahKn? 4&@ 4?&,P333FGTUn`ah;*n,ah@ 4hh9,n@/3/+999992/q99++99993/q99++?3/]3/+9992/99++999999++10#"''#"'#"&5467'#"&54767&'#"&5463267&'&546327&'&5463267632676324&#"326d,!5JJ vV%4j  ! !$"!.0$VqC!;+!+*",k3=z;E(* 3#'"D6`*<  it8K`A2k۴qF,{@# 4 4! * @4 *@ !* 4.',/3/9/39/+399?9/?+9910++7#"&'#"'&54732654'&'326Bi\AJk0,Y/_=APM(0AWP)0@'1D=+Gжxiw%47_q 3'J|+CYRgJ@J-{#y 4 4  @@4@ 4###"/3/3/39/39++??9/9/9/9910++47"&54676632&&#"3267XGQNK;v-5sK IM1}l_V{-b^hDM-.?>/YJRV_ C26<"8"Xa!!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ FW:ι@ @ 4 @ @ 4 $*783./#*//$88$$*3* @ 4 /.'$#877/#$$/.4. 4.$/++3/23/299/+<3/<?9/3/2/9/99993/+3/3/+3/10476476#"&'#"&5476773276773276573[,S\,S3! #)++   &W.+%P+(#>0%P+(#L06 " 91$$ #8K1 2)-1!!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ %W/?10!5!WW%!!%!! @ !!%!! @ !!%!! @  $($44(4@ 44 4!#"$$%'&((@ o     A "$!##% &('%%A @*  4 */2/+2/9/9/993/993/99???93/]q993/993/9910+++++!"'&547673!54&'7'7'7''7Fr*9|oO6AM, DEJLJM"KN%CT]a#b..G8vA:p27pTVZU; µ44 @ 44 4  @ o   @ @ 4   */2/9/9/+993/993/99??3/]q993/993/9910++++%'7'7''7%!5!4'&'7JLJM"KNKNH8TVZUv>+Q[3M;!!!%!! @ !!%!! @ !!%!! @ !!%!! @ 6N u,04844.48@4) 4* 4y* 413244.57688-/.0@ 400  241335.0-//687@5@ 455 :'*/3/3/33/999]9/+993/993/99?9/99?999/+993/993/9910+]+++++"&#"676323263!3#"'&'&547676'7'7''7L@P4Z(#KB_Ep%Ӕ{F:؏XdOBFJ6F4@4J@4 4 * 4y 4GIHJJA?B@@CEF@DDD84=)%03"4-%%34=DFCEEAHJIGG@BA@?@4_????83@99""3433L))*/3/3/33/999]9/999/]+992/993/99??9/99?99999/]CTXDD]Y992/992/9910+]+++++#"&54767!3#"'&'&5476767&&#"67632326733'7'7''7{yf WXoF:؏XdUB%(Y$e?n"%SaM3a5()4!:2KUJLJM"KN%Zh':$4%DVll^ (0jyǫdSZ b&T%  8RۑTVZUyk"44"4! ""   "!@ T 4$/9/+9/9/993/993/99?<2/93/993/993/9910+++!5!&'&'&#"676323'7'7''7y%fFWHQS34/DhfEy+TN}Mb@()qzJUel/ *""sVj[Z4bZHnF)"+0s~9=XpTNT&m,!Z%E*ֳ4!4/4,40 4.@ 4;k= 4 44(4(ܳ 4(@ 4A(#A "  78@ (_((( ##8@AA 8G   4 */2/+9/9/9/]99?<TNѫF;@()XG=5!I/-=-{RZ,Q1 3ow%9=XpTNT&m,!)1YC.&Z4bZHnF:#0CA8<%Z9&3T)i? 1dk%m@4 4;k 44ܳ 4@ 4   @@o/_  */3/9/]]]99?TN}Mb@()qzJ%j[Z4bZHnF)"+0s~%d6ܹ/ֳ 4& 4441 45 43@ 4T+T2D+D2; k $ 4 4-4-ܳ 4-@ 4-"-(A ' "@ ---((8*/9/9/9/]99?<TN}Mb@()XG=5!e9&3T)i? 1dk)1YC.&Z4bZHnF)"+0CA8<%Z%,7@04/ 46 4@4 4;k 4*43 2 -... 4ܳ 4@ 4, A   %$ ,@ . 22@( A 9% $ 4$$( */2/+3/9/993/<?TN}Mb@()qzJUel/ *""sVJظ] j[Z4bZHnF)"+0s~9=XpTNT&m,!OYN?j$~FOZ%EP3@I4H 4O 4*ֳ4!4/4,40 4.@ 4;k= 4 44L#K"FGGG"(4(ܳ 4(@ 4A(#A "  78@ G#KK@ (_((( ##8@AA 8R   4 */2/+9/9/9/]993/<?<TNѫF;@()XG=5!I/-=-{RZ,Q1 3owظ] %9=XpTNT&m,!)1YC.&Z4bZHnF:#0CA8<%Z9&3T)i? 1dk˩OYN?j$~FO%m(@! 4' 4@4 4;k 4$#4ܳ 4@ 4  @ ##  @@o/_  **/3/9/]]]993/<?TN}Mb@()qzJaظ] %j[Z4bZHnF)"+0s~/OYN?j$~FO%d6A:A@4? 49 4@ 4/ֳ 4& 4441 45 43@# 4T+T2D+D2; k $ 4 4=(<'788'-4-ܳ 4-@ 4-"-(A ' @ 8(<<""@ ---((C*/9/9/9/]993/<?<TN}Mb@()XG=5!:ظ] e9&3T)i? 1dk)1YC.&Z4bZHnF)"+0CA8<%COYN?j$~FO2;&@4)44*4 4!' A 9' 4 03 @ ,$,@=! 4 $ 9/2/+3/3/99/??+??9910+++&&#"332!"'&54767673276654&##"&54767632 #a2W`X+5PHE`^f".<*?Cx+B71Cs}TePj6 @ 455@ 4,," 45& / @8  4 9/2/+9/9/??+9/9/+3/910+#"32!"'&54767327654&#&&#"&54767633])0Q0{@b(&%9zՏm#s?6I?3:??4HH44:C%%:,@ TKQKKQ @ QQ(?>743!HGG?/344?>4> 4>$/++3/23/2993/2/3/2/999?9/3/2/9/99993/+3/9/3/+99910"'&'#"&'6767&'&54632#"&'#"&547677327677327657'4&#"66#'#9<8L0: G-/   3! #**+   &Q#1  1& "!+U)# K06 " 82$$ #8K2 2)-1( F)1@&'"''"@ @4 @ 4 0*,,0.@**.@%(4.'&&4 4$/++3/23/299/+3/?3/3/++9/3/2/9/999910#"&'#"&5476773276773276574763 #**+  &3Z,S}K/5 " 82# $ !7J1 2),1/-$P+(#!!%!! @ !!%!! @ ///10#!$HbGQ$///105!#QHG !@   /<//<10###!!!HrG !@   ///10!!5!###rHGS@ ////<]10###!H @@  @4   /9=/<<//<+9=/<<<10#'77'$Hb ׶yyx #@    ///103#5!3###HGG)@     ///103#5!#3###HGGG !@   ///<10!!!##HFHS///<10#!$H,l@ /9=///<10##$HSW$'@ /<<//9/9/10##$HHH'88W' @   ///1053#5!#3WGBGGGW'///10#Hnw W$'@ ///10]#'$H'0W'///103!$'wGJ!'@/) !)i.@%) .0@>")> > i@)!?O>>>8H(y+?N]M]<]<M]<]<9999999910]'76327'#"''7&5432654&#"ՋsjitGGtijsGkklkwHHwn}~nwIIwn~}}llk #.48DHLRY`h@wz&S%c%#%3%C%Y=i=)=9=I=YAiA)A9AIAV;f;&;6;F;VCfC&C6CFCfhbdV`f`Y[i[**c*****u***3*C*S*cBB(-Wo]?]O]_]]]'VP(/(?(O((/ OGG23/3g<^P''O'_'' '0'@''R F"OM7K R6JMap999@9P9`999'W0^^'''_'o'@f''''$U-e-%-5-E--S++_oZP$$o!6 5## ! #j0eeo??????O??IJN/MMN1EQ2FN/]/]qr]q]]]q3]]]qr]]]/<<<<]]q]/<<<<]]q9/qq910]]q]]qq]]]]]]]]]]]]]]q]]#5#5!!5!#3#"'73253!5!!5353!#32##!!5!#"&54632#3!5!!334##324##32%#"32dCC?ddV4I(_tC~dYwdC~CddCdYeo|~ddd~C-Od?d ĺ[6.C?d{C~ddCcm !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ S0HH 44 4 /3/</3?310+++&'&'&4767670,h3g9JJ:f5d.l8<"8-}N౞Sy*K]SHW|@!!%!! @ % /|O@#%-.)$%!%%...@ 4!)!@c~9W=@C~~IIPPwccWCk55W==C%$ .--%$@%%c9Zg_@ccwPgg0TFI~}@TLPPT4T@ 4TTF5n0s ww00F/3/3/999/++3/99/9/9/993/2/23/293/2/?<<9/2/<9/9/9/9993/9/3/+2/]9/99993/3/9910&'&'632#"&'#"&5467732677327677"'&'#"&'#"&5467&&547673267&'&547673267&'&54767'3263 6 %%5)%  !** / & " wL=.(80?A{(p5p   C9.3'; $ 'B#:$X.4#72<Q=5-*$9 *jHk 6-- 0#U(()&%2&#;DL<;M!TL4"*"&RR{j70< '#*"%3wrI&.-'* )"+%"To #8 !y3 +@@?4  ?4 @ @ 4'$' @  $''/9/39/2/33//3/??93/+3/9/+99/+910#"'&#"'67632327'6654'&'667)02-c   & d2!54F2!31v ! $  PK(W L hu{,f-rt"%-@+-@?4--'+#"?4""'+@ 4   @--""## @ 4 /2/9/2/+3/33//3/??3/+3/9/+99/+910#"'&&'.'&'733#"'&#"'67632327D)$%  '{' "!b)02-c   & d2!54%70q{'0$xh|2* ! $  V n 44 4%$-0@ *4004$@  -00(%$$ (;/9/39/9/2/3/9/99??2/3+/9993}/+910++47&'&547632&#"326'6654'&'667n*d5;- $+]!2!31f @.#8> 4PK(W L hu{,f-rtV% 6 4,-@ *4--46!@  @ -,@ 4,,--&11 8;2/9/2/+9/2/3/9/99??2/3+/9993}/+10+47&'&547632&#"326#"'&&'.'&'733n*d5;- $+]!̌D)$%  '{' "!f @.#8> 470q{'0$xh|2*xcq *J͹-@ 4@ 4@ 4@ 4@+B2H0:@BBH@4HH0@ 400  %%!  @ @2==E++E006EE(( !L 4 ;/+39/2/2/3/9/99?2/?2/93/+3/+3/99910++++#"'&'&'73276767"'&547632&'&#"47&'&547632&#"326zBF3RAA8{1zmUU+OCL08VW&?')XM*d5;- $+]!a # >1]/j+1pgXfeO`% %13 @.#8> 4xcq-@R4@ 4@ @44  4%$-0 /$$@  (-00(%$$ (;/9/39/3/3/2/9/99?]?93/+]+3/+3/99910+47&'&547632&#"326'6654'&'667E*d5;- $+]!+2!317 @.#8> 4gPK(W L hu{,f-rtY@6@ 4,.4&@ ..4@444 4   @ ,))11"@1@ 41@ 411 @ 4 8;2/9/2/+2/++2/3/9/99??3/+]3/+3/99910+#"'&&'.'&'73347&'&547632&#"326D)$%  '{' "!*d5;- $+]!%70q{'0$xh|2* @.#8> 42q;[> 4&@4)44*4 4Q1Cs}TePk @.#8> 4j6V9 4 @ 4L7N>TIIQ77Q< 4%:Y ,@ 44 4" $*@ $$*@4**@ "' '''.;/2/9/9/2/3/9/99??3/3/+3/99910++!5!4'&'747&'&547632&#"326:KNHl*d5;- $+]!%v>+Q[3M @.#8> 4%:Y R3   /9/39/??910'6654'&'667R2!31$PK(W L hu{,f-rtY%<   @ @ 4 2/9/2/+??10#"'&&'.'&'733D)$%  '{' "!%70q{'0$xh|2* @ 44 4   A  A @"  4 */2/+2/9/9/99???93/9910++!"'&547673!54&'7'7Fr*9|oO6AM, DNJ%CT]a#b..G8vA:p27pT: ]4 4  */2/9/9/99??3/9910+!5!4'&'7'7:KNHfNJ%v>+Q[3MT: , '@ 4%% @ "")"(/3/9/9993/993/99?2/99+3/]993/9910'7'7#"'&54767'74'&'326NKALJ.GI07# !=#xWn/6- 908ːVTGn!=F\NO_T&?1 '#39?=%F%&/ @@ 4'+( . ((.ﵐ& @ @+#('  +1+/9/]999/993/99?2/]2/2/9993/+993/9910]'7'7#"'&'#"&5467&&5476733'32INKALJH7)\3s  !Wd"81<АVT[{\8>VND"*"$>t>DhmC7 %$@ 44 4@ @ 4 A    A @&  4 */2/+2/9/9/993/99???93/+993/9910++'7'7!"'&547673!54&'7%NKALJ`Fr*9|oO6AM, DVTzCT]a#b..G8vA:p27p%%:V{4 4     */2/9/9/993/99??3/]993/9910+'7'7!5!4'&'7NKALJKNHVT*v>+Q[3M%:V% (@ 444@ 4"4 4  @ @ 4 $A #$  $$##A @ *  4*/2/+2/9/9/993/993/99???93/+993/993/9910+++++'7'7'7!"'&547673!54&'7`MJhNKALJ`Fr*9|oO6AM, DcVVTzCT]a#b..G8vA:p27p%%:  @ 44@ 44 4         */2/9/9/993/993/99??3/]993/993/9910++++'7'7'7!5!4'&'74MJhNKALJKNHVVT*v>+Q[3M%: 6N u0@- 4* 4y. 4@ 4 #"$@"$##2 +*/3/3/33/999]9/99?9/99?999/+9910+]++'7"&#"676323263!3#"'&'&547676UM}L@P4Z(#KB_Ep%Ӕ{F:؏XdOB@ 4 * 4y 4A?@B@ 4BB84=)%03"4-%%34=@BA??83@99""3433D))*/3/3/33/999]9/999/99??9/99?99999/+9910+]++#"&54767!3#"'&'&5476767&&#"67632326733'7{yf WXoF:؏XdUB%(Y$e?n"%SaM3a5()4!:2KDMM%Zh':$4%DVll^ (0jyǫdSZ b&T%  8RUyk\  @ T 4/9/+9/9/99?<2/93/9910!5!&'&'&#"676323'7y%fFWHQS34/DhfEy+<KN%O,7J-Ad2m yTyk6N u,u@) 4* 4y* 4  @ .'*/3/3/33/999]?9/99?9910+]++"&#"676323263!3#"'&'&547676L@P4Z(#KB_Ep%Ӕ{F:؏XdO@ 4 * 4y@ 484=)%03"4-%%34=83@99""3433@))*/3/3/33/999]9/99??9/99?999910+]++#"&54767!3#"'&'&5476767&&#"67632326733{yf WXoF:؏XdUB%(Y$e?n"%SaM3a5()4!:2K%Zh':$4%DVll^ (0jyǫdSZ b&T%  8R%yk<  @ T 4/9/+9/?<2/910!5!&'&'&#"676323y%fFWHQS34/DhfEy+<%O,7J-Ad2m %yk6N 0@- 4* 4y. 4 #"$@"$##2 +*/3/3/33/999]9/99?9/99?993/9910+]++'7"&#"676323263!3#"'&'&547676MKL@P4Z(#KB_Ep%Ӕ{F:؏XdOH:%B-&>%)m-U%j%mf @     */39/9/9/99?2/9/3/9910]'7!"&546733!4'&'7NI@9[  *2>H:VB-&>%)m-U%F/pr@ * 4* 4 4 4@ 44 4  :  /32/9/??910++++++#"'&'&'73276654'&'7/^RztKEP=UHGB:~.%C9R',%nvhKH ( RK\OWFJLLVjF/pF/"@ * 4* 4 4 4@ 44 4 : $/32/9/3/99??93/9910++++++'7#"'&'&'73276654'&'7MK9^RztKEP=UHGB:~.%C9R',ȑTnvhKH ( RK\OWFJLLVjF/lWF@ 4@4! 4&4 4AAB:45,BB(55'( :, A145@ 455A ((''''#, @ 4 ABB?AAA=A @H  4*/]2/+2/]9/9/+<2/]9/9/+99??<?9?9/9/99/10++++#"&'###"'&546767327654'&'7327654&'732654'&'7O<[/*!/Z{,9ujt*$6(F-%5S2{_(#(%)K&C/ %!$& \WqBSFMVY6pE|CSdZGAR?Y4;# 7m>-Dq%5l Ro@ 44@ 4L 4*@4- 424 4  @ 4MMNF@A8NN4AA34 %+$F 8+ IM=@A@ 4AAM443333/8@ 4M(NN?MMMIA @ T% $ 4$$(*/]2/+2/]9/9/+<2/]9/9/+999/993/993/99??<?9?9/9/99/3/993/993/9910+++++++'7'7'7#"&'###"'&546767327654'&'7327654&'732654'&'7MJhNKALJO<[/*!/Z{,9ujt*$6(F-%5S2{_(#(%)K&C/ cVVTz!$& \WqBSFMVY6pE|CSdZGAR?Y4;#6'256 466B#&'@ 4''BCCB@ 4BB> I/2/+9/9/+99/+9999/993/993/99?<<?9/9/9/99993/993/993/9910++++'7'7'7#"&'##"'&'##5327654&'73327654&'732654'&'7gMJhNKALJM@\&/#3YA44"20PZQ#:) &.@CK$(*'":!)*A)cVVTz# %  $E:$<\*I%-9:"<^o+&!8> 7m>-Dq%l W1>@44 44 45-- <";2""2A @@  4 */2/+9/3/2/9/9??<?9?9/10+++!!"'&546767327654'&'73276767676324&#"!26 \rjt*$6(F-%5S2wfXaRAJYD?{RHY?aIH`r%hFMVY6pE|CSdZGAR?Y&!Gg4OI17 2&&'l W% >%0[ !))-  -& &2 /9/999?<2/9/9910!"'&'##5327654&'73276767676324&#"!26 N61%2*T\Q#:)#=AXTqzX QBJXE@zQdqpmd%$E;#l 5B̹@44 4 4 4"911!" @& @ ?6""!!&&6A @D  4 */2/+9/3/2/9/99/99??<?9?9/3/9910+++'7!!"'&546767327654'&'73276767676324&#"!26uLJ>\rjt*$6(F-%5S2wfXaRAJYD?{RHY?aIH`rdTlhFMVY6pE|CSdZGAR?Y&!Gg4OI17 2&&'l % )4z@ %  %--1 1 * *6 /9/9999/99?<2/9/993/9910'7!"'&'##5327654&'73276767676324&#"!26LJ N61%2*T\Q#:)#=AXTqzX QBJXE@zQdqpmddTl$E;#9/I  #- 1jC=ibI_NXAE%5,e/k^B_9/I  #- 1jC=ibI_NXAEȑT5,e/k^B_E&#8gM3I;P-8xYsωu]^-d" #i(`*/K1"C8\j/2DAQK]G % n4/  @4 4  /3/3/33/9+99?9/]?]9/910+##53&&54632&&#"66 Es$ś{P"QEn;cN]7K/w8v<b=21y//%mX(j@ $(4(  @$$$P  * /3/2/]9/9/9?<2/+9/9/99910#"'&'##532767'&#"#54763233mACP$CViZZTHRO* (:5qG]%H[%%BE&#8gM3I;P-8xȑTѠYsωu]^-d" #i(`*/K1"C8\j/2DAQK]G % !4@ /   @ 4 4 # /3/3/33/9+999/99?9/]?]9/93/]9910+'7##53&&54632&&#"66eKLFEs$ś{P"QEn;cNȑT@7K/w8v<b=21y//%m,@ ( ,  4 ,@$ (((P$$$$./3/2/]9/9/99/99?<2/+9/9/9993/9910'7#"'&'##532767'&#"#54763233LKACP$CViZZTHRO* (:5qG]%H[ȑT%BFUc,%h/"!)XHNYwQ(W[%~ *0G]jwubW/8)%1m%s%j%t@  # # @  4  !! '/9/99+9/99?2/2/993/9910'7!5!4'#"'&547632&'&#"326MJ)4.#I.528ZzB7*&#X4yVVYN %*Oht$%2-P%`!j@  4    #/9/99/99?2/93/2/9910+]'7!5!267&'&547632'&'&#" XSW>W33s7>Yf5*Z):(OK`~ 2xi]igP'K,L gw5BѳT  4@ 4!@ 41::)@@ @ 6 4&6#-==#A @D  4*/]2/+9/99+9/993/99??99/3/2/993/9910+++]'7'7!"'&54767327654&'#"'&547632'&'&#"326xNKALJz&#A* nfՠ &M'X7C:AYuD: *0-:%-"VTh]PWvxxF6J5C?>9FQ3-(0aqgt>).#$gw%j)@@ 4" '""'  @  4   %%  + /9/99+9/993/99?2/2/993/+993/9910'7'7!5!4'#"'&547632&'&#"326JNKALJ4.#I.528ZzB7*&#X4VTYN %*Oht$%2-P%`%@  4  " ""  ' /9/99/993/99?2/93/2/993/9910+]'7'7!5!267&'&547632'&'&#"5U}ViO{SW>W33s7>Yf5*Z):(ORQ 2xi]igP'K,L s%3(I.84 @ /H# /&&&H@ @ 4 2:=>353%'IB@&>2SSQ!@ ('K-J.&D!OiN%mI#v@  4 4! 4   #    4 % /9/+99/9?<9/2/10+++#"'&'##5327676767'&'&'mhCTaJ:yt[G7-=YPCE)7s &0!$:%#=G7.$AXA:iTrG:8/2 !2'>%mIl{v$ 4@4 4 4 A ! @ 4!! A @&  4 */2/+2/9/9/+99??9?3/9910++++'7!"'&546767327654'&'7KHjt*$6(F-0S5($ViqFMVY6pE|CSfXN:Ql{v%:[ 4 4   */2/9/9/99??3/9910+'7!5!4'&'7LJKNH‘Tv>+Q[3M%:6 q=%F'n@ # & &@  #)# /9/]99?2/2/2/99910]#"'&'#"&5467&&5476733'32FH7)\3s  !Wd"81<%{\8>VND"*"$>t>DhmC7 Zp(5C@: 4:-=2-#4##--2 A @=:2)# 40##)00 )@ :@ 4:: 6E /3/9/+9/9/9+99999??9/2/3/+9/999+10#"'&'##53267&'&54677667&54767%4'&#"6764'&'326Z$'')pgGt5C[ZZ)LA c!E,@a{G^..Pz+8#3)%<=2 :GM40.B #/S7=ts+=+)C#J/51Umo)4&"."" 22@ *. &. &. * **6/9/9/9/3/999?<3/3/9910!#"'&57#536767632!%4#"6764'&'326m@-9@xdx#*5:C;/.(+<5[>H(t_\5@#%7EQN/;SdH]Pe@Jl=X7!C_^-i&,OI<nGVxc *u@ 4@ 4@ 4  %%!  (( !, 4 /+39/?2/?2/910+++#"'&'&'73276767"'&547632&'&#"zBF3RAA8{1zmUU+OCL08VW&?')Xa # >1]/j+1pgXfeO`% %13xc25j62V;?Cչ&@4)44*4 4<>?==@BCA!' A 9' 4 0=?<>>ACB@@$3 @ ,$,@E! 4 $ 9/2/+3/3/99/9/993/99??+??99?993/9910+++&&#"332!"'&54767673276654&##"&54767632'7'7 #a2W`X+5PHE`^f".<*?Cx+B71Cs}TePߐVTjN6:>33 @ 4:44 4,./4,,"@ >79::88;=>>< 4<58:799<>=0;;;/& / @@  4 9/2/+9/9/9/]993/99?2/9?+]993/]993/]9/+9/+10]+++q#"32!"'&54767327654&#&&#"&54767633'7'7])0Q0{@b(&%9zՏm#s?6I+Q[3MDVTr:@DNe0@TVJOce@?4ee_c[WZ?4ZZS_WWc@'SS.<;K.7 4H7#K##@ 4##.KK?.@K@eeOZOZ[[#*7HK@@ ??<<;;  @ 4*E@ @ 4 @ 4 g@**/]3/++9/9/+2/3/93/3/9999993/33//3/???9/9/+]99+99993/3/9/+99/+910]'#656767&'&'&'&#"#"'&'&&5476326765'4674&'276#"'&#"'676323270;"%P&jruF #T!  /)-$ )NEUKIf-/C9,Kw:v2U)02-c   & d2!54F[~F(?A%4# LA[7<+#,'9.=+>#5NFreuJ^x!Bk,+$+/6'f$  ! $  @ >UH44ֳ4)ֳ 4(@ 4[+"@% 4+* 4*J 4)T 4(@ 4?SU@?4UUOSKGJ?4JJCOGGS@CC @ 4  0@ 4>03'&&>@ UU?J??JKK  4@ 4 7- 0033-77W&&/3/2/3/]99/+]+3992/33//3/?3/??9/+9/9/+92/3/9/+99/+910+++++]+++++&'&#"#"'&'&5432#"'&54&5!5$767654&'76733#"'&#"'67632327'8nzF:I,;)HtT3=`KY n!$)02-c   & d2!540}4#,:NX?[eW[n6ct& Q;^{bYT1"sc~6$ ! $  & DNn@Q@, 4TVJ<;K.7 4H7#K##@ 4##.K?K. 4..T?OdfVlTT4Tllf^@ 4^K@ dVaaiOOiTTZ@@ii#*7HK@@ ??<<;;  @ 4*E@ @ 4 @ 4 p@**;/]3/++9/9/+2/3/93/3/9999993/2/3/9/99??+2/3+/999?3/+9/9/+]99+999910]+'#656767&'&'&'&#"#"'&'&&5476326765'4674&'27647&'&547632&#"3260;"%P&jruF #T!  /)-$ )NEUKIf-/C9,Kw:v2U4*d5;- $+]!F[~F(?A%4# LA[7<+#,'9.=+>#5NFreuJ^x!Bk,+$+/6'f$  @.#8> 40  >^RA 4)ֳ 4(@ 4[+"@/ 4+* 4*J 4)T 4(@ 4  @ 4 @ 4> >03'&&>4@ 4DT?VF\DD4D\\VN@ 4N@ TFQQY??YDDJYY  4@ 4 7- 0033-77`&&;/3/2/3/]99/+]+3992/2/3/9/99?+2/3+/9993/++?3/?9/9/+9/+]910+++++]]+++&'&#"#"'&'&5432#"'&54&5!5$767654&'7673347&'&547632&#"326'8nzF:I,;)HtT3=`KY n!$=*d5;- $+]!0}4#,:NX?[eW[n6ct& Q;^{bYT1"sc~6$ @.#8> 4SDNn@Q@ 4TVJdOfVlT^@ffl@4ll@TTT@* 4TT<;K.7 4H7#K##@ 4##.KK?.K@ dVaaiOOiTTZ@@ii#*7HK@@ ??<<;;  @ 4*E@ @ 4 @ 4 p@**;/]3/++9/9/+2/3/93/3/9999993/2/3/9/99???9/9/+]99+99993/+]3/+3/99910]+'#656767&'&'&'&#"#"'&'&&5476326765'4674&'27647&'&547632&#"3260;"%P&jruF #T!  /)-$ )NEUKIf-/C9,Kw:v2U*d5;- $+]!F[~F(?A%4# LA[7<+#,'9.=+>#5NFreuJ^x!Bk,+$+/6'f$ P @.#8> 4A >^_A 444ֳ4)ֳ 4(@ 4[+"@ 4+* 4*J 4)T 4(@ 4T?VF\DN@ VV\@4\\D4D@ 4DD& @ 4  0@ 4>03'&&>@ TFQQY??YDDJYY-&  4@ 4 7- 0033-77`&&;/3/2/3/]99/+]+3999/2/3/9/99?3/??9/+9/9/+93/++3/+3/99910+++++]++++++&'&#"#"'&'&5432#"'&54&5!5$767654&'7673347&'&547632&#"326'8nzF:I,;)HtT3=`KY n!$*d5;- $+]!0}4#,:NX?[eW[n6ct& Q;^{bYT1"sc~6$ @.#8> 4SDN@)TVJ<;K.7 4H7#K##@ 4##.KK?.@K@ #*7HK@@ ??<<;;  @ 4*E@ @ 4 @ 4 P@**/]3/++9/9/+2/3/93/3/999999???9/9/+]99+999910]'#656767&'&'&'&#"#"'&'&&5476326765'4674&'2760;"%P&jruF #T!  /)-$ )NEUKIf-/C9,Kw:v2UF[~F(?A%4# LA[7<+#,'9.=+>#5NFreuJ^x!Bk,+$+/6'f$ A >44ֳ4)ֳ 4(@ 4[+"@- 4+* 4*J 4)T 4(@ 4 @ 4  0@ 4>03'&&>  4@ 4 7- 0033-77@&&/3/2/3/]99/+]+399?3/??9/+9/9/+910+++++]+++++&'&#"#"'&'&5432#"'&54&5!5$767654&'76733'8nzF:I,;)HtT3=`KY n!$0}4#,:NX?[eW[n6ct& Q;^{bYT1"sc~6$!!%!! @ !!%!! @ Fb1F=!!%!! @ !!%!! @ !!%!! @ FQ F!!%!! @ !!%!! @ HFZ!!%!! @ !!%!! @ !!%!! @ FIFWFKF=H@.J0wG!!%!! @ FF[!!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ >@ 4 /3/9/?2/+?10#4'&'&54632#"&54632+9 %F79IH42HH42HCv~:~-=]\72HH23JJ"  /?10#"&54632O76LM58N6ON76ONW *  /3/?2/10#"&54632#"&54632N85LJ78NO75LK68N8NN87NN6ON76ON!!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ !!%!! @ %F/?10!5!FF%%F/?10!5!FF%%:/?10!5!::%c, 4'@4' 4 4 4 4@F 4(  % (,,&U# U U U U8U&U U޴ U U U UҴU@ 4&! U !!c-]+/]++++++++3/++++++9/99???9/910+++++++3276'&#"%53#"$576!2676'+u߃&4Ŀ;_I[%rIѥ|B[Lly[h18-VD@,@Y' 4 4 4@4 4)  % (,,& U0U U$@U U UUӴUִ U@0 U $@$%4! U! U! U! U!U!@U! U! U! U!?!!1-]++++++++++/]+++++++3/+++9/99???9/910++++]327654'&#"%53#"'&763266'YTSYZTSYB&1v䅉ۋiD;lffmʿkfelѥ|BVHA'vm*ZU%%4 4 @ 4&!@6 %% U& UD U U UDUDU& U@ U U@ U U UӴU@U& UU U U U UUU4]&+++++++++/++++++++<3/+++++++9/????9/910]++53# &53327636765$c24gs8$"}V[œFѥ> ~PRO]YcafNl*v&$ 4@S4 4    $$& U U- U U U 3%,UU@ U U@ U U U޷U%U@U U U U UU@364 N%]q++++++++/++++++++<3/+++++9//????9/9910+++53#5#"&&'&533266536765\$\|]P #S:?Uѥ>GnO6r/T9a*vE+, 4S@`/]}?10+#'3/+, 4S@`/]}?10+#'3 #S 4@ 4//@ 4S@`p/]]/+]qr+10+#3 T+A44 4SO`/]+}?10++3#+@+84 4SO`/]+}?10+3#^+s #T4@ 4//@ 4SO`/]/+]qr+10+]3##),@ 4 @4 4%4@ 794@SZ4 @   W@ 4p/]+3/93/}?}++++]qr+9910+7676'&#"'6#55*[? 'i{NVp^ ^'*Ce2p m,@* 4 @@|4@RU4@KL4@<>4@&64 @4  /3/93/+}?q+++++9/99CTX@ 4+Y10+7676'&#"'6#51'T< $b]  AZ?7,@ 4 @4 4%4@ 794@SZ4 @   W@ 4p/]+3/93/}?}++++]qr+9910+7676'&#"'6#55*[? 'i{NVp^ ^'*K]2pgm,@* 4 @@|4@RU4@KL4@<>4@&64 @4  /3/93/+}?q+++++9/99CTX@ 4+Y10+7676'&#"'6#51'T< $b]  AZ?7I;0_ 4 @7 4 4  EE   @ 4?  v v@o/]3//]+qr3/]9/]2/10+++&6323273#"'&#"q[>k;#= ?gCNIf~6W8$_|+ٳK @ 4 4@@ @^5 @OS4 @CE4 @+-4o    @a  / O _  _ o   @5 @jl4 @a5 @\]4 @WY4 @MQ4 @DI4 @:5 @144 @.B4 @',4 @%4 4  /3/}/+++++++++++++]qr3/]q++++3/10++]&6323273#"'&#"q[>k;D= a?gCCN|R[,F,Lr s 4 @ 4 4  E@4!&4E / ? /  @ 4 @6>4?  v v@o/]3//]++qr3/]9/+]2/10+++&6323273#"'&#"sq[>k;#= ?gCN f~6W8$_f= 44 @#(4 /3/?q+10++&'3327673#"'&N;@AC@;OIMp#v#%H$&9O9@4 4/++9?r910#73#ЯC{{(@k;#= ?gCNIf~6W8$_I0k 4 @A 4 4  EE O  @ 4? O  v v@P/]]q3//]+qr3/]9/]2/10+++&6323273#"'&#"q[>k;#= ?gCNIf~6W8$_IM0k 4 @A 4 4  EE O  @ 4? O  v v@P/]]q3//]+qr3/]9/]2/10+++&6323273#"'&#"q[>k;#= ?gCNIf~6W8$_ri@2 4 4 4EE    @ 4 v v4 4o/]++3//+]r3/]9/]2/10+++&763232673#"'&#"s:9Y>k;# "mT?gC"h>>6#4rr8$/Hi@2 4 4 4EE    @ 4 v v4 4o/]++3//+]r3/]9/]2/10+++&763232673#"'&#":9Y>k;# "mT?gC"h>>6#4rr8$/ji@2 4 4 4EE    @ 4 v v4 4o/]++3//+]r3/]9/]2/10+++&763232673#"'&#"k:9Y>k;# "mT?gC"h>>6#4rr8$/}}J}{}}e} b#S 4@ 4//@ 4S@`p/]]/+]qr+10+#3  #T4@ 4//@ 4SO`/]/+]qr+10+]3##`i@2 4 4 4EE    @ 4 v v4 4o/]++3//+]r3/]9/]2/10+++&763232673#"'&#":9Y>k;# "mT?gC"h>>6#4rr8$/}_,}]vC}t}}l9}jX%}V]}},}*|+nK @ 4 4@@ @^5 @OS4 @CE4 @+-4o       /3/}?3/]q++++3/10++]46323273#"'&#"p[>k;D= a?gC@Q|R[,F,LI0k 4 @A 4 4  EE O  @ 4? O  v v@P/]]q3//]+qr3/]9/]2/10+++&6323273#"'&#"q[>k;#= ?gCNIf~6W8$_|4+nK @ 4 4@@ @^5 @OS4 @CE4 @+-4o       /3/}?3/]q++++3/10++]&6323273#"'&#"q[>k;D= a?gCCN|R[,F,LI40k 4 @A 4 4  EE O  @ 4? O  v v@P/]]q3//]+qr3/]9/]2/10+++&6323273#"'&#"q[>k;#= ?gCNIf~6W8$_<&@@Op  % U U U@ U U U@ U /]+++++++??10]rq33&Y&$}4 5<44A+++5J>&D}@ 99:/7A+]5Y,&$t@ ##"A+]5J &D4:LUL@ULpLLPL`LLLLLLʱH++]qr++5Y+&$'|q0@*4H+A@(4/+5+5++]q5J#&D'KZ_BB@=4B;H+: :0:p::::::::@.24:=A>/>>_>>@ 4>/+]qr5++]qr5++]5Y+&$'|n'@H+A@(4/+5+5+]q5J#&D'-Y@E?@&34?@4?<H+: :0:p::::::::@.24:=A>/>>_>>@ 4>/+]qr5++]qr5+++5Y,&$'|u1)@4)))(AA@(4/+5+5+]q+5J,&D'tHb@ SOSSS@>4SR;/>>_>>@ 4>/+]qr5++]qr5++]q5Y+&$'|<0@"@ 4@4 AA@(4/+5+5+]++5J&D'ztT@A?O??I:=A: :0:p::::::::@.24:=A>/>>_>>@ 4>/+]qr5++]qr5+]5Yh&$'|}455<44@AA@ (4/+5+5+++5J&D'}C@0@@A/7A: :0:p::::::::@.24:=A>")+++]qr5+]5Y+&$'{q4#AB4#@95##H+A @-4 /+5+5+q++5J#&D'H7@ `HpHH[HH@4HCH+<<h+<")++]5++]q5Y+&$'{n\ @-4 /+5CTX@T##AA+5+5@#@894#@)14#@ 4@#o####@ H+A+5+q+++5YJ#&D'\*IPIIC@H+<<h+<")++]5+]5Y,&$'{u;@ 6666*246@!(465AA @-4 /+5+5+++r5J,&D't\B@0PZ`ZZZZZ0ZpZZZZZZZYA<<h+<")++]5+]qr5Y+&$'{P,@###/##-AA @-4 /+5+5+]q5J&D'z+F@ 4FP?9A<<h+<")++]5++5Yf&$'{}45$5<4$4@$%AA @ -4 /+5+5+++5J&D'}&@GGH/7A<<h+<")++]5+]5&(}\@    A+]5K>&H}P`ش A+]5,&(t A+5K &H*@2222221 A+]q5&(|j@  A !)++5K&H@ * A)++5+&('|q0@*4H+A@(4/+5+5++]q5K#&H'LK_((@/4(!H+ @;5 @-24  # A /  _  @ 4 /+]qr5+r++5++]5+&('|n4@%@:5H+A@(4/+5+5+]qr+5K#&H'.Q@=%@U%@&34%@4%"H+ @;5 @-24  # A /  _  @ 4 /+]qr5+r++5++++5,&('|u1&@ 4&&&%AA@(4/+5+5+]q+5K,&H'tHQ@ O9999@0498!"A @;5 @-24  # A /  _  @ 4 /+]qr5+r++5++]5+&('|P$@AA@(4/+5+5+q5K&H'ztE@3%O%%/ #A @;5 @-24  # A /  _  @ 4 /+]qr5+r++5+]5h&('|}\$@  AA@ (4/+5+5+]5K&H'}9P&`&@&'A @;5 @-24  # A$")++r++5+]5c,&,t:@ UA++5 &CTXA+O"H++qY5&,} A+5|I&L}z@ @mo4O  A+q+5c&2}  A+5D'>&R}  A+5c,&2t8@p00000/A+]q5D' &R*@....-A+]q5c+&2'|qn0&&&@*4&H+!A@(4/+5+5++]q5D'#&R'MD_$$@)4$H+@.24A/_@ 4/+]qr5+r+5++]5c+&2'|n@4@%#@:5###### H+!A@(4/+5+5+]qr+5D'#&R'/C@1!@&34!@4!H+@.24A/_@ 4/+]qr5+r+5+++5c,&2'|u`16@ 46665!A!A@(4/+5+5+]q+5D',&R'tHL@ O55555@*454A@.24A/_@ 4/+]qr5+r+5++]5c+&2'| @#-!A!A@(4/+5+5+5D'&R'zt>@-!O!!+A@.24A/_@ 4/+]qr5+r+5+]5ch&2'|} @$% A!A@ (4/+5+5+5D'&R'})@"# A@.24A ")++r+5+5c,&jj@0o000%H+-!)++]q5D&k!@0O0_000%1H+-")++]q5c,&jCj @ ...%H+-!)++]q5D&kC!@_.o. .0..%H+-")++]q5cE&jt8@PAAAAAA@%%A+]q5D &k*@AAAAA@%%A+]q5c&jQ@ -9%%A-!)++5D&k@ -9%%A-")++5c&j}@ ../A+q5D@&k} ./A+5"&8}p@ OA+q5&&X}@P`p A+]5",&8t@ % A+]5 &X2@P------P-`-p-----@ 4-, A++]q5,&lj)'@95p'/'_'''H+&!)++]r+5&m@O(((E4@.34@$)4/@4@4@ 4/+]+]+q+++++]<++</<<10!5!#53#53u4 4@% 4@ 4?@ 4 @#%4@4 @9 4@4@Os4@>E4@.:4@$%4/@4@4@ 4/+]+]+q+r+++++<++</+]+++9910#7#53#53炇燇44  0444@#%4@ 4 @144 d4 @#%4@ 4@4@ 4? @ 4 @#%4@4@+,4 @: 4@4@Os4@>E4@.:4@$%4/@4@4@ 4/+]+]+q+r++++<+9+<++</+]++++++++99++910#53'#'37#53QȮؓɱbb4 @ @ 4 @ 4@ 4? @#%4@4 @9 4@4@Os4@>E4@.:4@$%4/@4@4@ 4/+]+]+q+r+++++<++</]+++9910#53'#'3#53`ؓU Z@  UU U@ U]  ??9/++++9/10!!!##53!Uo¤ e & b@ % U@U U UN +@ U+  ??9/+++++9/10!3###53!Q||ci[F@_817$G$E )9$&& ) )   EDEEDBDE1// ?=??=?=+6 E+ U U U @3U &/1$,76*?= *DF,B) *EF ??9/99999999/++++99+}99+}99+}99+}10]]]]]##&'&##"7#67&'&'&&56323276767632"&#"3[E].Z|`IBj .d:$6?\WN e])>M$DǖF%L>']_ 3 g9 36#:dki.ZR2-n')T3R<(M~O*;G&3S+'P&B1@;#h$&& U& U&%) U%)  0//@U/%;9;;9;9,5%BA@ U%A?A??>,A, % U @ U  U @; U U 9;5+0$&/,4*+*?A,>)+ * BA+ ??9/999999/+++++99++}99++}99++}99+++}10]]##&'&##"#67&'&'&&#"532332767633'&3P"0"5IJ4 1ovZ-808 (j)9.)91cd0q%:vB1L '%&NuomI-IQ 10SI)L3 K bB5A'=)c_$2$i'@%@/ U U &$&&$g$&$#'  7   '@ U')  U U U U U U @#U ](   $&#  & ??9/9999999++++++++99]+}9]+++}10]]]]##&'&##3276767632"&#"3E\,ZwF%J>']p 4 g9 37"9eki.\R~R+;G'1S)'v&&@ U%%#%%#F#"#%&@U% %&@ U &&( % U @U  U  U U U U @. U U  N'+  #%" + %+ ??9/9999999]+++++++++]+99++}9]++}10##&'&##327676767633'&3v/#5Id0:(,:+_$2K '%&Muom>-IQ 1&5A` I( d^%2$+$&&$&@8 U& IYi$$* U **) U@U U - U U U U U U @1U  ],&$ ! *)       ??99//99/999999]+++++++]9/+++29++}99]]++}]10!#&'#&##3273676767632"&#":/x3EG1x&/76NHYp 4 g9 37"9e_<R~An*X,(G'1S)'&(4i#!#@J U#%!!!!!'U%''& U * % U @U  U  U U U @; U U 0  N)#! + '&  +     ??99//99/999999]++++++++rr9/+29++}99]]r++}ıCTX@ -"=2]Y10]!#&'#&##3273676767633'&c#+-!c(,:+_$2K ')")6jpI7&5 D+9` I( dh(0i@   U UU@ U U@ U U   UU U U U@U]  ??9/+++++++++++++10##!#3!33†iMZW&@, %%@ U U U U U UU@ UU@ U U" UߴU U@ U %UU@U U U@ U U N + +??9/]++++++++++++++++++++++10##!#3!33W t-)&Fnm U @: U U    U U o UU@ U U U@U  &6??9/]9/++++++]+++}ć+}+++10#367m$ "09rHUE9ji& ֹ @ U U U @=U U  U %  U U%%UU@U U U U@U  $4Dt /?]?9/+++++++݇+++}ć++}+++++10#367nm.1&i&wmgmѹ U@HU U U    U  U    UU@ U UU@ U   ??9/9/++++++39Ƈ+++}9+++}9++10!!#!5!367mkUdaUj"099_UE9ji&@& F v &Fv@ U U U@GU U U U%  U U %  % U U @U U U @ U   + /??9/++++++Ƈ+++}ć++}++++++10]]!!#!5!367nBCm.1&ڄ&wmg iI@ UiDtI   U U@ U  UCTX  @ 4 4    ?Vw=I^M&@&F&FX&F @ U( U @( U  U U    @ U %%@ U U U0@ U%_o  U @ U   + /??9/]++333]]++}]]+++++}+++++10]]]]###367733I* #.$g-](@74A bW8@dEU6@ U U@ UUU@ U U@ U U U@ U UU U@- U U  UU U U U@U U U@! U]    ??99//3332229/]+++++++++++++++++++9/++++++10]]]!###"'&'&53733673¢xt,(±y xO< >FyocG>E&@te U U U U@ UU%@U U U U U@ UUU %@UU U@: U U UUUO_+ ??99//333229/]++++++++]]++++++++9/++++++10]]!##5#"'&'&533673ndcY^d$! ?,;cW{" 7;bYkt+T/! )@g[J U U Uд U U UU@U U U U U U U @U ]   ??9/32+++++++++++++++10]]]!#4'&#"#3$328Gċs,'\s[7a>Ezm&@ zh%U@ U UUU U@ U 0 % @ U  U U U @ U  U  N +  ??9/32]++++++]+++++++10]]]!#54'&'&#"#3632A:Zfo\c%!x(S0+6&T46:dYkc!@5 m \  J bUDw9Ivj   &U U U U@& U\#&& c"/   ??99//]3]+++++10]]]]]]]]]]]]]]]! '&5!&'&# '67632!32u u|S8ȟRGL T^~2pkbcU(> @-8HUey\lJ ( 8 l[cU $U U UU@G U"$$ U  U  U ? O  4!+    ??99//]3]]++++++++210]]]]]]]]]]]#"'&547!&'&#"'!2!3276({w LVN]v 8VSO `mWChXT`#@8Y""VuTFVy\IYx Y&@ UU U U U@/ U\%&  U  c$@U@ U   ??9/++]+++++++10]]]]]]]]]]]]]]]]!"'&'&576! &'&#"!3276ڹϧOJMEuאvwۆ~gjTۃxϋD'>!@D\ l ScdU7G[kH9iXf fUZj$#@ U#@ U@U U U U UU@/ U7#$U U U U U U@,UU U?O4"+  ??9/]]++++++++++++++++++10]]]]]]]]]]]]]]#"'&57632&'&#"!3276'u{놀BYYBjITSH"A'vJeeJano`'(  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !.nullnonmarkingreturnmu1pi1OhmEurodmacron overscoremiddotAbreveabreveAogonekaogonekDcarondcaronDslashEogonekeogonekEcaronecaronLacutelacuteLcaronlcaronLdotldotNacutenacuteNcaronncaron Odblacute odblacuteRacuteracuteRcaronrcaronSacutesacuteTcedillatcedillaTcarontcaronUringuring Udblacute udblacuteZacutezacuteZdotzdotGammaThetaPhialphadeltaepsilonsigmatauphi underscoredbl exclamdbl nsuperiorpeseta arrowleftarrowup arrowright arrowdown arrowboth arrowupdn arrowupdnbse orthogonal intersection equivalencehouse revlogicalnot integraltp integralbtSF100000SF110000SF010000SF030000SF020000SF040000SF080000SF090000SF060000SF070000SF050000SF430000SF240000SF510000SF520000SF390000SF220000SF210000SF250000SF500000SF490000SF380000SF280000SF270000SF260000SF360000SF370000SF420000SF190000SF200000SF230000SF470000SF480000SF410000SF450000SF460000SF400000SF540000SF530000SF440000upblockdnblockblocklfblockrtblockltshadeshadedkshade filledbox filledrecttriaguptriagrttriagdntriaglfcircle invbullet invcircle smileface invsmilefacesunfemalemalespadeclubheartdiamond musicalnotemusicalnotedblIJij napostropheminutesecond afii61248 afii61289H22073H18543H18551H18533 openbulletAmacronamacron Ccircumflex ccircumflexCdotcdotEmacronemacronEbreveebreveEdotedot Gcircumflex gcircumflexGdotgdotGcedillagcedilla Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonek Jcircumflex jcircumflexKcedillakcedilla kgreenlandicLcedillalcedillaNcedillancedillaEngengOmacronomacronObreveobreveRcedillarcedilla Scircumflex scircumflexTbartbarUtildeutildeUmacronumacronUbreveubreveUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexlongs Aringacute aringacuteAEacuteaeacute Oslashacute oslashacute anoteleiaWgravewgraveWacutewacute Wdieresis wdieresisYgraveygrave quotereversed radicalex afii08941 estimated oneeighth threeeighths fiveeighths seveneighths commaaccentundercommaaccenttonos dieresistonos Alphatonos EpsilontonosEtatonos Iotatonos Omicrontonos Upsilontonos OmegatonosiotadieresistonosAlphaBetaDeltaEpsilonZetaEtaIotaKappaLambdaMuNuXiOmicronPiRhoSigmaTauUpsilonChiPsi IotadieresisUpsilondieresis alphatonos epsilontonosetatonos iotatonosupsilondieresistonosbetagammazetaetathetaiotakappalambdanuxiomicronrhosigma1upsilonchipsiomega iotadieresisupsilondieresis omicrontonos upsilontonos omegatonos afii10023 afii10051 afii10052 afii10053 afii10054 afii10055 afii10056 afii10057 afii10058 afii10059 afii10060 afii10061 afii10062 afii10145 afii10017 afii10018 afii10019 afii10020 afii10021 afii10022 afii10024 afii10025 afii10026 afii10027 afii10028 afii10029 afii10030 afii10031 afii10032 afii10033 afii10034 afii10035 afii10036 afii10037 afii10038 afii10039 afii10040 afii10041 afii10042 afii10043 afii10044 afii10045 afii10046 afii10047 afii10048 afii10049 afii10065 afii10066 afii10067 afii10068 afii10069 afii10070 afii10072 afii10073 afii10074 afii10075 afii10076 afii10077 afii10078 afii10079 afii10080 afii10081 afii10082 afii10083 afii10084 afii10085 afii10086 afii10087 afii10088 afii10089 afii10090 afii10091 afii10092 afii10093 afii10094 afii10095 afii10096 afii10097 afii10071 afii10099 afii10100 afii10101 afii10102 afii10103 afii10104 afii10105 afii10106 afii10107 afii10108 afii10109 afii10110 afii10193 afii10050 afii10098 afii00208 afii61352sheva hatafsegol hatafpatah hatafqamatshiriqtseresegolpatahqamatsholamqubutsdageshmetegmaqafrafepaseqshindotsindotsofpasuqalefbetgimeldalethevavzayinhettetyodfinalkafkaflamedfinalmemmemfinalnunnunsamekhayinfinalpepe finaltsaditsadiqofreshshintav doublevavvavyod doubleyodgeresh gershayim newsheqelsign vavshindot finalkafshevafinalkafqamats lamedholamlamedholamdageshaltayin shinshindot shinsindotshindageshshindotshindageshsindot alefpatah alefqamats alefmapiq betdagesh gimeldagesh daletdageshhedagesh vavdagesh zayindagesh tetdagesh yoddageshfinalkafdagesh kafdagesh lameddagesh memdagesh nundagesh samekhdagesh finalpedageshpedagesh tsadidagesh qofdagesh reshdagesh shindageshtavdagesvavholambetrafekafrafeperafe aleflamedzerowidthnonjoinerzerowidthjoinerlefttorightmarkrighttoleftmark afii57388 afii57403 afii57407 afii57409 afii57440 afii57451 afii57452 afii57453 afii57454 afii57455 afii57456 afii57457 afii57458 afii57392 afii57393 afii57394 afii57395 afii57396 afii57397 afii57398 afii57399 afii57400 afii57401 afii57381 afii57461 afii63167 afii57459 afii57543 afii57534 afii57494 afii62843 afii62844 afii62845 afii64240 afii64241 afii63954 afii57382 afii64242 afii62881 afii57504 afii57369 afii57370 afii57371 afii57372 afii57373 afii57374 afii57375 afii57391 afii57471 afii57460 afii52258 afii57506 afii62958 afii62956 afii52957 afii57505 afii62889 afii62887 afii62888 afii57507 afii62961 afii62959 afii62960 afii57508 afii62962 afii57567 afii62964 afii52305 afii52306 afii57509 afii62967 afii62965 afii62966 afii57555 afii52364 afii63753 afii63754 afii63759 afii63763 afii63795 afii62891 afii63808 afii62938 afii63810 afii62942 afii62947 afii63813 afii63823 afii63824 afii63833 afii63844 afii62882 afii62883 afii62884 afii62885 afii62886 afii63846 afii63849uni202Auni202Buni202Duni202Euni202Cuni206Euni206F;uni206Auni206Buni206C;uni206DuniF00AuniF00BuniF00CuniF00DuniF00EuniFFFC afii63904 afii63905 afii63906 afii63908 afii63910 afii63912 afii62927 afii63941 afii62939 afii63943 afii62943 afii62946 afii63946 afii62951 afii63948 afii62953 afii63950 afii63951 afii63952 afii63953 afii63956 afii63958 afii63959 afii63960 afii63961 afii64046 afii64058 afii64059 afii64060 afii64061 afii62945 afii64184 afii52399 afii52400 afii62753 afii57411 afii62754 afii57412 afii62755 afii57413 afii62756 afii57414 afii62759 afii62757 afii62758 afii57415 afii62760 afii57416 afii62763 afii62761 afii62762 afii57417 afii62764 afii57418 afii62767 afii62765 afii62766 afii57419 afii62770 afii62768 afii62769 afii57420 afii62773 afii62771 afii62772 afii57421 afii62776 afii62774 afii62775 afii57422 afii62779 afii62777 afii62778 afii57423 afii62780 afii57424 afii62781 afii57425 afii62782 afii57426 afii62783 afii57427 afii62786 afii62784 afii62785 afii57428 afii62789 afii62787 afii62788 afii57429 afii62792 afii62790 afii62791 afii57430 afii62795 afii62793 afii62794 afii57431 afii62798 afii62796 afii62797 afii57432 afii62801 afii62799 afii62800 afii57433 afii62804 afii62802 afii62803 afii57434 afii62807 afii62805 afii62806 afii57441 afii62810 afii62808 afii62809 afii57442 afii62813 afii62811 afii62812 afii57443 afii62816 afii57410 afii62815 afii57444 afii62819 afii62817 afii62818 afii57445 afii62822 afii62820 afii62821 afii57446 afii62825 afii62823 afii62824 afii57447 afii62828 afii57470 afii62827 afii57448 afii62829 afii57449 afii62830 afii57450 afii62833 afii62831 afii62832 afii62834 afii62835 afii62836 afii62837 afii62838 afii62839 afii62840 afii62841 glyph1021 afii57543-2 afii57454-2 afii57451-2 glyph1025 glyph1026 afii57471-2 afii57458-2 afii57457-2 afii57494-2 afii57459-2 afii57455-2 afii57452-2 glyph1034 glyph1035 glyph1036 afii62884-2 afii62881-2 afii62886-2 afii62883-2 afii62885-2 afii62882-2 afii57504-2 afii57456-2 afii57453-2 glyph1046 glyph1047 afii57543-3 afii57454-3 afii57451-3 glyph1051 glyph1052 afii57471-3 afii57458-3 afii57457-3 afii57494-3 afii57459-3 afii57455-3 afii57452-3 glyph1060 glyph1061 glyph1062 afii62884-3 afii62881-3 afii62886-3 afii62883-3 afii62885-3 afii62882-3 afii57504-3 afii57456-3 afii57453-3 glyph1072 glyph1073 afii57543-4 afii57454-4 afii57451-4 glyph1077 glyph1078 afii57471-4 afii57458-4 afii57457-4 afii57494-4 afii57459-4 afii57455-4 afii57452-4 glyph1086 glyph1087 glyph1088 afii62884-4 afii62881-4 afii62886-4 afii62883-4 afii62885-4 afii62882-4 afii57504-4 afii57456-4 afii57453-4 glyph1098 glyph1099 glyph1100 glyph1101 glyph1102 glyph1103 glyph1104 glyph1105 glyph1106 glyph1107 glyph1108 glyph1109 glyph1110 glyph1111 glyph1112 glyph1113 glyph1114 glyph1115 glyph1116 glyph1117 glyph1118 glyph1119 glyph1120 glyph1121 glyph1122 glyph1123 glyph1124 glyph1125 glyph1126 afii57440-2 afii57440-3 afii57440-4OhornohornUhornuhornf006f007f009combininghookabovef010f013f011f01cf015combiningtildeaccentf02cdongsignonethird twothirdsf008f00ff012f014f016f017f018f019f01af01bf01ef01ff020f021f022combininggraveaccentcombiningacuteaccentf01dcombiningdotbelowf023f029f02af02bf024f025f026f027f028f02df02ef02ff030f031 Adotbelow adotbelow Ahookabove ahookaboveAcircumflexacuteacircumflexacuteAcircumflexgraveacircumflexgraveAcircumflexhookaboveacircumflexhookaboveAcircumflextildeacircumflextildeAcircumflexdotbelowacircumflexdotbelow Abreveacute abreveacute Abrevegrave abrevegraveAbrevehookaboveabrevehookabove Abrevetilde abrevetildeAbrevedotbelowabrevedotbelow Edotbelow edotbelow Ehookabove ehookaboveEtildeetildeEcircumflexacuteecircumflexacuteEcircumflexgraveecircumflexgraveEcircumflexhookaboveecircumflexhookaboveEcircumflextildeecircumflextildeEcircumflexdotbelowecircumflexdotbelow Ihookabove ihookabove Idotbelow idotbelow Odotbelow odotbelow Ohookabove ohookaboveOcircumflexacuteocircumflexacuteOcircumflexgraveocircumflexgraveOcircumflexhookaboveocircumflexhookaboveOcircumflextildeocircumflextildeOcircumflexdotbelowocircumflexdotbelow Ohornacute ohornacute Ohorngrave ohorngraveOhornhookaboveohornhookabove Ohorntilde ohorntilde Ohorndotbelow ohorndotbelow Udotbelow udotbelow Uhookabove uhookabove Uhornacute uhornacute Uhorngrave uhorngraveUhornhookaboveuhornhookabove Uhorntilde uhorntilde Uhorndotbelow uhorndotbelow Ydotbelow ydotbelow Yhookabove yhookaboveYtildeytildeuni01CDuni01CEuni01CFuni01D0uni01D1uni01D2uni01D3uni01D4uni01D5uni01D6uni01D7uni01D8uni01D9uni01DAuni01DBuni01DCuni0492uni0493uni0496uni0497uni049auni049buni049cuni049duni04a2uni04a3uni04aeuni04afuni04b0uni04b1uni04b2uni04b3uni04b8uni04b9uni04bauni04bbuni018funi0259uni04e8uni04e9\ N$7<  h$$7h$9h$:$D:A:E-:H:I:K:L`:M:N:Q`:W:Z:l:m:n:w-;:;A;H;K;L;M;N;O;Q;T;W;Y;e;m<:<><@<A<E<H<K<Lw<M<N<O<Q<T<Y<^<f<l<m<o<q<y===w=w==:w=>w=A=E=F=H=K=Y=Z=\=^w=_w=b=e=f=g=hw=j=mw=u=v=x=yw>M>N>Q>aD>h>m-?A?k@A@H@K@L@M-@T-@Z@_@h@mAEAHAKALAMANAQAYDADHDKDMDNENE[EmFNFQFZF_FhFkFmFqFwH:H>H@HEHMHOHQHYH^HeHoJ}J}JJJJ:wJ>wJ@JAJEJFJHJKJLJMJNJOJYJZJ^`J_JhJwJyK:K>KAKEKFKHKLKMKOKQKTKWKZK`-KqLLLLLL:L>L@LALELHLNLYLZL\L_LbLdLeLfLh`LiLjLkLmLoLsLuLvLxLyMMMMMMMM:wM>MAMEMHMNMWMYM[M\M]M^`M_wM`MaMbMcMdMewMfMgMhwMiMjMkwMoMpMrMsMxMywN:N>NENLNMNQNYNeOAOHOKONOWOhOmPHPZ-SZSm-TwTYV`V:V>V@VAVEVFVHVKVL3VOVQ`VWVYW>W@WAWEWOWYW^W`WeWfWyX:X>X@XEXHXKXLXOXQX^XeXfZaZlZmZq[Z[^[_[`[a[e[f[k[m[n[o[q[t[w[y\Z\[\^\_\`\a\e\f\h\k\l\m\n\q\t\y]]]Z]^]_]a]e]h]k]y^t^w_[_^_`_a_e_l_m_o_q`[`m`q`t-a[a^a_aaaeahakamanaqatdZ-d[-d_dadedhdkdldmdweheqf[fafmh^h`hahehlhmhohqj^jajejljmjojqjyk`khkqkwlllZl^l_l`Dlelhlklmm3m3mmZm[m^m_m`memfmhmjmkmnmwmyn[n^nenlnmnqnyoZo[o_oaohokolonoqp_paphpks_shsmvl`vqww^w_wawewhwlwowyx^x`xexfxlxoxq33``.13 "&+M"9&@M Arial ?ARLR00@   "'6GK|}  LNgi $Xarabinitmedi fina&liga, >>!)/3'-15>"*04'-15`- (,.26-'+-15 X 6  & : &,GHIJKarab ghiB:06 *H '0#10 *H 0` +7R0P0, +7<<<Obsolete>>>0 0 *H ytTA(&Xꠂ800%J8Y]s_]ܣ0  *H 010U VeriSign Trust Network10U VeriSign, Inc.1,0*U #VeriSign Time Stamping Service Root1402U +NO LIABILITY ACCEPTED, (c)97 VeriSign, Inc.0 970512000000Z 040107235959Z010U VeriSign Trust Network10U VeriSign, Inc.1,0*U #VeriSign Time Stamping Service Root1402U +NO LIABILITY ACCEPTED, (c)97 VeriSign, Inc.00  *H 0. h|,-.  WSu3* [4 Z%}XsjxqX)X^-bXq"X/6MJ;"V~!lJGj6 -Ӵ90  *H aU>{ǒ~"Գ+[D x~rȲ㉔LNaﳤF=P4 pV*cyis.(]  γ(y)gBHaSs?OUcc00kzm\obOC0  *H 010U VeriSign Trust Network10U VeriSign, Inc.1,0*U #VeriSign Time Stamping Service Root1402U +NO LIABILITY ACCEPTED, (c)97 VeriSign, Inc.0 010228000000Z 040106235959Z010U VeriSign, Inc.10U VeriSign Trust Network1;09U 2Terms of use at https://www.verisign.com/rpa (c)011'0%UVeriSign Time Stamping Service0"0  *H 0 za벧c+aހ='9)fHOO^/Ǒ{!NXc-)pP햻@۾%BU狙1L$*MhaXr0HO/oc ىʂ{K(Łh@F:?6LTBZze{GT=3*^:.uk=`BO[?"1s+FLmP.K*xt=,G100@+40200+0$http://ocsp.verisign.com/ocsp/status0 U00DU =0;09 `HE0*0(+https://www.verisign.com/rpa0U% 0 +0 U0  *H -Oc`,$R 볼g#F M|z 02h2;'{>! Ř@W%误j;#)]@US6:9ess2үc@0  *H 0p1+0)U "Copyright (c) 1997 Microsoft Corp.10U Microsoft Corporation1!0UMicrosoft Root Authority0 970110070000Z 201231070000Z0p1+0)U "Copyright (c) 1997 Microsoft Corp.10U Microsoft Corporation1!0UMicrosoft Root Authority0"0  *H 0 p;N(x^0ꢩ%_L >|Q`2kBdyvT뜆fkzb#<Ŀ-fh&:, X&F >8,(9IBlUa|`-wL陴d;P1$+=c`Xe7RӿUE:TNzmtN̖ (!W`i7Kc@0  *H  5$w\`2 >:!W,Gb;;Z6Ti$m?̪|1=pjOiCZ Ob{+7%-e%cT!RnC2gl QRǽ0 1 )M[WeIRT(~ū7,zwvj?6A5jj5EZ38nM b T?FUp:uҠ00s a* 0  *H 01 0 UUS10U Washington10URedmond10U Microsoft Corporation1+0)U "Copyright (c) 2000 Microsoft Corp.1#0!UMicrosoft Code Signing PCA0 010329212726Z 020529213726Z01 0 UUS10U Washington10URedmond10U Microsoft Corporation1+0)U "Copyright (c) 2001 Microsoft Corp.10UMicrosoft Corporation00  *H 0oE1=ćNHV+cD0xrLFfbFnD;GQ^wg"{S*-"|N3va `4;I,َ.-kUnp`/@0<0U0U% 0 +0U@OE{uf50U#0)\3Y}. 4(tr0p1+0)U "Copyright (c) 1997 Microsoft Corp.10U Microsoft Corporation1!0UMicrosoft Root Authorityj Oު@0JUC0A0?=;9http://crl.microsoft.com/pki/crl/products/CodeSignPCA.crl0  *H gqMGŽik_&ӞZ'i5+} WK 00j Oު@0  *H 0p1+0)U "Copyright (c) 1997 Microsoft Corp.10U Microsoft Corporation1!0UMicrosoft Root Authority0 001210080000Z 051112080000Z01 0 UUS10U Washington10URedmond10U Microsoft Corporation1+0)U "Copyright (c) 2000 Microsoft Corp.1#0!UMicrosoft Code Signing PCA0 0  *H  0S 04:/{m7#MҌ4$T~tG2XQ)8~:G9NnT1 :mPJ&?ˏIm>U7/`̀aBITJKٓ0ZGudӻݶ Os;:MON3 :doD4J#N`)*򄚙 p{4Af\3T?=tC9泬Hzk*ba9vn>KFGO%(0$0U% 0 +0U0[pir#Q~Mˡr0p1+0)U "Copyright (c) 1997 Microsoft Corp.10U Microsoft Corporation1!0UMicrosoft Root Authority<<>c@0 +70U)\3Y}. 4(0 +7  SubCA0 UF0U00  *H EXAHwwW_Ej9Y'-M88d"B߹/*Ϸ*|Q="mD_ddĩ,ې7Javv%$VT:>Ky_I^2i:TuMd0wz0>MLQ TS ۲9nDGLTזUs2uuIdsV/ǀ]VM= L0H *H  19050010U VeriSign Trust Network10U VeriSign, Inc.1,0*U #VeriSign Time Stamping Service Root1402U +NO LIABILITY ACCEPTED, (c)97 VeriSign, Inc.zm\obOC0 *H Y0 *H  1  *H 0 *H  1 011109205623Z0 *H  18{Lf>0  *H IV5;n ͯ)y7F/PyV/Vhg Sڣ>Oݢ⸻/aUڽ Y5%8]z>/ {Ыm }cÚR #rvi(2$7 B—j j$ZicrkQо|T̫韅[v*T<]D[5_@qݭ(n)A^'3ɎsӴg#]g`\hpH4PK!tiSSLegacy/nggallery.phpnu[load_options(); $this->define_constant(); $this->define_tables(); $this->load_dependencies(); // Start this plugin once all other plugins are fully loaded. add_action( 'plugins_loaded', [ $this, 'start_plugin' ] ); add_action( 'wpmu_new_blog', [ $this, 'multisite_new_blog' ], 10, 6 ); // Add some links on the plugin page. add_filter( 'plugin_row_meta', [ $this, 'add_plugin_links' ], 10, 2 ); } public function start_plugin() { // Content Filters. add_filter( 'ngg_gallery_name', 'sanitize_title' ); // Check if we are in the admin area. if ( is_admin() ) { if ( get_option( 'ngg_init_check' ) ) { add_action( 'admin_notices', [ $this, 'output_init_check_error' ] ); } } else { $settings = \Imagely\NGG\Settings\Settings::get_instance(); if ( $settings->get( 'useMediaRSS' ) ) { add_action( 'wp_head', [ 'nggMediaRss', 'add_mrss_alternate_link' ] ); } } } public function output_init_check_error() { printf( "

    %s

    ", esc_html( get_option( 'ngg_init_check' ) ) ); } public function define_tables() { global $wpdb; $wpdb->nggpictures = $wpdb->prefix . 'ngg_pictures'; $wpdb->nggallery = $wpdb->prefix . 'ngg_gallery'; $wpdb->nggalbum = $wpdb->prefix . 'ngg_album'; } public function define_constant() { define( 'NGG_LEGACY_MOD_DIR', implode( DIRECTORY_SEPARATOR, [ rtrim( NGG_PLUGIN_DIR, '/\\' ), 'src', basename( __DIR__ ), ] ) ); define( 'NGGVERSION', NGG_PLUGIN_VERSION ); define( 'NGGFOLDER', dirname( NGG_PLUGIN_BASENAME ) ); define( 'NGGALLERY_ABSPATH', rtrim( NGG_LEGACY_MOD_DIR, '/\\' ) . DIRECTORY_SEPARATOR ); define( 'NGGALLERY_URLPATH', plugin_dir_url( __FILE__ ) ); } public function load_dependencies() { // Load global libraries. require_once __DIR__ . '/lib/core.php'; require_once __DIR__ . '/lib/ngg-db.php'; require_once __DIR__ . '/lib/image.php'; require_once __DIR__ . '/lib/tags.php'; require_once __DIR__ . '/lib/post-thumbnail.php'; require_once __DIR__ . '/lib/sitemap.php'; // Load frontend libraries. require_once __DIR__ . '/lib/shortcodes.php'; // We didn't need all stuff during a AJAX operation. if ( defined( 'DOING_AJAX' ) ) { require_once __DIR__ . '/admin/ajax.php'; } else { require_once __DIR__ . '/lib/meta.php'; require_once __DIR__ . '/lib/media-rss.php'; if ( is_admin() && ! $this->is_rest_url() ) { require_once __DIR__ . '/admin/admin.php'; require_once __DIR__ . '/admin/media-upload.php'; $this->nggAdminPanel = new nggAdminPanel(); } } } public function is_rest_url(): bool { return strpos( $_SERVER['REQUEST_URI'], 'wp-json' ) !== false; } public function load_options() { $this->options = get_option( 'ngg_options' ); } public function multisite_new_blog( $blog_id, $user_id, $domain, $path, $site_id, $meta ) { global $wpdb; include_once __DIR__ . '/admin/install.php'; if ( is_plugin_active_for_network( NGG_PLUGIN_BASENAME ) ) { $current_blog = $wpdb->blogid; switch_to_blog( $blog_id ); $installer = new C_NGG_Legacy_Installer(); nggallery_install( $installer ); switch_to_blog( $current_blog ); } } public function add_plugin_links( $links, $file ) { if ( $file == NGG_PLUGIN_BASENAME ) { $links[] = '' . __( 'Get help', 'nggallery' ) . ''; foreach ( $links as $key => $link ) { if ( false !== strpos( $link, 'Imagely' ) ) { $links[$key] = str_replace( 'remove_transients(); if ( is_multisite() ) { $network = isset( $_SERVER['SCRIPT_NAME'] ) ? $_SERVER['SCRIPT_NAME'] : ''; $activate = isset( $_GET['action'] ) ? $_GET['action'] : ''; $isNetwork = $network == '/wp-admin/network/plugins.php'; $isActivation = ! ( ( $activate == 'deactivate' ) ); if ( $isNetwork && $isActivation ) { $old_blog = $wpdb->blogid; // $wpdb->prepare() cannot be used just yet as it only supported the %i placeholder for column names as of // WordPress 6.2 which is newer than NextGEN's current minimum WordPress version. // // TODO: Once NextGEN's minimum WP version is 6.2 or higher use wpdb->prepare() here. // // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $blogids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs", null ) ); foreach ( $blogids as $blog_id ) { \switch_to_blog( $blog_id ); \nggallery_install( $this ); } switch_to_blog( $old_blog ); return; } } // remove the update message. delete_option( 'ngg_update_exists' ); nggallery_install( $this ); } public function uninstall( $hard = false ) { include_once 'admin/install.php'; if ( $hard ) { delete_option( 'ngg_init_check' ); delete_option( 'ngg_update_exists' ); delete_option( 'ngg_options' ); delete_option( 'ngg_db_version' ); delete_option( 'ngg_update_exists' ); delete_option( 'ngg_next_update' ); } // now remove the capability. ngg_remove_capability( 'NextGEN Attach Interface' ); ngg_remove_capability( 'NextGEN Change options' ); ngg_remove_capability( 'NextGEN Change style' ); ngg_remove_capability( 'NextGEN Edit album' ); ngg_remove_capability( 'NextGEN Gallery overview' ); ngg_remove_capability( 'NextGEN Manage gallery' ); ngg_remove_capability( 'NextGEN Upload images' ); ngg_remove_capability( 'NextGEN Use TinyMCE' ); ngg_remove_capability( 'NextGEN Manage others gallery' ); ngg_remove_capability( 'NextGEN Manage tags' ); $this->remove_transients(); } public function remove_transients() { global $wpdb, $_wp_using_ext_object_cache; // Fetch all transients $transient_names = $wpdb->get_col( $wpdb->prepare( "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s", [ '%' . $wpdb->esc_like( 'ngg_request' ) . '%', ] ) ); // Delete all transients in the database $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", [ '%' . $wpdb->esc_like( 'ngg_request' ) . '%', ] ) ); // If using an external caching mechanism, delete the cached items. if ( $_wp_using_ext_object_cache ) { foreach ( $transient_names as $transient ) { wp_cache_delete( $transient, 'transient' ); wp_cache_delete( substr( $transient, 11 ), 'transient' ); } } } public function upgrade_schema( $sql ) { global $wpdb; // upgrade function changed in WordPress 2.3. require_once ABSPATH . 'wp-admin/includes/upgrade.php'; // add charset & collate like wp core. $charset_collate = ''; if ( version_compare( $wpdb->get_var( 'SELECT VERSION() AS `mysql_version`' ), '4.1.0', '>=' ) ) { if ( ! empty( $wpdb->charset ) ) { $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset"; } if ( ! empty( $wpdb->collate ) ) { $charset_collate .= " COLLATE $wpdb->collate"; } } // Add charset to table creation query. $sql = str_replace( $charset_collate, '', str_replace( ';', '', $sql ) ); // Execute the query. return dbDelta( $sql . ' ' . $charset_collate . ';' ); } } global $ngg; $ngg = new nggLoader(); PK!#ϒHHLegacy/lib/meta.phpnu[image = \Imagely\NGG\DataMappers\Image::get_instance()->find( $image_or_id ); } else { $this->image = $image_or_id; } $imagePath = \Imagely\NGG\DataStorage\Manager::get_instance()->get_image_abspath( $this->image ); if ( !file_exists( $imagePath ) ) { return false; } $this->size = @getimagesize( $imagePath, $metadata ); if ($this->size && is_array( $metadata )) { // get exif data if (is_callable( 'exif_read_data' ) && \Imagely\NGG\DataStorage\EXIFWriter::is_jpeg_file( $imagePath )) { $this->exif_data = @exif_read_data( $imagePath, null, true ); } // stop here if we didn't need other meta data if ($onlyEXIF) { return true; } // get the iptc data - should be in APP13 if ( is_callable( 'iptcparse' ) && isset( $metadata['APP13'] ) ) { $this->iptc_data = @iptcparse( $metadata['APP13'] ); } // get the xmp data in a XML format if ( is_callable( 'xml_parser_create' )) { $this->xmp_data = $this->extract_XMP( $imagePath ); } return true; } return false; } /** * return the saved meta data from the database * * @since 1.4.0 * @param string $object (optional) * @return array|mixed return either the complete array or the single object */ function get_saved_meta( $object = false ) { $meta = $this->image->meta_data; // Check if we already import the meta data to the database if (!is_array( $meta ) || !isset( $meta['saved'] ) || ( $meta['saved'] !== true )) { return false; } // return one element if requested if ($object) { return $meta[$object]; } // removed saved parameter we don't need that to show unset( $meta['saved'] ); // and remove empty tags or arrays foreach ($meta as $key => $value) { if ( empty( $value ) or is_array( $value )) { unset( $meta[$key] ); } } // on request sanitize the output if ( $this->sanitize == true ) { array_walk( $meta, 'esc_html' ); } return $meta; } /** * nggMeta::get_EXIF() * See also http://trac.wordpress.org/changeset/6313 * * @return bool|array Structured EXIF data */ function get_EXIF( $object = false ) { if ( !$this->exif_data ) { return false; } if (!is_array( $this->exif_array )) { $meta = array(); $exif = isset( $this->exif_data['EXIF'] ) ? $this->exif_data['EXIF'] : array(); if (count( $exif )) { if (!empty( $exif['FNumber'] )) { $meta['aperture'] = 'F ' . round( $this->exif_frac2dec( $exif['FNumber'] ), 2 ); } if (!empty( $exif['Model'] )) { $meta['camera'] = trim( $exif['Model'] ); } if (!empty( $exif['DateTimeDigitized'] )) { $meta['created_timestamp'] = $this->exif_date2ts( $exif['DateTimeDigitized'] ); } elseif (!empty( $exif['DateTimeOriginal'] )) { $meta['created_timestamp'] = $this->exif_date2ts( $exif['DateTimeOriginal'] ); } elseif (!empty( $exif['FileDateTime'] )) { $meta['created_timestamp'] = $this->exif_date2ts( $exif['FileDateTime'] ); } if (!empty( $exif['FocalLength'] )) { $meta['focal_length'] = $this->exif_frac2dec( $exif['FocalLength'] ) . __( ' mm', 'nggallery' ); } if (!empty( $exif['ISOSpeedRatings'] )) { $meta['iso'] = $exif['ISOSpeedRatings']; } if (!empty( $exif['ExposureTime'] )) { $meta['shutter_speed'] = $this->exif_frac2dec( $exif['ExposureTime'] ); $meta['shutter_speed'] =( $meta['shutter_speed'] > 0.0 and $meta['shutter_speed'] < 1.0 ) ? ( '1/' . round( 1 / $meta['shutter_speed'], -1 ) ) : ( $meta['shutter_speed'] ); $meta['shutter_speed'] .= __( ' sec', 'nggallery' ); } // Bit 0 indicates the flash firing status. On some images taken on older iOS versions, this may be // incorrectly stored as an array. if (isset( $exif['Flash'] ) && is_array( $exif['Flash'] )) { $meta['flash'] = __( 'Fired', 'nggallery' ); } elseif (!empty( $exif['Flash'] )) { $meta['flash'] = ( $exif['Flash'] & 1 ) ? __( 'Fired', 'nggallery' ) : __( 'Not fired', ' nggallery' ); } } // additional information if ( isset( $this->exif_data['IFD0'] ) ) { $exif = $this->exif_data['IFD0']; if (!empty( $exif['Model'] )) { $meta['camera'] = $exif['Model']; } if (!empty( $exif['Make'] )) { $meta['make'] = $exif['Make']; } if (!empty( $exif['ImageDescription'] )) { $meta['title'] = $exif['ImageDescription']; } if (!empty( $exif['Orientation'] )) { $meta['Orientation'] = $exif['Orientation']; } } // this is done by Windows if ( isset( $this->exif_data['WINXP'] ) ) { $exif = $this->exif_data['WINXP']; if (!empty( $exif['Title'] ) && empty( $meta['title'] )) { $meta['title'] = $this->utf8_encode( $exif['Title'] ); } if (!empty( $exif['Author'] )) { $meta['author'] = $this->utf8_encode( $exif['Author'] ); } if (!empty( $exif['Keywords'] )) { $meta['keywords'] = $this->utf8_encode( $exif['Keywords'] ); } if (!empty( $exif['Subject'] )) { $meta['subject'] = $this->utf8_encode( $exif['Subject'] ); } if (!empty( $exif['Comments'] )) { $meta['caption'] = $this->utf8_encode( $exif['Comments'] ); } } $this->exif_array = $meta; } // return one element if requested if ( $object == true ) { $value = isset( $this->exif_array[$object] ) ? $this->exif_array[$object] : false; return $value; } // on request sanitize the output if ( $this->sanitize == true ) { array_walk( $this->exif_array, 'esc_html' ); } return $this->exif_array; } // convert a fraction string to a decimal function exif_frac2dec( $str ) { @list( $n, $d ) = explode( '/', $str ); if ( !empty( $d ) ) { return $n / $d; } return $str; } // convert the exif date format to a unix timestamp function exif_date2ts( $str ) { $retval = is_numeric( $str ) ? $str : @strtotime( $str ); if (!$retval && $str) { @list( $date, $time ) = explode( ' ', trim( $str ) ); @list( $y, $m, $d ) = explode( ':', $date ); $retval = strtotime( "{$y}-{$m}-{$d} {$time}" ); } return $retval; } /** * nggMeta::readIPTC() - IPTC Data Information for EXIF Display * * @param mixed $object (optional) * @return null|bool|array */ function get_IPTC( $object = false ) { if (!$this->iptc_data) { return false; } if (!is_array( $this->iptc_array )) { // --------- Set up Array Functions --------- // $iptcTags = array( "2#005" => 'title', "2#007" => 'status', "2#012" => 'subject', "2#015" => 'category', "2#025" => 'keywords', "2#055" => 'created_date', "2#060" => 'created_time', "2#080" => 'author', "2#085" => 'position', "2#090" => 'city', "2#092" => 'location', "2#095" => 'state', "2#100" => 'country_code', "2#101" => 'country', "2#105" => 'headline', "2#110" => 'credit', "2#115" => 'source', "2#116" => 'copyright', "2#118" => 'contact', "2#120" => 'caption', ); $meta = array(); foreach ($iptcTags as $key => $value) { if (isset( $this->iptc_data[$key] )) { $meta[$value] = trim( $this->utf8_encode( implode( ", ", $this->iptc_data[$key] ) ) ); } } $this->iptc_array = $meta; } // return one element if requested if ($object) { return ( isset( $this->iptc_array[$object] ) ) ? $this->iptc_array[$object] : null; } // on request sanitize the output if ( $this->sanitize == true ) { array_walk( $this->iptc_array, 'esc_html' ); } return $this->iptc_array; } /** * nggMeta::extract_XMP() * get XMP DATA * code by Pekka Saarinen http://photography-on-the.net * * @param mixed $filename * @return bool|string XML data */ function extract_XMP( $filename ) { // TODO:Require a lot of memory, could be better ob_start(); @readfile( $filename ); $source = ob_get_contents(); ob_end_clean(); $start = strpos( $source, "" ); if (( !$start === false ) && ( !$end === false )) { $lenght = $end - $start; $xmp_data = substr( $source, $start, $lenght+12 ); unset( $source ); return $xmp_data; } unset( $source ); return false; } /** * nggMeta::get_XMP() * * @package Taken from http://php.net/manual/en/function.xml-parse-into-struct.php * @author Alf Marius Foss Olsen & Alex Rabe * @return bool|array|object XML Array or object */ function get_XMP( $object = false ) { if (!$this->xmp_data) { return false; } if (!is_array( $this->xmp_array )) { $parser = xml_parser_create(); xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 ); // Dont mess with my cAsE sEtTings xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 1 ); // Dont bother with empty info xml_parse_into_struct( $parser, $this->xmp_data, $values ); xml_parser_free( $parser ); $xmlarray = array(); // The XML array $this->xmp_array = array(); // The returned array $stack = array(); // tmp array used for stacking $list_array = array(); // tmp array for list elements $list_element = false; // rdf:li indicator foreach ($values as $val) { if ($val['type'] == "open") { array_push( $stack, $val['tag'] ); } elseif ($val['type'] == "close") { // reset the compared stack if ($list_element == false) { array_pop( $stack ); } // reset the rdf:li indicator & array $list_element = false; $list_array = array(); } elseif ($val['type'] == "complete") { if ($val['tag'] == "rdf:li") { // first go one element back if ($list_element == false) { array_pop( $stack ); } $list_element = true; // do not parse empty tags if ( empty( $val['value'] ) ) { continue; } // save it in our temp array $list_array[] = $val['value']; // in the case it's a list element we seralize it $value = implode( ",", $list_array ); $this->setArrayValue( $xmlarray, $stack, $value ); } else { array_push( $stack, $val['tag'] ); // do not parse empty tags if ( !empty( $val['value'] ) ) { $this->setArrayValue( $xmlarray, $stack, $val['value'] ); } array_pop( $stack ); } } } // foreach // don't parse a empty array if ( empty( $xmlarray ) || empty( $xmlarray['x:xmpmeta'] ) ) { return false; } // cut off the useless tags $xmlarray = $xmlarray['x:xmpmeta']['rdf:RDF']['rdf:Description']; // --------- Some values from the XMP format--------- // $xmpTags = array( 'xap:CreateDate' => 'created_timestamp', 'xap:ModifyDate' => 'last_modfied', 'xap:CreatorTool' => 'tool', 'dc:format' => 'format', 'dc:title' => 'title', 'dc:creator' => 'author', 'dc:subject' => 'keywords', 'dc:description' => 'caption', 'photoshop:AuthorsPosition' => 'position', 'photoshop:City' => 'city', 'photoshop:Country' => 'country', ); foreach ($xmpTags as $key => $value) { // if the kex exist if ( isset( $xmlarray[$key] ) ) { switch ($key) { case 'xap:CreateDate': case 'xap:ModifyDate': $this->xmp_array[$value] = $this->exif_date2ts( $xmlarray[$key] ); break; default: $this->xmp_array[$value] = $xmlarray[$key]; } } } } // return one element if requested if ($object != false ) { return isset( $this->xmp_array[$object] ) ? $this->xmp_array[$object] : false; } // on request sanitize the output if ( $this->sanitize == true ) { array_walk( $this->xmp_array, 'esc_html' ); } return $this->xmp_array; } function setArrayValue( &$array, $stack, $value ) { if ($stack) { $key = array_shift( $stack ); $this->setArrayValue( $array[$key], $stack, $value ); return $array; } else { $array = $value; } return $array; } /** * nggMeta::get_META() - return a meta value form the available list * * @param string $object * @return mixed $value */ function get_META( $object = false ) { if ($value = $this->get_saved_meta( $object )) { return $value; } if ($object == 'created_timestamp' && ( $d = $this->get_IPTC( 'created_date' ) ) && ( $t = $this->get_IPTC( 'created_time' ) )) { return $this->exif_date2ts( $d . ' ' . $t ); } $order = apply_filters( 'ngg_metadata_parse_order', [ 'XMP', 'IPTC', 'EXIF' ] ); foreach ($order as $method) { $method = 'get_' . $method; if (method_exists( $this, $method ) && $value = $this->$method( $object )) { return $value; } } return false; } /** * nggMeta::i8n_name() - localize the tag name * * @param mixed $key * @return string Translated $key */ function i18n_name( $key ) { $tagnames = [ 'aperture' => __( 'Aperture', 'nggallery' ), 'author' => __( 'Author', 'nggallery' ), 'camera' => __( 'Camera', 'nggallery' ), 'caption' => __( 'Caption', 'nggallery' ), 'category' => __( 'Category', 'nggallery' ), 'city' => __( 'City', 'nggallery' ), 'contact' => __( 'Contact', 'nggallery' ), 'copyright' => __( 'Copyright Notice', 'nggallery' ), 'country' => __( 'Country', 'nggallery' ), 'country_code' => __( 'Country code', 'nggallery' ), 'created_date' => __( 'Date Created', 'nggallery' ), 'created_time' => __( 'Time Created', 'nggallery' ), 'created_timestamp' => __( 'Date/Time', 'nggallery' ), 'credit' => __( 'Credit', 'nggallery' ), 'flash' => __( 'Flash', 'nggallery' ), 'focal_length' => __( 'Focal length', 'nggallery' ), 'format' => __( 'Format', 'nggallery' ), 'headline' => __( 'Headline', 'nggallery' ), 'height' => __( 'Image Height', 'nggallery' ), 'iso' => __( 'ISO', 'nggallery' ), 'keywords' => __( 'Keywords', 'nggallery' ), 'last_modfied' => __( 'Last modified', 'nggallery' ), 'location' => __( 'Location', 'nggallery' ), 'make' => __( 'Make', 'nggallery' ), 'position' => __( 'Author Position', 'nggallery' ), 'shutter_speed' => __( 'Shutter speed', 'nggallery' ), 'source' => __( 'Source', 'nggallery' ), 'state' => __( 'Province/State', 'nggallery' ), 'status' => __( 'Edit Status', 'nggallery' ), 'subject' => __( 'Subject', 'nggallery' ), 'tags' => __( 'Tags', 'nggallery' ), 'title' => __( 'Title', 'nggallery' ), 'tool' => __( 'Program tool', 'nggallery' ), 'width' => __( 'Image Width', 'nggallery' ), ]; if ( isset( $tagnames[$key] ) ) { $key = $tagnames[$key]; } return( $key ); } /** * Return the Timestamp from the image , if possible it's read from exif data * * @return string */ function get_date_time() { $date = $this->exif_date2ts( $this->get_META( 'created_timestamp' ) ); if (!$date) { $image_path = \Imagely\NGG\DataStorage\Manager::get_instance()->get_backup_abspath( $this->image ); if (file_exists( $image_path )) { $date = filectime( $image_path ); } } // Fallback if (!$date) { $date = time(); } // Return the MySQL format $date_time = gmdate( 'Y-m-d H:i:s', $date ); return $date_time; } /** * This function return the most common metadata, via a filter we can add more * Reason : GD manipulation removes that options * * @since V1.4.0 * @return bool|array */ function get_common_meta() { global $wpdb; $meta = array( 'aperture' => 0, 'credit' => '', 'camera' => '', 'caption' => '', 'created_timestamp' => 0, 'copyright' => '', 'focal_length' => 0, 'iso' => 0, 'shutter_speed' => 0, 'flash' => 0, 'title' => '', 'keywords' => '', ); $meta = apply_filters( 'ngg_read_image_metadata', $meta ); // meta should be still an array if ( !is_array( $meta ) ) { return false; } foreach ($meta as $key => $value) { $meta[$key] = $this->get_META( $key ); } // let's add now the size of the image $meta['width'] = $this->size[0]; $meta['height'] = $this->size[1]; return $meta; } /** * If needed sanitize each value before output * * @return void */ function sanitize() { $this->sanitize = true; } /** * Wrapper to utf8_encode() that avoids double encoding * * Regex adapted from http://www.w3.org/International/questions/qa-forms-utf-8.en.php * to determine if the given string is already UTF-8. mb_detect_encoding() is not * always available and is limited in accuracy * * @param string $str * @return string */ function utf8_encode( $str ) { $is_utf8 = preg_match( '%^(?: [\x09\x0A\x0D\x20-\x7E] # ASCII | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 )*$%xs', $str ); if (!$is_utf8) { utf8_encode( $str ); } return $str; } } PK!SѰ4Legacy/lib/image.phpnu[meta_data = \Imagely\NGG\Util\Serializable::unserialize( $image->meta_data ); $this->_ngiw = new \Imagely\NGG\DataTypes\LegacyImage( $image, null, true ); } public function __set( $name, $value ) { $this->$name = $value; if ($this->_propogate) { $this->_ngiw->__set( $name, $value ); } } public function __isset( $name ) { return $this->_ngiw->__isset( $name ); } public function __unset( $name ) { return $this->_ngiw->__unset( $name ); } public function __get( $name ) { $this->_propogate = false; $this->$name = $this->_ngiw->__get( $name ); $this->_propogate = true; return $this->$name; } function get_thumbcode( $galleryname = '' ) { return $this->_ngiw->get_thumbcode( $galleryname ); } function get_href_link() { return $this->_ngiw->get_href_link(); } function get_href_thumb_link() { return $this->_ngiw->get_href_thumb_link(); } function cached_singlepic_file( $width = '', $height = '', $mode = '' ) { return $this->_ngiw->cached_singlepic_file( $width, $height, $mode ); } function get_tags() { return $this->_ngiw->get_tags(); } function get_permalink() { return $this->_ngiw->get_permalink(); } } PK!S"Legacy/lib/post-thumbnail.phpnu[" * * @param string $content * @return string html output */ function admin_post_thumbnail( $content, $post_id = null ) { if ($post_id == null) { global $post; if ( !is_object( $post ) ) { return $content; } $post_id = $post->ID; } $thumbnail_id = get_post_meta( $post_id, '_thumbnail_id', true ); // in the case it's a ngg image it return ngg- if ( strpos( $thumbnail_id, 'ngg-' ) === false) { global $wp_version; if (version_compare( $wp_version, '3.5', '>=' ) && $thumbnail_id <= 0) { $iframe_src = get_upload_iframe_src( 'image', $post_id ); $iframe_src = remove_query_arg( 'TB_iframe', $iframe_src ); $iframe_src = add_query_arg( 'tab', 'nextgen', $iframe_src ); $iframe_src = add_query_arg( 'chromeless', '1', $iframe_src ); $iframe_src = add_query_arg( 'TB_iframe', '1', $iframe_src ); $set_thumbnail_link = '

    %s

    '; $content .= sprintf( $set_thumbnail_link, esc_html__( 'Set NextGEN featured image', 'nggallery' ) ); } return $content; } // cut off the 'ngg-' $thumbnail_id = substr( $thumbnail_id, 4 ); return $this->_wp_post_thumbnail_html( $thumbnail_id ); } /** * Filter for the post content * * @param string $html * @param int $post_id * @param int $post_thumbnail_id * @param string|array $size Optional. Image size. Defaults to 'thumbnail'. * @param string|array $attr Optional. Query string or array of attributes. * @return string html output */ function ngg_post_thumbnail( $html, $post_id, $post_thumbnail_id, $size = 'post-thumbnail', $attr = '' ) { global $post, $_wp_additional_image_sizes; // in the case it's a ngg image it return ngg- if ( strpos( $post_thumbnail_id, 'ngg-' ) === false) { return $html; } // cut off the 'ngg-' $post_thumbnail_id = substr( $post_thumbnail_id, 4 ); // get the options $ngg_options = nggGallery::get_option( 'ngg_options' ); // get the image data $image = nggdb::find_image( $post_thumbnail_id ); if (!$image) { return $html; } $img_src = false; $class = 'wp-post-image ngg-image-' . $image->pid . ' '; if (is_array( $size ) || is_array( $_wp_additional_image_sizes ) && isset( $_wp_additional_image_sizes[$size] )) { $class .= isset( $attr['class'] ) ? esc_attr( $attr['class'] ) : ''; if ( is_array( $size )) { // the parameters is given as an array rather than a predfined image $width = absint( $size[0] ); $height = absint( $size[1] ); if (isset( $size[2] ) && $size[2] === true) { $mode = 'crop'; } elseif (isset( $size[2] )) { $mode = $size[2]; } else { $mode = ''; } } else { $width = absint( $_wp_additional_image_sizes[$size]['width'] ); $height = absint( $_wp_additional_image_sizes[$size]['height'] ); $mode = ( $_wp_additional_image_sizes[$size]['crop'] ) ? 'crop' : ''; } // check fo cached picture if ( $post->post_status == 'publish' ) { $img_src = $image->cached_singlepic_file( $width, $height, $mode ); } // if we didn't use a cached image then we take the on-the-fly mode if ($img_src == false) { $img_src = trailingslashit( home_url() ) . 'index.php?callback=image&pid=' . $image->pid . '&width=' . $width . '&height=' . $height . '&mode=crop'; } } else { $img_src = $image->thumbURL; } $alttext = isset( $attr['alt'] ) ? $attr['alt'] : $image->alttext; $titletext = isset( $attr['title'] ) ? $attr['title'] : $image->title; $html = '' . esc_attr( $alttext ) . ''; return $html; } /** * nggPostThumbnail::ajax_set_post_thumbnail() * * @return void */ function ajax_set_post_thumbnail() { // This function does the following: // 1) Check if the user is logged in and has permission to edit the post // 2) Get the thumbnail id from the POST request. The thumbnail id is actually the NGG image id // 3)] global $post_ID; // check for correct capability if ( ! is_user_logged_in() ) { die( '-1' ); } if ( ! isset( $_REQUEST['nonce'] ) || ! wp_verify_nonce( $_REQUEST['nonce'], 'ngg_set_post_thumbnails' ) ) { die( '-1' ); } // get the post id as global variable, otherwise the ajax_nonce failed later $post_ID = intval( $_REQUEST['post_id'] ); if ( ! current_user_can( 'edit_post', $post_ID ) ) { die( '-1' ); } $thumbnail_id = intval( $_REQUEST['thumbnail_id'] ); // delete the image if ( $thumbnail_id == '-1' ) { delete_post_meta( $post_ID, '_thumbnail_id' ); die( '1' ); } if ( ( $attachment_id = StorageManager::get_instance()->set_post_thumbnail( $post_ID, $thumbnail_id, TRUE ) ) ) { die( strval( $attachment_id ) ); } die( strval( 0 ) ); } /** * Output HTML for the post thumbnail meta-box. * * @see wp-admin\includes\post.php * @param int $thumbnail_id ID of the image used for thumbnail * @return string html output */ function _wp_post_thumbnail_html( $thumbnail_id = null ) { global $_wp_additional_image_sizes, $post_ID; $set_thumbnail_link = '

    %s

    '; $content = sprintf( $set_thumbnail_link, esc_html__( 'Set featured image', 'nggallery' ) ); $image = nggdb::find_image( $thumbnail_id ); $img_src = false; // get the options $ngg_options = nggGallery::get_option( 'ngg_options' ); if ( $image ) { if ( is_array( $_wp_additional_image_sizes ) && isset( $_wp_additional_image_sizes['post-thumbnail'] ) ) { // Use post thumbnail settings if defined $width = absint( $_wp_additional_image_sizes['post-thumbnail']['width'] ); $height = absint( $_wp_additional_image_sizes['post-thumbnail']['height'] ); $mode = $_wp_additional_image_sizes['post-thumbnail']['crop'] ? 'crop' : ''; // check fo cached picture $img_src = $image->cached_singlepic_file( $width, $height, $mode ); } // if we didn't use a cached image then we take the on-the-fly mode if ( $img_src == false ) { $img_src = trailingslashit( home_url() ) . 'index.php?callback=image&pid=' . $image->pid . '&width=' . $width . '&height=' . $height . '&mode=crop'; } $thumbnail_html = '' . $image->alttext . ''; if ( !empty( $thumbnail_html ) ) { $ajax_nonce = wp_create_nonce( "set_post_thumbnail-$post_ID" ); $content = sprintf( $set_thumbnail_link, $thumbnail_html ); $content .= '

    ' . esc_html__( 'Remove featured image' ) . '

    '; } } return $content; } } $nggPostThumbnail = new nggPostThumbnail(); PK!TnnLegacy/lib/gd.thumbnail.inc.phpnu[errmsg = ''; $this->error = false; $this->currentDimensions = array(); $this->newDimensions = array(); $this->fileName = $fileName; $this->percent = 100; $this->maxWidth = 0; $this->maxHeight = 0; $this->watermarkImgPath = ''; $this->watermarkText = ''; // check to see if file exists if (!file_exists( $this->fileName )) { $this->errmsg = 'File not found'; $this->error = true; } // check to see if file is readable elseif (!is_readable( $this->fileName )) { $this->errmsg = 'File is not readable'; $this->error = true; } // if there are no errors, determine the file format if ($this->error == false) { @ini_set( 'memory_limit', -1 ); $data = @getimagesize( $this->fileName ); if (isset( $data ) && is_array( $data )) { $extensions = [ IMAGETYPE_GIF => 'GIF', IMAGETYPE_JPEG => 'JPG', IMAGETYPE_PNG => 'PNG', IMAGETYPE_WEBP => 'WEBP', ]; $extension = array_key_exists( $data[2], $extensions ) ? $extensions[$data[2]] : ''; if ($extension) { $this->format = $extension; } else { $this->errmsg = 'Unknown file format'; $this->error = true; } } else { $this->errmsg = 'File is not an image'; $this->error = true; } } // increase memory-limit if possible, GD needs this for large images // @ini_set('memory_limit', '128M'); if ($this->error == false) { // Check memory consumption if file exists $this->checkMemoryForImage( $this->fileName ); } // initialize resources if no errors if ($this->error == false) { switch ($this->format) { case 'GIF': $this->oldImage = ImageCreateFromGif( $this->fileName ); break; case 'JPG': $this->oldImage = ImageCreateFromJpeg( $this->fileName ); break; case 'PNG': $this->oldImage = ImageCreateFromPng( $this->fileName ); break; case 'WEBP': $this->oldImage = imagecreatefromwebp( $this->fileName ); } if (!$this->oldImage) { $this->errmsg = 'Create Image failed. Check memory limit'; $this->error = true; } else { $size = GetImageSize( $this->fileName ); $this->currentDimensions = array( 'width'=>$size[0], 'height'=>$size[1] ); $this->newImage = $this->oldImage; } } if ($this->error == true) { if (!$no_ErrorImage) { $this->showErrorImage(); } return; } } /** * Calculate the memory limit */ function checkMemoryForImage( $filename ) { if ( ( function_exists( 'memory_get_usage' ) ) && ( ini_get( 'memory_limit' ) ) ) { $imageInfo = getimagesize( $filename ); switch ($this->format) { case 'GIF': // measured factor 1 is better $CHANNEL = 1; break; case 'JPG': $CHANNEL = $imageInfo['channels']; break; case 'PNG': // didn't get the channel for png $CHANNEL = 3; break; case 'WEBP': $CHANNEL = $imageInfo['bits']; break; } $MB = 1048576; // number of bytes in 1M $K64 = 65536; // number of bytes in 64K $TWEAKFACTOR = 1.68; // Or whatever works for you $memoryNeeded = round( ( $imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $CHANNEL / 8 + $K64 ) * $TWEAKFACTOR ); $memoryNeeded = memory_get_usage() + $memoryNeeded; // get memory limit $memory_limit = ini_get( 'memory_limit' ); // PHP docs : Note that to have no memory limit, set this directive to -1. if ($memory_limit == -1 ) { return; } // Just check megabyte limits, not higher if ( strtolower( substr( $memory_limit, -1 ) ) == 'm' ) { if ($memory_limit != '') { $memory_limit = substr( $memory_limit, 0, -1 ) * 1024 * 1024; } if ($memoryNeeded > $memory_limit) { $memoryNeeded = round( $memoryNeeded / 1024 / 1024, 2 ); $this->errmsg = 'Exceed Memory limit. Require : ' . $memoryNeeded . " MByte"; $this->error = true; } } } return; } /** * Must be called to free up allocated memory after all manipulations are done */ function destruct() { if (is_resource( $this->newImage ) || $this->newImage instanceof GdImage) { @imagedestroy( $this->newImage ); } if (is_resource( $this->oldImage ) || $this->oldImage instanceof GdImage) { @imagedestroy( $this->oldImage ); } if (is_resource( $this->workingImage ) || $this->workingImage instanceof GdImage) { @imagedestroy( $this->workingImage ); } } /** * Returns the current width of the image * * @return int */ function getCurrentWidth() { return $this->currentDimensions['width']; } /** * Returns the current height of the image * * @return int */ function getCurrentHeight() { return $this->currentDimensions['height']; } /** * Calculates new image width * * @param int $width * @param int $height * @return array */ function calcWidth( $width, $height ) { $newWp = ( 100 * $this->maxWidth ) / $width; $newHeight = ( $height * $newWp ) / 100; return array( 'newWidth'=>intval( $this->maxWidth ), 'newHeight'=>intval( $newHeight ) ); } /** * Calculates new image height * * @param int $width * @param int $height * @return array */ function calcHeight( $width, $height ) { $newHp = ( 100 * $this->maxHeight ) / $height; $newWidth = ( $width * $newHp ) / 100; return array( 'newWidth'=>intval( $newWidth ), 'newHeight'=>intval( $this->maxHeight ) ); } /** * Calculates new image size based on percentage * * @param int $width * @param int $height * @return array */ function calcPercent( $width, $height ) { $newWidth = ( $width * $this->percent ) / 100; $newHeight = ( $height * $this->percent ) / 100; return array( 'newWidth'=>intval( $newWidth ), 'newHeight'=>intval( $newHeight ) ); } /** * Calculates new image size based on width and height, while constraining to maxWidth and maxHeight * * @param int $width * @param int $height */ function calcImageSize( $width, $height ) { $newSize = array( 'newWidth'=>$width, 'newHeight'=>$height ); if ($this->maxWidth > 0) { $newSize = $this->calcWidth( $width, $height ); if ($this->maxHeight > 0 && $newSize['newHeight'] > $this->maxHeight) { $newSize = $this->calcHeight( $newSize['newWidth'], $newSize['newHeight'] ); } // $this->newDimensions = $newSize; } if ($this->maxHeight > 0) { $newSize = $this->calcHeight( $width, $height ); if ($this->maxWidth > 0 && $newSize['newWidth'] > $this->maxWidth) { $newSize = $this->calcWidth( $newSize['newWidth'], $newSize['newHeight'] ); } // $this->newDimensions = $newSize; } $this->newDimensions = $newSize; } /** * Calculates new image size based percentage * * @param int $width * @param int $height */ function calcImageSizePercent( $width, $height ) { if ($this->percent > 0) { $this->newDimensions = $this->calcPercent( $width, $height ); } } /** * Displays error image */ function showErrorImage() { header( 'Content-type: image/png' ); $errImg = ImageCreate( 220, 25 ); $bgColor = imagecolorallocate( $errImg, 0, 0, 0 ); $fgColor1 = imagecolorallocate( $errImg, 255, 255, 255 ); $fgColor2 = imagecolorallocate( $errImg, 255, 0, 0 ); imagestring( $errImg, 3, 6, 6, 'Error:', $fgColor2 ); imagestring( $errImg, 3, 55, 6, $this->errmsg, $fgColor1 ); imagepng( $errImg ); imagedestroy( $errImg ); } /** * Resizes image to fixed Width x Height * * @param int $Width * @param int $Height */ function resizeFix( $Width = 0, $Height = 0, $deprecated = 3 ) { $this->newWidth = $Width; $this->newHeight = $Height; if (function_exists( "ImageCreateTrueColor" )) { $this->workingImage = ImageCreateTrueColor( $this->newWidth, $this->newHeight ); } else { $this->workingImage = ImageCreate( $this->newWidth, $this->newHeight ); } // ImageCopyResampled( $this->imagecopyresampled( $this->workingImage, $this->oldImage, 0, 0, 0, 0, $this->newWidth, $this->newHeight, $this->currentDimensions['width'], $this->currentDimensions['height'] ); $this->oldImage = $this->workingImage; $this->newImage = $this->workingImage; $this->currentDimensions['width'] = $this->newWidth; $this->currentDimensions['height'] = $this->newHeight; } /** * Resizes image to maxWidth x maxHeight * * @param int $maxWidth * @param int $maxHeight */ function resize( $maxWidth = 0, $maxHeight = 0, $deprecated = 3 ) { $this->maxWidth = $maxWidth; $this->maxHeight = $maxHeight; $this->calcImageSize( $this->currentDimensions['width'], $this->currentDimensions['height'] ); if (function_exists( "ImageCreateTrueColor" )) { $this->workingImage = ImageCreateTrueColor( $this->newDimensions['newWidth'], $this->newDimensions['newHeight'] ); } else { $this->workingImage = ImageCreate( $this->newDimensions['newWidth'], $this->newDimensions['newHeight'] ); } // ImageCopyResampled( $this->imagecopyresampled( $this->workingImage, $this->oldImage, 0, 0, 0, 0, $this->newDimensions['newWidth'], $this->newDimensions['newHeight'], $this->currentDimensions['width'], $this->currentDimensions['height'] ); $this->oldImage = $this->workingImage; $this->newImage = $this->workingImage; $this->currentDimensions['width'] = $this->newDimensions['newWidth']; $this->currentDimensions['height'] = $this->newDimensions['newHeight']; } /** * Resizes the image by $percent percent * * @param int $percent */ function resizePercent( $percent = 0 ) { $this->percent = $percent; $this->calcImageSizePercent( $this->currentDimensions['width'], $this->currentDimensions['height'] ); if (function_exists( "ImageCreateTrueColor" )) { $this->workingImage = ImageCreateTrueColor( $this->newDimensions['newWidth'], $this->newDimensions['newHeight'] ); } else { $this->workingImage = ImageCreate( $this->newDimensions['newWidth'], $this->newDimensions['newHeight'] ); } $this->ImageCopyResampled( $this->workingImage, $this->oldImage, 0, 0, 0, 0, $this->newDimensions['newWidth'], $this->newDimensions['newHeight'], $this->currentDimensions['width'], $this->currentDimensions['height'] ); $this->oldImage = $this->workingImage; $this->newImage = $this->workingImage; $this->currentDimensions['width'] = $this->newDimensions['newWidth']; $this->currentDimensions['height'] = $this->newDimensions['newHeight']; } /** * Crops the image from calculated center in a square of $cropSize pixels * * @param int $cropSize */ function cropFromCenter( $cropSize ) { if ($cropSize > $this->currentDimensions['width']) { $cropSize = $this->currentDimensions['width']; } if ($cropSize > $this->currentDimensions['height']) { $cropSize = $this->currentDimensions['height']; } $cropX = intval( ( $this->currentDimensions['width'] - $cropSize ) / 2 ); $cropY = intval( ( $this->currentDimensions['height'] - $cropSize ) / 2 ); if (function_exists( "ImageCreateTrueColor" )) { $this->workingImage = ImageCreateTrueColor( $cropSize, $cropSize ); } else { $this->workingImage = ImageCreate( $cropSize, $cropSize ); } $this->imagecopyresampled( $this->workingImage, $this->oldImage, 0, 0, $cropX, $cropY, $cropSize, $cropSize, $cropSize, $cropSize ); $this->oldImage = $this->workingImage; $this->newImage = $this->workingImage; $this->currentDimensions['width'] = $cropSize; $this->currentDimensions['height'] = $cropSize; } /** * Advanced cropping function that crops an image using $startX and $startY as the upper-left hand corner. * * @param int $startX * @param int $startY * @param int $width * @param int $height */ function crop( $startX, $startY, $width, $height ) { // make sure the cropped area is not greater than the size of the image if ($width > $this->currentDimensions['width']) { $width = $this->currentDimensions['width']; } if ($height > $this->currentDimensions['height']) { $height = $this->currentDimensions['height']; } // make sure not starting outside the image if (( $startX + $width ) > $this->currentDimensions['width']) { $startX = ( $this->currentDimensions['width'] - $width ); } if (( $startY + $height ) > $this->currentDimensions['height']) { $startY = ( $this->currentDimensions['height'] - $height ); } if ($startX < 0) { $startX = 0; } if ($startY < 0) { $startY = 0; } if (function_exists( "ImageCreateTrueColor" )) { $this->workingImage = ImageCreateTrueColor( $width, $height ); } else { $this->workingImage = ImageCreate( $width, $height ); } $this->imagecopyresampled( $this->workingImage, $this->oldImage, 0, 0, $startX, $startY, $width, $height, $width, $height ); $this->oldImage = $this->workingImage; $this->newImage = $this->workingImage; $this->currentDimensions['width'] = $width; $this->currentDimensions['height'] = $height; } /** * Outputs the image to the screen, or saves to $name if supplied. Quality of JPEG images can be controlled with the $quality variable * * @param int $quality * @param string $name */ function show( $quality = 100, $name = '' ) { switch ($this->format) { case 'GIF': if ($name != '') { @ImageGif( $this->newImage, $name ) or $this->error = true; } else { header( 'Content-type: image/gif' ); ImageGif( $this->newImage ); } break; case 'JPG': if ($name != '') { @ImageJpeg( $this->newImage, $name, $quality ) or $this->error = true; } else { header( 'Content-type: image/jpeg' ); ImageJpeg( $this->newImage, null, $quality ); } break; case 'PNG': if ($name != '') { @ImagePng( $this->newImage, $name ) or $this->error = true; } else { header( 'Content-type: image/png' ); ImagePng( $this->newImage ); } break; case 'WEBP': if ($name != '') { $this->error = !@imagewebp( $this->newImage, $name ); } else { header( 'Content-type: image/webp' ); imagewebp( $this->newImage ); } break; } } /** * Saves image as $name (can include file path), with quality of # percent if file is a jpeg * * @param string $name * @param int $quality * @return bool errorstate */ function save( $name, $quality = 100 ) { $this->show( $quality, $name ); if ($this->error == true) { $this->errmsg = 'Create Image failed. Check safe mode settings'; return false; } if ( function_exists( 'do_action' ) ) { do_action( 'ngg_ajax_image_save', $name ); } return true; } /** * Creates Apple-style reflection under image, optionally adding a border to main image * * @param int $percent * @param int $reflection * @param int $white * @param bool $border * @param string $borderColor */ function createReflection( $percent, $reflection, $white, $border = true, $borderColor = '#a4a4a4' ) { $width = $this->currentDimensions['width']; $height = $this->currentDimensions['height']; $reflectionHeight = intval( $height * ( $reflection / 100 ) ); $newHeight = $height + $reflectionHeight; $reflectedPart = $height * ( $percent / 100 ); $this->workingImage = ImageCreateTrueColor( $width, $newHeight ); ImageAlphaBlending( $this->workingImage, true ); $colorToPaint = ImageColorAllocateAlpha( $this->workingImage, 255, 255, 255, 0 ); ImageFilledRectangle( $this->workingImage, 0, 0, $width, $newHeight, $colorToPaint ); imagecopyresampled( $this->workingImage, $this->newImage, 0, 0, 0, $reflectedPart, $width, $reflectionHeight, $width, ( $height - $reflectedPart ) ); $this->imageFlipVertical(); imagecopy( $this->workingImage, $this->newImage, 0, 0, 0, 0, $width, $height ); imagealphablending( $this->workingImage, true ); for ($i=0;$i<$reflectionHeight;$i++) { $colorToPaint = imagecolorallocatealpha( $this->workingImage, 255, 255, 255, ( $i/$reflectionHeight*-1+1 )*$white ); imagefilledrectangle( $this->workingImage, 0, $height+$i, $width, $height+$i, $colorToPaint ); } if ($border == true) { $rgb = $this->hex2rgb( $borderColor, false ); $colorToPaint = imagecolorallocate( $this->workingImage, $rgb[0], $rgb[1], $rgb[2] ); imageline( $this->workingImage, 0, 0, $width, 0, $colorToPaint ); // top line imageline( $this->workingImage, 0, $height, $width, $height, $colorToPaint ); // bottom line imageline( $this->workingImage, 0, 0, 0, $height, $colorToPaint ); // left line imageline( $this->workingImage, $width-1, 0, $width-1, $height, $colorToPaint ); // right line } $this->oldImage = $this->workingImage; $this->newImage = $this->workingImage; $this->currentDimensions['width'] = $width; $this->currentDimensions['height'] = $newHeight; } /** * Flip an image. * * @param bool $horz flip the image in horizontal mode * @param bool $vert flip the image in vertical mode */ function flipImage( $horz = false, $vert = false ) { $sx = $vert ? ( $this->currentDimensions['width'] - 1 ) : 0; $sy = $horz ? ( $this->currentDimensions['height'] - 1 ) : 0; $sw = $vert ? -$this->currentDimensions['width'] : $this->currentDimensions['width']; $sh = $horz ? -$this->currentDimensions['height'] : $this->currentDimensions['height']; $this->workingImage = imagecreatetruecolor( $this->currentDimensions['width'], $this->currentDimensions['height'] ); $this->imagecopyresampled( $this->workingImage, $this->oldImage, 0, 0, $sx, $sy, $this->currentDimensions['width'], $this->currentDimensions['height'], $sw, $sh ); $this->oldImage = $this->workingImage; $this->newImage = $this->workingImage; return true; } /** * Rotate an image clockwise or counter clockwise * * @param string $dir Either CW or CCW */ function rotateImage( $dir = 'CW' ) { $angle = ( $dir == 'CW' ) ? 90 : -90; if (function_exists( 'imagerotate' )) { $this->workingImage = imagerotate( $this->oldImage, 360 - $angle, 0 ); // imagerotate() rotates CCW $this->currentDimensions['width'] = imagesx( $this->workingImage ); $this->currentDimensions['height'] = imagesy( $this->workingImage ); $this->oldImage = $this->workingImage; $this->newImage = $this->workingImage; return true; } $this->workingImage = imagecreatetruecolor( $this->currentDimensions['height'], $this->currentDimensions['width'] ); imagealphablending( $this->workingImage, false ); imagesavealpha( $this->workingImage, true ); switch ($angle) { case 90: for ( $x = 0; $x < $this->currentDimensions['width']; $x++ ) { for ( $y = 0; $y < $this->currentDimensions['height']; $y++ ) { if ( !imagecopy( $this->workingImage, $this->oldImage, $this->currentDimensions['height'] - $y - 1, $x, $x, $y, 1, 1 ) ) { return false; } } } break; case -90: for ( $x = 0; $x < $this->currentDimensions['width']; $x++ ) { for ( $y = 0; $y < $this->currentDimensions['height']; $y++ ) { if ( !imagecopy( $this->workingImage, $this->oldImage, $y, $this->currentDimensions['width'] - $x - 1, $x, $y, 1, 1 ) ) { return false; } } } break; default: return false; } $this->currentDimensions['width'] = imagesx( $this->workingImage ); $this->currentDimensions['height'] = imagesy( $this->workingImage ); $this->oldImage = $this->workingImage; $this->newImage = $this->workingImage; return true; } /** * Inverts working image, used by reflection function * * @access private */ function imageFlipVertical() { $x_i = imagesx( $this->workingImage ); $y_i = imagesy( $this->workingImage ); for ($x = 0; $x < $x_i; $x++) { for ($y = 0; $y < $y_i; $y++) { imagecopy( $this->workingImage, $this->workingImage, $x, $y_i - $y - 1, $x, $y, 1, 1 ); } } } /** * Converts hexidecimal color value to rgb values and returns as array/string * * @param string $hex * @param bool $asString * @return array|string */ function hex2rgb( $hex, $asString = false ) { // strip off any leading # if (0 === strpos( $hex, '#' )) { $hex = substr( $hex, 1 ); } elseif (0 === strpos( $hex, '&H' )) { $hex = substr( $hex, 2 ); } // break into hex 3-tuple $cutpoint = ceil( strlen( $hex ) / 2 )-1; $rgb = explode( ':', wordwrap( $hex, $cutpoint, ':', $cutpoint ), 3 ); // convert each tuple to decimal $rgb[0] = ( isset( $rgb[0] ) ? hexdec( $rgb[0] ) : 0 ); $rgb[1] = ( isset( $rgb[1] ) ? hexdec( $rgb[1] ) : 0 ); $rgb[2] = ( isset( $rgb[2] ) ? hexdec( $rgb[2] ) : 0 ); return ( $asString ? "{$rgb[0]} {$rgb[1]} {$rgb[2]}" : $rgb ); } /** * Based on the Watermark function by Marek Malcherek * http://www.malcherek.de * * @param string $color * @param string $wmFont * @param int $wmSize * @param int $wmOpaque */ function watermarkCreateText( $color, $wmFont, $wmSize = 10, $wmOpaque = 90 ) { if ( empty( $this->watermarkText ) ) { return; } if (!$color) { $color = '000000'; } // set font path $wmFontPath = NGGALLERY_ABSPATH . "fonts/" . $wmFont; if ( !is_readable( $wmFontPath )) { return; } // This function requires both the GD library and the FreeType library. if ( !function_exists( 'ImageTTFBBox' ) ) { return; } $TextSize = @ImageTTFBBox( $wmSize, 0, $wmFontPath, $this->watermarkText ) or die; $TextWidth = abs( $TextSize[2] ) + abs( $TextSize[0] ); $TextHeight = abs( $TextSize[7] ) + abs( $TextSize[1] ); // Create Image for Text $this->workingImage = ImageCreateTrueColor( $TextWidth, $TextHeight ); ImageSaveAlpha( $this->workingImage, true ); ImageAlphaBlending( $this->workingImage, false ); $bgText = imagecolorallocatealpha( $this->workingImage, 255, 255, 255, 127 ); imagefill( $this->workingImage, 0, 0, $bgText ); $wmTransp = 127 -( $wmOpaque * 1.27 ); $rgb = $this->hex2rgb( $color, false ); $TextColor = imagecolorallocatealpha( $this->workingImage, $rgb[0], $rgb[1], $rgb[2], $wmTransp ); // Create Text on image imagettftext( $this->workingImage, $wmSize, 0, 0, abs( $TextSize[5] ), $TextColor, $wmFontPath, $this->watermarkText ); $this->watermarkImgPath = $this->workingImage; return; } /** * Modfied Watermark function by Steve Peart * http://parasitehosting.com/ * * @param string $relPOS * @param int $xPOS * @param int $yPOS */ function watermarkImage( $relPOS = 'botRight', $xPOS = 0, $yPOS = 0 ) { // if it's a resource ID take it as watermark text image if (is_resource( $this->watermarkImgPath ) || $this->watermarkImgPath instanceof GdImage) { $this->workingImage = $this->watermarkImgPath; } else { // Would you really want to use anything other than a png? $this->workingImage = @imagecreatefrompng( $this->watermarkImgPath ); // if it's not a valid file die... if (empty( $this->workingImage ) or ( !$this->workingImage )) { return; } } imagealphablending( $this->workingImage, false ); imagesavealpha( $this->workingImage, true ); $sourcefile_width =imageSX( $this->oldImage ); $sourcefile_height =imageSY( $this->oldImage ); $watermarkfile_width =imageSX( $this->workingImage ); $watermarkfile_height =imageSY( $this->workingImage ); switch (substr( $relPOS, 0, 3 )) { case 'top': $dest_y = 0 + $yPOS; break; case 'mid': $dest_y = ( $sourcefile_height / 2 ) - ( $watermarkfile_height / 2 ); break; case 'bot': $dest_y = $sourcefile_height - $watermarkfile_height - $yPOS; break; default: $dest_y = 0; break; } switch (substr( $relPOS, 3 )) { case 'Left': $dest_x = 0 + $xPOS; break; case 'Center': $dest_x = ( $sourcefile_width / 2 ) - ( $watermarkfile_width / 2 ); break; case 'Right': $dest_x = $sourcefile_width - $watermarkfile_width - $xPOS; break; default: $dest_x = 0; break; } // debug // $this->errmsg = 'X '.$dest_x.' Y '.$dest_y; // $this->showErrorImage(); // if a gif, we have to upsample it to a truecolor image if ($this->format == 'GIF') { $tempimage = imagecreatetruecolor( $sourcefile_width, $sourcefile_height ); imagecopy( $tempimage, $this->oldImage, 0, 0, 0, 0, $sourcefile_width, $sourcefile_height ); $this->newImage = $tempimage; } imagecopy( $this->newImage, $this->workingImage, $dest_x, $dest_y, 0, 0, $watermarkfile_width, $watermarkfile_height ); } /** * Modfied imagecopyresampled function to save transparent images * See : http://www.akemapa.com/2008/07/10/php-gd-resize-transparent-image-png-gif/ * * @since 1.9.0 * * @param resource $dst_image * @param resource $src_image * @param int $dst_x * @param int $dst_y * @param int $src_x * @param int $src_y * @param int $dst_w * @param int $dst_h * @param int $src_w * @param int $src_h * @return bool */ function imagecopyresampled( &$dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) { // Check if this image is PNG or GIF, then set if Transparent if ( $this->format == 'GIF' || $this->format == 'PNG') { imagealphablending( $dst_image, false ); imagesavealpha( $dst_image, true ); $transparent = imagecolorallocatealpha( $dst_image, 255, 255, 255, 127 ); imagefilledrectangle( $dst_image, 0, 0, $dst_w, $dst_h, $transparent ); } imagecopyresampled( $dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ); return true; } } PK!(;%%Legacy/lib/tags.phpnu[ 'ok', 'message' => '', ); if ( trim( str_replace( ',', '', stripslashes( $new ) ) ) == '' ) { $return_value['message'] = __( 'No new tag specified!', 'nggallery' ); $return_value['status'] = 'error'; return $return_value; } // String to array $old_tags = explode( ',', $old ); $new_tags = explode( ',', $new ); // Remove empty element and trim $old_tags = array_filter( $old_tags, 'nggtags_delete_empty_element' ); $new_tags = array_filter( $new_tags, 'nggtags_delete_empty_element' ); // If old/new tag are empty => exit ! if ( empty( $old_tags ) || empty( $new_tags ) ) { $return_value['message'] = __( 'No new/old valid tag specified!', 'nggallery' ); $return_value['status'] = 'error'; return $return_value; } $counter = 0; if ( count( $old_tags ) == count( $new_tags ) ) { // Rename only foreach ( (array) $old_tags as $i => $old_tag ) { $new_name = $new_tags[$i]; // Get term by name $term = get_term_by( 'name', $old_tag, 'ngg_tag' ); if ( !$term ) { continue; } // Get objects from term ID $objects_id = get_objects_in_term( $term->term_id, 'ngg_tag', array( 'fields' => 'all_with_object_id' ) ); // Delete old term wp_delete_term( $term->term_id, 'ngg_tag' ); // Set objects to new term ! (Append no replace) foreach ( (array) $objects_id as $object_id ) { wp_set_object_terms( $object_id, $new_name, 'ngg_tag', true ); } // Clean cache clean_object_term_cache( $objects_id, 'ngg_tag' ); clean_term_cache( $term->term_id, 'ngg_tag' ); // Increment ++$counter; } if ( $counter == 0 ) { $return_value['message'] = __( 'No tag renamed.', 'nggallery' ); } else { $return_value['message'] = sprintf( __( 'Renamed tag(s) «%1$s» to «%2$s»', 'nggallery' ), $old, $new ); } } elseif ( count( $new_tags ) == 1 ) { // Merge // Set new tag $new_tag = $new_tags[0]; if ( empty( $new_tag ) ) { $return_value['message'] = __( 'No valid new tag.', 'nggallery' ); $return_value['status'] = 'error'; return $return_value; } // Get terms ID from old terms names $terms_id = array(); foreach ( (array) $old_tags as $old_tag ) { $term = get_term_by( 'name', addslashes( $old_tag ), 'ngg_tag' ); $terms_id[] = (int) $term->term_id; } // Get objects from terms ID $objects_id = get_objects_in_term( $terms_id, 'ngg_tag', array( 'fields' => 'all_with_object_id' ) ); // No objects ? exit ! if ( !$objects_id ) { $return_value['message'] = __( 'No objects (post/page) found for specified old tags.', 'nggallery' ); $return_value['status'] = 'error'; return $return_value; } // Delete old terms foreach ( (array) $terms_id as $term_id ) { wp_delete_term( $term_id, 'ngg_tag' ); } // Set objects to new term ! (Append no replace) foreach ( (array) $objects_id as $object_id ) { wp_set_object_terms( $object_id, $new_tag, 'ngg_tag', true ); ++$counter; } // Test if term is also a category if ( term_exists( $new_tag, 'category' ) ) { // Edit the slug to use the new term $slug = sanitize_title( $new_tag ); self::edit_tag_slug( $new_tag, $slug ); unset( $slug ); } // Clean cache clean_object_term_cache( $objects_id, 'ngg_tag' ); clean_term_cache( $terms_id, 'ngg_tag' ); if ( $counter == 0 ) { $return_value['message'] = __( 'No tag merged.', 'nggallery' ); } else { $return_value['message'] = sprintf( __( 'Merge tag(s) «%1$s» to «%2$s». %3$s objects edited.', 'nggallery' ), $old, $new, $counter ); } } else { // Error $return_value['message'] = sprintf( __( 'Error. Not enough tags provided to rename or merge.', 'nggallery' ), $old ); $return_value['status'] = 'error'; } do_action( 'ngg_manage_tags', $new_tags ); return $return_value; } /** * Delete tags */ static function delete_tags( $delete ) { $return_value = array( 'status' => 'ok', 'message' => '', ); if ( trim( str_replace( ',', '', stripslashes( $delete ) ) ) == '' ) { $return_value['message'] = __( 'No tag specified!', 'nggallery' ); $return_value['status'] = 'error'; return $return_value; } // In array + filter $delete_tags = explode( ',', $delete ); $delete_tags = array_filter( $delete_tags, 'nggtags_delete_empty_element' ); // Delete tags $counter = 0; foreach ( (array) $delete_tags as $tag ) { $term = get_term_by( 'name', $tag, 'ngg_tag' ); $term_id = (int) $term->term_id; if ( $term_id != 0 ) { wp_delete_term( $term_id, 'ngg_tag' ); clean_term_cache( $term_id, 'ngg_tag' ); ++$counter; } } if ( $counter == 0 ) { $return_value['message'] = __( 'No tag deleted.', 'nggallery' ); } else { $return_value['message'] = sprintf( __( '%1s tag(s) deleted.', 'nggallery' ), $counter ); } do_action( 'ngg_manage_tags', $delete_tags ); return $return_value; } /** * Edit tag slug given the name of the tag */ static function edit_tag_slug( $names = '', $slugs = '' ) { $return_value = array( 'status' => 'ok', 'message' => '', ); if ( trim( str_replace( ',', '', stripslashes( $slugs ) ) ) == '' ) { $return_value['message'] = __( 'No new slug(s) specified!', 'nggallery' ); $return_value['status'] = 'error'; return $return_value; } $match_names = explode( ',', $names ); $new_slugs = explode( ',', $slugs ); $match_names = array_filter( $match_names, 'nggtags_delete_empty_element' ); $new_slugs = array_filter( $new_slugs, 'nggtags_delete_empty_element' ); if ( count( $match_names ) != count( $new_slugs ) ) { $return_value['message'] = __( 'Tags number and slugs number isn\'t the same!', 'nggallery' ); $return_value['status'] = 'error'; return $return_value; } else { $counter = 0; foreach ( (array) $match_names as $i => $match_name ) { // Sanitize slug + Escape $new_slug = sanitize_title( $new_slugs[$i] ); // Get term by name $term = get_term_by( 'name', $match_name, 'ngg_tag' ); if ( !$term ) { continue; } // Increment ++$counter; // Update term wp_update_term( $term->term_id, 'ngg_tag', array( 'slug' => $new_slug ) ); // Clean cache clean_term_cache( $term->term_id, 'ngg_tag' ); } } if ( $counter == 0 ) { $return_value['message'] = __( 'No slug edited.', 'nggallery' ); } else { $return_value['message'] = sprintf( __( '%s slug(s) edited.', 'nggallery' ), $counter ); } return $return_value; } /** * Get a list of the tags used by the images */ static function find_all_tags() { return get_terms( 'ngg_tag', '' ); } /** * */ static function find_tags( $args = '', $skip_cache = false ) { $taxonomy = 'ngg_tag'; if ( $skip_cache == true ) { $terms = get_terms( $taxonomy, $args ); } else { $key = md5( serialize( $args ) ); // Get cache if exist // -- if ( $cache = wp_cache_get( 'ngg_get_tags', 'nggallery' ) ) { if ( isset( $cache[$key] ) ) { return apply_filters( 'get_tags', $cache[$key], $args ); } } // Get tags // -- $terms = get_terms( $taxonomy, $args ); if ( empty( $terms ) ) { return array(); } $cache[$key] = $terms; wp_cache_set( 'ngg_get_tags', $cache, 'nggallery' ); } $terms = apply_filters( 'get_tags', $terms, $args ); return $terms; } /** * Get images corresponding to a list of tags * * nggTags::find_images_for_tags() * * @param mixed $taglist * @param string $mode could be 'ASC', 'DESC' or 'RAND' * * @return array of images */ static function find_images_for_tags( $taglist, $mode = "ASC" ) { // return the images based on the tag global $wpdb; // extract it into a array $taglist = explode( ",", $taglist ); if ( ! is_array( $taglist ) ) { $taglist = array( $taglist ); } $taglist = array_map( 'trim', $taglist ); $new_slugarray = array_map( 'sanitize_title', $taglist ); $sluglist = implode( "', '", $new_slugarray ); // Treat % as a literal in the database, for unicode support $sluglist = str_replace( "%", "%%", $sluglist ); // first get all $term_ids with this tag $term_ids = $wpdb->get_col( $wpdb->prepare( "SELECT term_id FROM $wpdb->terms WHERE slug IN (%s) ORDER BY term_id ASC ", $sluglist ) ); $picids = get_objects_in_term( $term_ids, 'ngg_tag' ); if ( $mode == 'RAND' ) { shuffle( $picids ); } // Now lookup in the database $mapper = \Imagely\NGG\DataMappers\Image::get_instance(); $images = array(); foreach ( $picids as $image_id ) { $images[] = $mapper->find( $image_id ); } if ( 'DESC' == $mode ) { $images = array_reverse( $images ); } return $images; } } /** * trim and remove empty element * * @param string $element * @return null|string */ if (!function_exists( 'nggtags_delete_empty_element' )) { function nggtags_delete_empty_element( $element ) { $element = stripslashes( $element ); $element = trim( $element ); if (!empty( $element )) { return $element; } return null; } } PK! { Legacy/lib/sitemap.phpnu[images = $images; // first get the content of the post/page $p = get_post( $post_id ); // Backward check for older images $p->post_content = NextGEN_shortcodes::convert_shortcode( $p->post_content ); // Don't process the images in the normal way remove_all_shortcodes(); // We cannot parse at this point a album, just galleries & single images \Imagely\NGG\Display\Shortcodes::add( 'singlepic', array( &$this, 'add_images' ) ); \Imagely\NGG\Display\Shortcodes::add( 'thumb', array( &$this, 'add_images' ) ); \Imagely\NGG\Display\Shortcodes::add( 'nggallery', array( &$this, 'add_gallery' ) ); \Imagely\NGG\Display\Shortcodes::add( 'imagebrowser', array( &$this, 'add_gallery' ) ); \Imagely\NGG\Display\Shortcodes::add( 'slideshow', array( &$this, 'add_gallery' ) ); // Search now for shortcodes do_shortcode( $p->post_content ); return $this->images; } /** * Parse the gallery/imagebrowser/slideshow shortcode and return all images into an array * * @TODO: replace or remove this function, it's return value isn't even linked to the queries it performs * @param string $atts * @return string */ function add_gallery( $atts ) { global $wpdb; $tmp = shortcode_atts( array( 'id' => 0 ), $atts, 'ngg' ); extract( $tmp ); $gallery_mapper = \Imagely\NGG\DataMappers\Gallery::get_instance(); if (!is_numeric( $id )) { $tmp = $gallery_mapper->select()->where( array( 'name = %s', $id ) )->limit( 1 )->run_query(); if (( $gallery = array_shift( $tmp ) )) { $id = $gallery->{$gallery->id_field}; } else { $id = null; } } if ($id) { $gallery_storage = \Imagely\NGG\DataStorage\Manager::get_instance(); $image_mapper = \Imagely\NGG\DataMappers\Image::get_instance(); foreach ($image_mapper->find_all_for_gallery( $id ) as $image) { $this->images[] = array( 'src' => $gallery_storage->get_image_url( $image ), 'title' => $image->title, 'alt' => $image->alttext, ); } } return ''; } /** * Parse the single image shortcode and return all images into an array * * @param array $atts * @return string */ function add_images( $atts ) { $tmp = shortcode_atts( array( 'id' => 0 ), $atts, 'ngg' ); extract( $tmp ); // make an array out of the ids (for thumbs shortcode)) $pids = explode( ',', $id ); // Some error checks if ( count( $pids ) == 0 ) { return ''; } $images = nggdb::find_images_in_list( $pids ); foreach ($images as $image) { $newimage = array(); $newimage['src'] = $newimage['sc'] = $image->imageURL; if ( !empty( $image->title ) ) { $newimage['title'] = $image->title; } if ( !empty( $image->alttext ) ) { $newimage['alt'] = $image->alttext; } $this->images[] = $newimage; } return ''; } } $nggSitemaps = new nggSitemaps(); PK!_ǣf""Legacy/lib/media-rss.phpnu[\n"; } /** * Get the URL of the general media RSS */ public static function get_mrss_url(): string { return NGGALLERY_URLPATH . 'xml/media-rss.php'; } /** * Get the URL of a gallery media RSS */ public static function get_gallery_mrss_url( $gid, $prev_next = false ): string { return self::get_mrss_url() . '?' . ( 'gid=' . $gid . ( $prev_next ? '&prev_next=true' : '' ) . '&mode=gallery' ); } /** * Get the URL of the media RSS for last pictures */ public static function get_last_pictures_mrss_url( $page = 0, $show = 30 ): string { return self::get_mrss_url() . '?' . ( 'show=' . $show . '&page=' . $page . '&mode=last_pictures' ); } /** * Get the XML node corresponding to the last pictures registered * * @param int $page The current page (defaults to 0) * @param int $show The number of pictures to include in one field (default 30) */ public static function get_last_pictures_mrss( $page = 0, $show = 30 ) { $images = nggdb::find_last_images( $page, $show ); $title = stripslashes( get_option( 'blogname' ) ); $description = stripslashes( get_option( 'blogdescription' ) ); $link = site_url(); $prev_link = ( $page > 0 ) ? self::get_last_pictures_mrss_url( $page-1, $show ) : ''; $next_link = count( $images )!=0 ? self::get_last_pictures_mrss_url( $page+1, $show ) : ''; return self::get_mrss_root_node( $title, $description, $link, $prev_link, $next_link, $images ); } /** * Get the XML node corresponding to a gallery * * @param $gallery (object) The gallery to include in RSS * @param $prev_gallery (object) The previous gallery to link in RSS (null if none) * @param $next_gallery (object) The next gallery to link in RSS (null if none) */ public static function get_gallery_mrss( $gallery, $prev_gallery = null, $next_gallery = null ) { $ngg_options = nggGallery::get_option( 'ngg_options' ); // Set sort order value, if not used (upgrade issue) $ngg_options['galSort'] = ( $ngg_options['galSort'] ) ? $ngg_options['galSort'] : 'pid'; $ngg_options['galSortDir'] = ( $ngg_options['galSortDir'] == 'DESC' ) ? 'DESC' : 'ASC'; $title = stripslashes( \Imagely\NGG\Display\I18N::translate( $gallery->title ) ); $description = stripslashes( \Imagely\NGG\Display\I18N::translate( $gallery->galdesc ) ); $link = self::get_permalink( $gallery->pageid ); $prev_link = ( $prev_gallery != null ) ? self::get_gallery_mrss_url( $prev_gallery->gid, true ) : ''; $next_link = ( $next_gallery != null ) ? self::get_gallery_mrss_url( $next_gallery->gid, true ) : ''; $images = nggdb::get_gallery( $gallery->gid, $ngg_options['galSort'], $ngg_options['galSortDir'] ); return self::get_mrss_root_node( $title, $description, $link, $prev_link, $next_link, $images ); } /** * Get the XML node corresponding to an album * * @param object $album The album to include in RSS */ public static function get_album_mrss( $album ) { $nggdb = new nggdb(); $title = stripslashes( \Imagely\NGG\Display\I18N::translate( $album->name ) ); $description = ''; $link = self::get_permalink( 0 ); $prev_link = ''; $next_link = ''; $images = $nggdb->find_images_in_album( $album->id ); return self::get_mrss_root_node( $title, $description, $link, $prev_link, $next_link, $images ); } /** * Get the XML node */ public static function get_mrss_root_node( $title, $description, $link, $prev_link, $next_link, $images ) { if ($prev_link != '' || $next_link != '') { $out = "\n"; } else { $out = "\n"; } $out .= "\t\n"; $out .= self::get_generator_mrss_node(); $out .= self::get_title_mrss_node( $title ); $out .= self::get_description_mrss_node( $description ); $out .= self::get_link_mrss_node( $link ); if ($prev_link != '' || $next_link != '') { $out .= self::get_self_node( self::get_mrss_url() ); } if ($prev_link!='') { $out .= self::get_previous_link_mrss_node( $prev_link ); } if ($next_link!='') { $out .= self::get_next_link_mrss_node( $next_link ); } foreach ($images as $image) { $out .= self::get_image_mrss_node( $image ); } $out .= "\t\n"; $out .= "\n"; return $out; } /** * Get the XML node */ public static function get_generator_mrss_node( $indent = "\t\t" ) { return $indent . "\n"; } /** * Get the XML node */ public static function get_title_mrss_node( $title, $indent = "\t\t" ) { return $indent . "<title>" . $title . "\n"; } /** * Get the XML node */ public static function get_description_mrss_node( $description, $indent = "\t\t" ) { return $indent . "" . $description . "\n"; } /** * Get the XML node */ public static function get_link_mrss_node( $link, $indent = "\t\t" ) { return $indent . "\n"; } /** * Get the XML node */ public static function get_self_node( $link, $indent = "\t\t" ) { return $indent . "\n"; } /** * Get the XML node */ public static function get_previous_link_mrss_node( $link, $indent = "\t\t" ) { return $indent . "\n"; } /** * Get the XML node */ public static function get_next_link_mrss_node( $link, $indent = "\t\t" ) { return $indent . "
    ' . "\n"; } /** * Show a system messages */ static function show_message( $message, $message_id = null ) { echo '

    ' . $message . '

    ' . "\n"; } /** * nggGallery::get_option() - get the options and overwrite them with custom meta settings * * @param string $key * @return array $options */ static function get_option( $key ) { global $post; // get first the options from the database $options = get_option( $key ); if ( $post == null ) { return $options; } // Get all key/value data for the current post. $meta_array = get_post_custom(); // Ensure that this is a array if ( !is_array( $meta_array ) ) { $meta_array = array( $meta_array ); } // assign meta key to db setting key $meta_tags = array( 'string' => array( 'ngg_gal_ShowOrder' => 'galShowOrder', 'ngg_gal_Sort' => 'galSort', 'ngg_gal_SortDirection' => 'galSortDir', 'ngg_gal_ShowDescription' => 'galShowDesc', 'ngg_ir_Audio' => 'irAudio', 'ngg_ir_Overstretch' => 'irOverstretch', 'ngg_ir_Transition' => 'irTransition', 'ngg_ir_Backcolor' => 'irBackcolor', 'ngg_ir_Frontcolor' => 'irFrontcolor', 'ngg_ir_Lightcolor' => 'irLightcolor', 'ngg_slideshowFX' => 'slideFx', ), 'int' => array( 'ngg_gal_Images' => 'galImages', 'ngg_gal_Columns' => 'galColumns', 'ngg_paged_Galleries' => 'galPagedGalleries', 'ngg_ir_Width' => 'irWidth', 'ngg_ir_Height' => 'irHeight', 'ngg_ir_Rotatetime' => 'irRotatetime', ), 'bool' => array( 'ngg_gal_ShowSlide' => 'galShowSlide', 'ngg_gal_ImageBrowser' => 'galImgBrowser', 'ngg_gal_HideImages' => 'galHiddenImg', 'ngg_ir_Shuffle' => 'irShuffle', 'ngg_ir_LinkFromDisplay' => 'irLinkfromdisplay', 'ngg_ir_ShowNavigation' => 'irShownavigation', 'ngg_ir_ShowWatermark' => 'irWatermark', 'ngg_ir_Kenburns' => 'irKenburns', ), ); foreach ($meta_tags as $typ => $meta_keys) { foreach ($meta_keys as $key => $db_value) { // if the kex exist overwrite it with the custom field if (array_key_exists( $key, $meta_array )) { switch ($typ) { case 'string': $options[$db_value] = (string) esc_attr( $meta_array[$key][0] ); break; case 'int': $options[$db_value] = (int) $meta_array[$key][0]; break; case 'bool': $options[$db_value] = (bool) $meta_array[$key][0]; break; } } } } return $options; } /** * Renders a section of user display code. The code is first checked for in the current theme display directory * before defaulting to the plugin * Call the function : nggGallery::render ('template_name', array ('var1' => $var1, 'var2' => $var2)); * * @autor John Godley * @param string $template_name Name of the template file (without extension) * @param string $vars Array of variable name=>value that is available to the display code (optional) * @param bool $callback In case we check we didn't find template we tested it one time more (optional) * @return void **/ static function render( $template_name, $vars = array(), $callback = false ) { $vars['template'] = $template_name; echo \Imagely\NGG\DisplayedGallery\Renderer::get_instance()->display_images( $vars ); } /** * Captures an section of user display code. * * @autor John Godley * @param string $template_name Name of the template file (without extension) * @param string $vars Array of variable name=>value that is available to the display code (optional) * @deprecated Use Imagely\NGG\DisplayedGallery\Renderer class * @return string **/ static function capture( $template_name, $vars = array() ) { $vars['template'] = $template_name; return \Imagely\NGG\DisplayedGallery\Renderer::get_instance()->display_images( $vars ); } /** * Returns the path to lib/gd.thumbnail.inc.php * * @return string Path to the selected library */ static function graphic_library() { return NGGALLERY_ABSPATH . '/lib/gd.thumbnail.inc.php'; } /** * Support for i18n with wpml, polyglot or qtrans * * @param string $in * @param string $name (optional) required for wpml to determine the type of translation * @return string $in localized */ static function i18n( $in, $name = null ) { if ( function_exists( 'langswitch_filter_langs_with_message' ) ) { $in = langswitch_filter_langs_with_message( $in ); } if ( function_exists( 'polyglot_filter' )) { $in = polyglot_filter( $in ); } if ( function_exists( 'qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage' )) { $in = qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage( $in ); } if (is_string( $name ) && !empty( $name ) && function_exists( 'icl_translate' )) { $in = icl_translate( 'plugin_ngg', $name, $in, true ); } $in = apply_filters( 'localization', $in ); return $in; } /** * Check the memory_limit and calculate a recommended memory size * * @since V1.2.0 * @return string message about recommended image size */ static function check_memory_limit() { if ( ( function_exists( 'memory_get_usage' ) ) && ( ini_get( 'memory_limit' ) ) ) { // get memory limit $memory_limit = ini_get( 'memory_limit' ); if ($memory_limit != '') { $memory_limit = substr( $memory_limit, 0, -1 ) * 1024 * 1024; } // calculate the free memory $freeMemory = $memory_limit - memory_get_usage(); // build the test sizes $sizes = array(); $sizes[] = array( 'width' => 800, 'height' => 600 ); $sizes[] = array( 'width' => 1024, 'height' => 768 ); $sizes[] = array( 'width' => 1280, 'height' => 960 ); // 1MP $sizes[] = array( 'width' => 1600, 'height' => 1200 ); // 2MP $sizes[] = array( 'width' => 2016, 'height' => 1512 ); // 3MP $sizes[] = array( 'width' => 2272, 'height' => 1704 ); // 4MP $sizes[] = array( 'width' => 2560, 'height' => 1920 ); // 5MP // test the classic sizes foreach ($sizes as $size) { // very, very rough estimation if ($freeMemory < round( $size['width'] * $size['height'] * 5.09 )) { $result = sprintf( __( 'Note : Based on your server memory limit you should not upload larger images then %d x %d pixel', 'nggallery' ), $size['width'], $size['height'] ); return $result; } } } return ''; } /** * Check for extended capabilites. Must previously registers with add_ngg_capabilites() * * @since 1.5.0 * @param string $capability * @return bool $result of capability check */ static function current_user_can( $capability ) { global $_ngg_capabilites; if ( is_array( $_ngg_capabilites ) ) { if ( in_array( $capability, $_ngg_capabilites ) ) { return current_user_can( $capability ); } } return true; } } PK!7WLegacy/xml/media-rss.phpnu[find_all(); if ( count( $galleries ) == 0 ) { header( 'content-type:text/plain;charset=utf-8' ); print esc_html( __( 'No galleries have been yet created.', 'nggallery' ) ); exit; } // Get additional parameters $gid = isset( $_GET['gid'] ) ? (int) $_GET['gid'] : 0; // if no gid is present, take the first gallery if ( $gid == 0 ) { $first = current( $galleries ); $gid = $first->gid; } // account for the the odd logic used in selecting galleries here if ( $gid == 1 ) { $gid = 0; } elseif ( $gid > 1 ) { --$gid; } // Set the main gallery object $gallery = $galleries[ $gid ]; if ( ! isset( $gallery ) || $gallery == null ) { header( 'content-type:text/plain;charset=utf-8' ); print esc_html( sprintf( __( 'The gallery ID=%s does not exist.', 'nggallery' ), intval( $gid ) ) ); exit; } // show other galleries if needed $prev_next = 'true' === $_GET['prev_next']; $prev_gallery = $next_gallery = null; // Get previous and next galleries if required if ( $prev_next ) { reset( $galleries ); while ( current( $galleries ) ) { if ( key( $galleries ) == $gid ) { break; } next( $galleries ); } // one step back $prev_gallery = prev( $galleries ); // two step forward... Could be easier ? How ? next( $galleries ); $next_gallery = next( $galleries ); } $rss = nggMediaRss::get_gallery_mrss( $gallery, $prev_gallery, $next_gallery ); } elseif ( $mode == 'album' ) { // Get additional parameters $aid = isset( $_GET['aid'] ) ? (int) $_GET['aid'] : 0; if ( $aid == 0 ) { header( 'content-type:text/plain;charset=utf-8' ); print esc_html( __( 'No album ID has been provided as parameter', 'nggallery' ) ); exit; } // Get the album object $nggdb = new nggdb(); $album = $nggdb->find_album( $aid ); if ( ! isset( $album ) || $album == null ) { header( 'content-type:text/plain;charset=utf-8' ); printf( __( 'The album ID=%s does not exist.', 'nggallery' ), intval( $aid ) ); exit; } $rss = nggMediaRss::get_album_mrss( $album ); } else { header( 'content-type:text/plain;charset=utf-8' ); echo __( 'Invalid MediaRSS command', 'nggallery' ); exit; } // Output header for media RSS header( 'content-type:text/xml;charset=utf-8' ); echo "\n"; echo $rss; PK!нl  Legacy/admin/wpmu.phpnu[set( $option_name, $option_value ); } if ( isset( $_POST['gallerypath'] ) ) { $new_gallerypath = trailingslashit( $_POST['gallerypath'] ); $fs = \Imagely\NGG\Util\Filesystem::get_instance(); $root = $fs->get_document_root( 'galleries' ); if ( $root[0] != DIRECTORY_SEPARATOR ) { $root = DIRECTORY_SEPARATOR . $root; } $gallery_abspath = $fs->get_absolute_path( $fs->join_paths( $root, $new_gallerypath ) ); if ( $gallery_abspath[0] != DIRECTORY_SEPARATOR ) { $gallery_abspath = DIRECTORY_SEPARATOR . $gallery_abspath; } if ( strpos( $gallery_abspath, $root ) === false ) { $messagetext[] = sprintf( __( 'Gallery path must be located in %s.', 'nggallery' ), $root ); } elseif ( preg_match( '\.+[/\\]', $new_gallerypath ) ) { $messagetext[] = __( 'Gallery path cannot include relative paths.', 'nggallery' ); } else { $ngg_options->set( 'gallerypath', $new_gallerypath ); $ngg_options->save(); } } $ngg_options->save(); $messagetext[] = __( 'Updated successfully.', 'nggallery' ); $messagetext = implode( ' ', $messagetext ); } // message windows. if ( ! empty( $messagetext ) ) { echo '

    ' . esc_html( $messagetext ) . '

    '; } ?>


    wp-content/uploads/sites/%BLOG_ID%/nggallery/', __( 'The default setting should be %s', 'nggallery' ) ); ?>
    : get( 'wpmuQuotaCheck' ) ); ?> />
    : get( 'wpmuZipUpload' ) ); ?> />
    : get( 'wpmuImportFolder' ) ); ?> />
    : get( 'wpmuRoles' ) ); ?> />
    id ) ) { $image = $image->id; } elseif ( isset( $image->pid ) ) { $image = $image->pid; } } $storage = \Imagely\NGG\DataStorage\Manager::get_instance(); // XXX NextGEN Legacy wasn't handling watermarks or reflections at this stage, so we're forcefully disabling them to maintain compatibility. $params = [ 'watermark' => false, 'reflection' => false, ]; $result = $storage->generate_thumbnail( $image, $params ); if ( ! $result ) { // XXX there isn't any error handling unfortunately at the moment in the generate_thumbnail functions, need a way to return proper error status. return __( 'Error while creating thumbnail.', 'nggallery' ); } // success. return '1'; } /** * nggAdmin::resize_image() - create a new image, based on the height /width * * @class nggAdmin * @param object|int $image Contain all information about the image or the id * @param integer $width optional * @param integer $height optional * @return string result code */ static function resize_image( $image, $width = 0, $height = 0 ) { if ( is_object( $image ) ) { if ( isset( $image->id ) ) { $image = $image->id; } elseif ( isset( $image->pid ) ) { $image = $image->pid; } } $storage = \Imagely\NGG\DataStorage\Manager::get_instance(); // XXX maybe get rid of this...it's needed to get width/height defaults, placing these directly in generate_image_size could have unwanted consequences. $settings = \Imagely\NGG\Settings\Settings::get_instance(); // XXX NextGEN Legacy wasn't handling watermarks or reflections at this stage, so we're forcefully disabling them to maintain compatibility. $params = [ 'watermark' => false, 'reflection' => false, ]; if ( $width > 0 ) { $params['width'] = $width; } else { $params['width'] = $settings->get( 'imgWidth' ); } if ( $height > 0 ) { $params['height'] = $height; } else { $params['height'] = $settings->get( 'imgHeight' ); } $result = $storage->generate_image_size( $image, 'full', $params ); if ( ! $result ) { // XXX there isn't any error handling unfortunately at the moment in the generate_thumbnail functions, need a way to return proper error status. return __( 'Error while resizing image.', 'nggallery' ); } // success. return '1'; } /** * Rotated/Flip an image based on the orientation flag or a definded angle * * @param int|object $image * @param string|bool $dir (optional) CW (clockwise)or CCW (counter clockwise), if set to false, the exif flag will be used * @param string|bool $flip (optional) Either false | V (flip vertical) | H (flip horizontal) * @return string result code */ static function rotate_image( $image, $dir = false, $flip = false ) { if ( is_object( $image ) ) { if ( isset( $image->id ) ) { $image = $image->id; } elseif ( isset( $image->pid ) ) { $image = $image->pid; } } $storage = \Imagely\NGG\DataStorage\Manager::get_instance(); // XXX NextGEN Legacy wasn't handling watermarks or reflections at this stage, so we're forcefully disabling them to maintain compatibility. $params = [ 'watermark' => false, 'reflection' => false, ]; $rotation = null; if ( $dir === 'CW' ) { $rotation = 90; } elseif ( $dir === 'CCW' ) { $rotation = -90; } // if you didn't define a rotation, we look for the orientation flag in EXIF. elseif ( $dir === false ) { $meta = new nggMeta( $image ); $exif = $meta->get_EXIF(); if ( isset( $exif['Orientation'] ) ) { switch ( $exif['Orientation'] ) { case 5: // vertical flip + 90 rotate right. $flip = 'V'; case 6: // 90 rotate right $rotation = 90; break; case 7: // horizontal flip + 90 rotate right. $flip = 'H'; case 8: // 90 rotate left. $rotation = -90; break; case 4: // vertical flip. $flip = 'V'; break; case 3: // 180 rotate left. $rotation = -180; break; case 2: // horizontal flip. $flip = 'H'; break; case 1: // no action in the case it doesn't need a rotation. default: return '0'; break; } } else { return '0'; } } if ( $rotation != null ) { $params['rotation'] = $rotation; } if ( $flip != null ) { $params['flip'] = $flip; } $result = $storage->generate_image_size( $image, 'full', $params ); if ( ! $result ) { // XXX there isn't any error handling unfortunately at the moment in the generate_thumbnail functions, need a way to return proper error status. return __( 'Error while rotating image.', 'nggallery' ); } // success. return '1'; } /** * nggAdmin::set_watermark() - set the watermark for the image * * @class nggAdmin * @param object|int $image Contain all information about the image or the id * @return string result code */ static function set_watermark( $image ) { if ( is_object( $image ) ) { if ( isset( $image->id ) ) { $image = $image->id; } elseif ( isset( $image->pid ) ) { $image = $image->pid; } } $storage = \Imagely\NGG\DataStorage\Manager::get_instance(); // XXX NextGEN Legacy was only handling watermarks at this stage, so we're forcefully disabling all else. $params = [ 'watermark' => true, 'reflection' => false, 'crop' => false, ]; $result = $storage->generate_image_size( $image, 'full', $params ); if ( ! $result ) { // XXX there isn't any error handling unfortunately at the moment in the generate_thumbnail functions, need a way to return proper error status. return __( 'Error while applying watermark to image.', 'nggallery' ); } // success. return '1'; } /** * Recover image from backup copy and reprocess it * * @class nggAdmin * @since 1.5.0 * @param object|int $image Contain all information about the image or the id * @return string result code */ static function recover_image( $image ) { return \Imagely\NGG\DataStorage\Manager::get_instance()->recover_image( $image ); } /** * Add images to database * * @class nggAdmin * @param int $galleryID * @param array $imageslist * @return array $image_ids IDs which have been successfully added */ public static function add_Images( $galleryID, $imageslist ) { global $ngg; $image_ids = []; if ( is_array( $imageslist ) ) { foreach ( $imageslist as $picture ) { // filter function to rename/change/modify image before. $picture = apply_filters( 'ngg_pre_add_new_image', $picture, $galleryID ); // strip off the extension of the filename. $path_parts = \Imagely\NGG\Display\I18N::mb_pathinfo( $picture ); $alttext = ( ! isset( $path_parts['filename'] ) ) ? substr( $path_parts['basename'], 0, strpos( $path_parts['basename'], '.' ) ) : $path_parts['filename']; // save it to the database. $pic_id = nggdb::add_image( $galleryID, $picture, '', $alttext ); if ( \Imagely\NGG\Settings\Settings::get_instance()->imgBackup && ! empty( $pic_id ) ) { $storage = \Imagely\NGG\DataStorage\Manager::get_instance(); $storage->backup_image( $pic_id ); } if ( ! empty( $pic_id ) ) { $image_ids[] = $pic_id; } // add the metadata. self::import_MetaData( $pic_id ); // auto rotate. self::rotate_image( $pic_id ); // Autoresize image if required. if ( $ngg->options['imgAutoResize'] ) { $imagetmp = nggdb::find_image( $pic_id ); $sizetmp = @getimagesize( $imagetmp->imagePath ); $widthtmp = $ngg->options['imgWidth']; $heighttmp = $ngg->options['imgHeight']; if ( ( $sizetmp[0] > $widthtmp && $widthtmp ) || ( $sizetmp[1] > $heighttmp && $heighttmp ) ) { self::resize_image( $pic_id ); } } // action hook for post process after the image is added to the database. $image = [ 'id' => $pic_id, 'filename' => $picture, 'galleryID' => $galleryID, ]; do_action( 'ngg_added_new_image', $image ); } } // delete dirsize after adding new images. delete_transient( 'dirsize_cache' ); do_action( 'ngg_after_new_images_added', $galleryID, $image_ids ); return $image_ids; } /** * Import some meta data into the database (if avialable) * * @class nggAdmin * @param array|int $imagesIds * @return string result code */ static function import_MetaData( $imagesIds ) { global $wpdb; require_once NGGALLERY_ABSPATH . '/lib/image.php'; if ( ! is_array( $imagesIds ) ) { $imagesIds = [ $imagesIds ]; } foreach ( $imagesIds as $imageID ) { // Get the image. $image = null; if ( is_int( $imageID ) ) { $image = \Imagely\NGG\DataMappers\Image::get_instance()->find( $imageID ); } else { $image = $imageID; } if ( $image ) { $meta = self::get_MetaData( $image ); // get the title. $alttext = empty( $meta['title'] ) ? $image->alttext : $meta['title']; // get the caption / description field. $description = empty( $meta['caption'] ) ? $image->description : $meta['caption']; // get the file date/time from exif. $timestamp = $meta['timestamp']; // first update database. $result = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->nggpictures SET alttext = %s, description = %s, imagedate = %s WHERE pid = %d", $alttext, $description, $timestamp, $image->pid ) ); if ( $result === false ) { return ' ' . esc_html( $image->filename ) . ' ' . __( '(Error : Couldn\'t not update data base)', 'nggallery' ) . ''; } // this flag will inform us that the import is already one time performed. $meta['common']['saved'] = true; $result = nggdb::update_image_meta( $image->pid, $meta['common'] ); if ( $result === false ) { return ' ' . esc_html( $image->filename ) . ' ' . __( '(Error : Couldn\'t not update meta data)', 'nggallery' ) . ''; } // add the tags if we found some. if ( $meta['keywords'] ) { $taglist = explode( ',', $meta['keywords'] ); wp_set_object_terms( $image->pid, $taglist, 'ngg_tag' ); } } else { return ' ' . esc_html( $image->filename ) . ' ' . __( '(Error : Couldn\'t not find image)', 'nggallery' ) . ''; // error check. } } return '1'; } /** * nggAdmin::get_MetaData() * * @class nggAdmin * @require NextGEN Meta class * @param int|object $image_or_id * @return array metadata */ static function get_MetaData( $image_or_id ) { require_once NGGALLERY_ABSPATH . '/lib/meta.php'; $meta = []; $pdata = new nggMeta( $image_or_id ); $meta['title'] = trim( $pdata->get_META( 'title' ) ); $meta['caption'] = trim( $pdata->get_META( 'caption' ) ); $meta['keywords'] = trim( $pdata->get_META( 'keywords' ) ); $meta['timestamp'] = $pdata->get_date_time(); // this contain other useful meta information. $meta['common'] = $pdata->get_common_meta(); // hook for addon plugin to add more meta fields. $meta = apply_filters( 'ngg_get_image_metadata', $meta, $pdata ); return $meta; } /** * nggAdmin::import_gallery() * TODO: Check permission of existing thumb folder & images * * @param string $galleryfolder contains relative path to the gallery itself * @param int $gallery_id * @return void */ public static function import_gallery( $galleryfolder, $gallery_id = null ) { global $wpdb, $user_ID; // get the current user ID. wp_get_current_user(); $created_msg = ''; // remove trailing slash at the end, if somebody use it. $galleryfolder = untrailingslashit( $galleryfolder ); $fs = \Imagely\NGG\Util\Filesystem::get_instance(); if ( is_null( $gallery_id ) ) { $gallerypath = $fs->join_paths( $fs->get_document_root( 'content' ), $galleryfolder ); } else { $storage = \Imagely\NGG\DataStorage\Manager::get_instance(); $gallerypath = $storage->get_gallery_abspath( $gallery_id ); } if ( ! is_dir( $gallerypath ) ) { nggGallery::show_error( sprintf( __( 'Directory %s doesn`t exist!', 'nggallery' ), esc_html( $gallerypath ) ) ); return; } // read list of images. $new_imageslist = self::scandir( $gallerypath ); if ( empty( $new_imageslist ) ) { nggGallery::show_message( sprintf( __( 'Directory %s contains no pictures', 'nggallery' ), esc_html( $gallerypath ) ) ); return; } // take folder name as gallery name. $galleryname = basename( $galleryfolder ); $galleryname = apply_filters( 'ngg_gallery_name', $galleryname ); // check for existing gallery folder. if ( is_null( $gallery_id ) ) { $gallery_id = $wpdb->get_var( $wpdb->prepare( "SELECT gid FROM {$wpdb->nggallery} WHERE path = %s", [ $galleryfolder ] ) ); } if ( ! $gallery_id ) { // now add the gallery to the database. $gallery_id = nggdb::add_gallery( $galleryname, $galleryfolder, '', 0, 0, $user_ID ); if ( ! $gallery_id ) { nggGallery::show_error( __( 'Database error. Could not add gallery!', 'nggallery' ) ); return; } else { do_action( 'ngg_created_new_gallery', $gallery_id ); } $created_msg = sprintf( _n( 'Gallery %s successfully created!', 'Galleries %s successfully created!', 1, 'nggallery' ), esc_html( $galleryname ) ); } // Look for existing image list. $old_imageslist = $wpdb->get_col( $wpdb->prepare( "SELECT `filename` FROM {$wpdb->nggpictures} WHERE `galleryid` = %d", [ $gallery_id, ] ) ); // if no images are there, create empty array. if ( $old_imageslist == null ) { $old_imageslist = []; } // check difference. $new_images = array_diff( $new_imageslist, $old_imageslist ); // all images must be valid files. foreach ( $new_images as $key => $picture ) { // filter function to rename/change/modify image before. $picture = apply_filters( 'ngg_pre_add_new_image', $picture, $gallery_id ); $new_images[ $key ] = $picture; if ( ! @getimagesize( $gallerypath . '/' . $picture ) ) { unset( $new_images[ $key ] ); @unlink( $gallerypath . '/' . $picture ); } } // add images to database. $image_ids = self::add_Images( $gallery_id, $new_images ); do_action( 'ngg_after_new_images_added', $gallery_id, $image_ids ); // add the preview image if needed. self::set_gallery_preview( $gallery_id ); // now create thumbnails. self::do_ajax_operation( 'create_thumbnail', $image_ids, __( 'Create new thumbnails', 'nggallery' ) ); // TODO:Message will not shown, because AJAX routine require more time, message should be passed to AJAX. $message = $created_msg . sprintf( _n( '%s picture successfully added', '%s pictures successfully added', count( $image_ids ), 'nggallery' ), count( $image_ids ) ); $message .= ' ['; $message .= __( 'Edit gallery', 'nggallery' ); $message .= ']'; nggGallery::show_message( $message ); return; } /** * Capability check. Check is the ID fit's to the user_ID * * @class nggAdmin * @param int $check_ID is the user_id * @return bool $result */ static function can_manage_this_gallery( $check_ID ) { global $user_ID, $wp_roles; if ( ! current_user_can( 'NextGEN Manage others gallery' ) ) { // get the current user ID. wp_get_current_user(); if ( $user_ID != $check_ID ) { return false; } } return true; } /** * Initate the Ajax operation * * @class nggAdmin * @param string $operation name of the function which should be executed * @param array $image_array * @param string $title name of the operation * @return string the javascript output */ static function do_ajax_operation( $operation, $image_array, $title = '' ) { if ( ! is_array( $image_array ) || empty( $image_array ) ) { return ''; } $js_array = implode( '","', $image_array ); // send out some JavaScript, which initate the ajax operation. ob_start(); ?> find( $galleryID ) ) ) { if ( ! $gallery->previewpic ) { $image_mapper = \Imagely\NGG\DataMappers\Image::get_instance(); $image = $image_mapper->select() ->where( [ 'galleryid = %d', $galleryID ] ) ->where( [ 'exclude != 1' ] ) ->order_by( $image_mapper->get_primary_key_column() ) ->limit( 1 ) ->run_query(); if ( $image ) { $gallery->previewpic = $image->{$image->id_field}; $gallery_mapper->save( $gallery ); } } } } /** * Return a JSON coded array of Image ids for a requested gallery * * @class nggAdmin * @param int $galleryID * @return string|int (JSON) */ static function get_image_ids( $galleryID ) { if ( ! function_exists( 'json_encode' ) ) { return( -2 ); } $gallery = nggdb::get_ids_from_gallery( $galleryID, 'pid', 'ASC', false ); header( 'Content-Type: text/plain; charset=' . get_option( 'blog_charset' ), true ); return json_encode( $gallery ); } /** * Deprecated function, restored to fix compatibility with "NextGen Public Uploader" * * @deprecated * @class nggAdmin * @param string $filename * @return bool $result */ function chmod( $filename = '' ) { $stat = @stat( dirname( $filename ) ); $perms = $stat['mode'] & 0000666; if ( @chmod( $filename, $perms ) ) { return true; } return false; } } // END class nggAdmin // XXX temporary...used as a quick fix to refresh I_Settings_Manager when the nextgen option is updated manually in order to run Hooks etc. function ngg_refreshSavedSettings(): bool { $settings = \Imagely\NGG\Settings\Settings::get_instance(); if ( $settings != null ) { $width = $settings->get( 'thumbwidth' ); $height = $settings->get( 'thumbheight' ); $new_dimension = "{$width}x{$height}"; $dimensions = (array) $settings->get( 'thumbnail_dimensions' ); if ( ! in_array( $new_dimension, $dimensions ) ) { $dimensions[] = $new_dimension; $settings->set( 'thumbnail_dimensions', $dimensions ); $settings->save(); return true; } } return false; } PK!4, . . 'Legacy/admin/css/jquery.ui.tabs.min.cssnu[@media projection,screen{.ui-tabs-hide{display:none}}@media print{.ui-tabs-nav{display:none}}#slider{border-color:#ebebeb #ccc #ccc #ebebeb;border-style:solid;border-width:1px;margin:15px 15% 0 15px;padding:2px}#tabs{display:block;background:#f1f1f1 none repeat scroll 0;font-size:14px;overflow:hidden}.ui-tabs-nav{list-style:none;margin:0;padding:0 0 0 10px}.ui-tabs-nav:after{display:block;clear:both;content:" "}.ui-tabs-nav li{float:left;padding:6px 5px;min-width:84px;margin:2px 2px 0 1px!important;text-decoration:none;list-style:none}.ui-tabs-nav a,.ui-tabs-nav a span{display:block;padding:0 1px}.ui-tabs-nav a{margin:1px 0 0;padding-left:0;color:#2583ad;line-height:1.2;text-align:center;text-decoration:none;white-space:nowrap;outline:0}.ui-tabs-nav .ui-tabs-selected{background:#6d6d6d url(../images/menu-bits.gif) repeat-x scroll left top;border-color:#6d6d6d;color:#fff;text-shadow:0 -1px 0 #666;-moz-border-radius-topright:6px;-khtml-border-top-right-radius:6px;-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-moz-border-radius-topleft:6px;-khtml-border-top-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px}.ui-tabs-selected a,.ui-tabs-selected a:hover{color:#fff!important}.ui-tabs-nav .ui-tabs-selected a,.ui-tabs-nav .ui-tabs-selected a:hover{position:relative;top:1px;z-index:2;margin-top:0}.ui-tabs-nav li a:hover{color:#d54e21}.ui-tabs-nav a span{width:64px;min-width:64px;height:18px;min-height:18px;padding-top:6px;padding-right:0}*>.ui-tabs-nav a span{width:auto;height:auto}.ui-tabs-nav .ui-tabs-selected a span{padding-bottom:1px}.ui-tabs-nav .ui-tabs-selected a,.ui-tabs-nav a:active,.ui-tabs-nav a:focus,.ui-tabs-nav a:hover{background-position:100% -150px}.ui-tabs-nav .ui-tabs-disabled a:active,.ui-tabs-nav .ui-tabs-disabled a:focus,.ui-tabs-nav .ui-tabs-disabled a:hover,.ui-tabs-nav a{background-position:100% -100px}.ui-tabs-nav .ui-tabs-selected a span,.ui-tabs-nav a:active span,.ui-tabs-nav a:focus span,.ui-tabs-nav a:hover span{background-position:0 -50px}.ui-tabs-nav .ui-tabs-disabled a:active span,.ui-tabs-nav .ui-tabs-disabled a:focus span,.ui-tabs-nav .ui-tabs-disabled a:hover span,.ui-tabs-nav a span{background-position:0 0}.ui-tabs-nav .ui-tabs-disabled a:link,.ui-tabs-nav .ui-tabs-disabled a:visited,.ui-tabs-nav .ui-tabs-selected a:link,.ui-tabs-nav .ui-tabs-selected a:visited{cursor:text}.ui-tabs-nav .ui-tabs-unselect a:active,.ui-tabs-nav .ui-tabs-unselect a:focus,.ui-tabs-nav .ui-tabs-unselect a:hover,.ui-tabs-nav a:active,.ui-tabs-nav a:focus,.ui-tabs-nav a:hover{cursor:pointer}.ui-tabs-disabled{opacity:.4}.ui-tabs-panel{border-top:1px solid #97a5b0!important;padding:1em 8px;background:#fff;border:none!important;height:100%!important;margin:0!important;overflow:visible!important}.ui-tabs-panel a{display:inline}* html .ui-tabs-nav{display:inline-block}PK!S"Legacy/admin/css/nggSorter.min.cssnu[.imageBox,.imageBoxHighlighted{width:130px;height:160px;float:left}.imageBox_theImage{width:110px;height:125px;background-position:center;background-repeat:no-repeat;margin:0 auto;margin-bottom:2px}.imageBox .imageBox_theImage{border:1px solid #ddd;padding:2px}.imageBoxHighlighted .imageBox_theImage{border:3px solid #316ac5;padding:0}.imageBoxHighlighted span{background-color:#316ac5;color:#fff;padding:2px}.imageBox_label{text-align:center;font-family:arial;font-size:11px;padding-top:2px;margin:0 auto}#insertionMarker{height:150px;width:6px;position:absolute}#insertionMarkerLine{width:6px;height:145px}#insertionMarker img{float:left}#dragDropContent{opacity:.4;position:absolute;z-index:10;display:none}PK!ߛJLegacy/admin/css/nggadmin.cssnu[/* ** NextGEN Gallery Style for Wordpress 3.3 */ #iframely h2.title { display: none; } /* OVERVIEW PAGES */ .toplevel_page_nextgen-gallery #ngg_page_content { width: 98%; } .toplevel_page_nextgen-gallery #ngg_page_content .about-wrap.ngg_overview { width: 100%; } .toplevel_page_nextgen-gallery #ngg_page_content .ngg_page_content_main { padding-right: 40px !important; } #newversion { border-color:#CCCCCC; border-style:solid; border-width:1px; margin-right:7px; margin-top:10px; padding:2px; } .ngg-dashboard-widget ul.settings span { padding-left : 10px; color:#2583AD; font-weight:bold; } .ngg-overview .postbox .handlediv { float:right; height:24px; width:24px; } #ngg_page_content .ngg_overview .ngg_page_content_header h2 { padding-top: 2px; } #ngg_page_content .ngg_overview .ngg_page_content_main h2 { text-align: left; font-size: 22px; font-weight: 400; color: black; margin: 20px 0 20px; text-transform: uppercase; letter-spacing: 2px; } #ngg_page_content .ngg_overview .ngg_page_content_main .about-text { font-size: 17px; max-width: none; margin: 20px 0; color: black; font-weight: 400; } #ngg-gallery-wizard { min-height: auto; position: absolute; top: 0; right: 0; text-align: right; margin: 0 20px 0 0; line-height: 80px; color: #fff; font-size: 14px; margin-right: 0; color: black; font-weight: 400; letter-spacing: .5px; } #ngg_page_content #ngg-gallery-wizard a { font-weight: bold; text-decoration: none; margin-left: 20px; height: 50px !important; line-height: 50px; } .warning { color: #9F6000; background-color: #FEEFB3; border: 1px solid; margin: 5px 0px; padding:5px; } #donator_message { margin:5px 0 15px; background-color:#BDE5F8; border-color:#00529B; -moz-border-radius-bottomleft:3px; -moz-border-radius-bottomright:3px; -moz-border-radius-topleft:3px; -moz-border-radius-topright:3px; border-style:solid; border-width:1px; margin:5px 15px 2px; padding:0 0.6em; } #donator_message p{ line-height:1; margin:0.5em 0; padding:2px; padding-bottom:10px; } #donator_message span{ padding-top:10px; float:right; } #plugin_check img { float: right; } #plugin_check p.message { font-size: 90%; color: #666; } .toplevel_page_nextgen-gallery .feature-video iframe { box-shadow: 0 0 8px 4px rgba(0,0,0,.03); width: 800px; height: 450px; max-width: 100%; } div[data-id="welcome-link"] .about-text { margin: 0 0 40px !important; } div[data-id="pro-link"] .feature-section { position: relative; margin: 40px 0; padding-bottom: 56.25%; } div[data-id="pro-link"] .feature-section iframe { width: 900px; height: 506px; max-width: 100%; position: absolute; top: 0; left: 0; width: 100%; height: 100%; } #ngg_page_content .button-primary.ngg-pro-upgrade { height: 50px !important; padding: 0 40px !important; line-height: 50px; } div[data-id="videos-link"] .feature-section, div[data-id="videos-link"] .feature-section .col, div[data-id="genesis-link"] .feature-section, div[data-id="genesis-link"] .feature-section .col { padding: 0; margin: 0; } /* COMMON STYLING FOR DIALOGS */ .ngg-admin .ui-dialog { max-width: 100%; } /* OPTIONS TABLE */ .ngg-options th { width:22%; } a.switch-expert { text-decoration:none; } /* WATERMARK */ #wm-preview { float:right; font-size:90%; width:35%; border-color:#EBEBEB rgb(204, 204, 204) rgb(204, 204, 204) rgb(235, 235, 235); border-style:solid; border-width:1px; margin-bottom:10px; margin-left:10px; margin-right:8px; padding:2px; } #wm-preview h3{ background:#F9F9F9 none repeat scroll 0%; font-size:14px; font-weight:bold; margin:0pt 0pt 10px; padding:8px 5px; } #wm-position { width:100%; margin-left:40px; } .wm-table { border-collapse:collapse; margin-top:1em; width: 60%; clear:none; } .wm-table td { border-bottom:8px solid #FFFFFF; line-height:20px; margin-bottom:9px; padding:10px; } .wm-table th { border-bottom:8px solid #FFFFFF; padding:10px; text-align:left; } .wm-table tr { background:#F9F9F9 none repeat scroll 0%; } /* MANAGE GALLERY */ .ngg-admin.gallery_page_nggallery-manage-gallery #ngg_page_content .notice, .ngg-admin.gallery_page_nggallery-manage-gallery #ngg_page_content div.updated, .ngg-admin.gallery_page_nggallery-manage-gallery #ngg_page_content div.error { margin: 10px 0 40px 0; } .ngg_admin_notice ul { list-style: circle inside; margin: 0; padding: 0; } .gallery_page_nggallery-manage-gallery #ngg_page_content .ngg_page_content_main { padding-top: 30px; } .ngg-admin.gallery_page_nggallery-manage-gallery #ngg_page_content div.updated#message { margin-bottom: 35px; } .gallery_page_nggallery-manage-gallery #ngg_page_content > .wrap > h2 { display:none; } #ngg_page_content .ngg_manage_galleries .tablenav { margin: 0 0 30px; } #ngg_page_content .ngg_manage_images .handlediv { float: none; width: 100%; height: 50px; } #gallerydiv h3 { margin-left: 10px; display: inline-block; height: 50px; float: left; margin: 0; line-height: 50px; text-transform: uppercase; font-size: 16px; letter-spacing: 1.5px; } #gallerydiv span.toggle-indicator { display: inline-block; float: left; line-height: 50px; } #gallerydiv span.toggle-indicator:before { font-size: 24px; margin: 12px 20px 0 10px; } #gallerydiv span.toggle-indicator:hover { cursor: pointer; } #gallerydiv h3:active, #gallerydiv h3:focus, #gallerydiv span.toggle-indicator:active, #gallerydiv span.toggle-indicator:focus { outline: 0; border: none; -moz-outline-style: none; } #ngg_page_content .ngg_manage_images .tablenav { margin: 50px 0 30px; } #ngg_page_content .ngg_manage_galleries .tablenav.top > div, #ngg_page_content .ngg_manage_images .tablenav.top > div { margin-bottom: 10px; } #ngg_page_content .ngg_manage_galleries .search-box-wrapper { display: flex; flex-direction: row; justify-content: center; width: 100%; } #ngg_page_content .ngg_manage_galleries div.search-box { display: flex; flex-direction: row; justify-content: center; } #ngg_page_content .ngg_manage_galleries div.search-box:last-of-type { } #ngg_page_content .ngg_manage_galleries .search-box input[type=text] { width: calc(100% - 150px) !important; height: 35px !important; margin-right: 4px !important; } #ngg_page_content .ngg_manage_galleries .search-box input[type=submit].button-primary { width: 150px !important; height: 35px !important; padding: 0 !important; } #ngg_page_content .ngg_manage_galleries form.search-form { width: 100%; } #ngg_page_content .ngg_manage_galleries form.search-form:first-of-type { padding-right: 25px; } #ngg_page_content #editgalleries .displaying-num { margin-right: 7px !important; font-size: 14px; letter-spacing: 1px; } #ngg_page_content #editgalleries #bulkaction { min-height: 35px; max-height: 35px; } #ngg_page_content .ngg_manage_galleries .tablenav.bottom { margin: 15px 0 0; } #ngg_page_content .ngg_manage_images .tablenav.bottom { margin: 25px 0 0; } .ngg-admin #ngg_page_content .ngg_manage_images td { vertical-align: top; } #ngg_page_content .ngg_manage_galleries .tablenav input { height: 28px; width: 50px; padding: 0 3px; } #ngg_page_content .ngg_manage_galleries .tablenav input.current-page { width: 50px !important; } #ngg_page_content .ngg_manage_images .tablenav .tablenav-pages { margin-top: 0; } #ngg_page_content .ngg_manage_galleries .tablenav .tablenav-pages { margin-top: 6px; } #ngg_page_content .ngg_manage_galleries .tablenav .tablenav-pages a, #ngg_page_content .ngg_manage_images .tablenav .tablenav-pages a { background: black; border: none; color: #fff !important; margin: 0 2px; text-decoration: none; font-size: 20px; padding: 4px; line-height: 20px; padding: 2px 8px 6px 8px; } #ngg_page_content .ngg_manage_images .tablenav input, #ngg_page_content .ngg_manage_images .tablenav select { width: auto; margin-top: 0; } #ngg_page_content .ngg_manage_images .tablenav input.current-page, #ngg_page_content #ngg-manage-images-items-per-page { padding: 4px !important; text-align-last: center; background-image: none; } #ngg_page_content .ngg_manage_galleries table { box-shadow: none; border: 1px solid rgba(159, 187, 26, 0.08)!important } #ngg_page_content .ngg_manage_galleries table thead, #ngg_page_content .ngg_manage_galleries table tfoot { background-color: black; } #ngg_page_content .ngg_manage_galleries table thead th, #ngg_page_content .ngg_manage_galleries table thead td, #ngg_page_content .ngg_manage_galleries table tfoot th, #ngg_page_content .ngg_manage_galleries table tfoot td { background-color: transparent; border: none; } #ngg_page_content .ngg_manage_galleries table th, #ngg_page_content .ngg_manage_galleries table td { padding: 12px 10px; font-size: 14px; } #ngg_page_content .ngg_manage_galleries table th { font-weight: bold !important; color: #fff; } .ngg_manage_galleries th#id { width: 33px; } .ngg_manage_galleries th#title { min-width: 140px; } .ngg_manage_galleries td.title { text-transform: uppercase; font-weight: 400; font-size: 13px !important; } .ngg_manage_galleries th#author { min-width: 80px; } .ngg_manage_galleries th#page_id { min-width: 60px; } #ngg_page_content .ngg_manage_galleries table tr.alternate { background-color: #f7f7f7; } #ngg_page_content .ngg_manage_galleries th a { padding: 0 !important; color: #fff; } div#poststuff { min-width: auto; } div#poststuff #gallerydiv { cursor:pointer; } p#ngg-inlinebutton { float:right; margin:0pt; position:relative; top:-25pt; } #gallery_fields { width: 100%; } #gallery_fields td{ padding: 5px; min-width: 105px; } #gallery_fields tr td:nth-of-type(2) { padding-right: 60px; } #gallery_fields input[type=text], #gallery_fields textarea, #gallery_fields select { min-width: 220px; width: 99%; color: #888; } table#ngg-listimages { border: 1px solid #f7f7f7; } #ngg-listimages thead, #ngg-listimages tfoot { background: black; } #ngg-listimages tfoot { background: black; } #ngg-listimages.widefat thead th, .ngg-admin #ngg_page_content .widefat tfoot th { padding: 12px 10px !important; } #ngg-listimages tr.alternate { background-color: #f7f7f7; } #ngg-listimages td { padding: 15px 5px !important; } #ngg-listimages .iedit, #ngg-listimages .iedit td, #ngg-listimages th { border: none; } #ngg-listimages th, #ngg-listimages .iedit td { padding: 15px 5px; } #ngg-listimages th { font-size: 12px; font-weight: bold; } #ngg-listimages .column select { width: 100% !important; } #ngg-listimages .column-1 input { margin: 0 0 0 8px; } #ngg-listimages .column-1 { width: 24px; } #ngg-listimages .column-2 { width: 30px; } #ngg-listimages .column-3 { min-width: 80px; width: 15%; } #ngg-listimages .column-3 .thumb { max-height: 100%; max-width: 100%; } #ngg-listimages .column-4 { width: 15%; max-width: 220px; } #ngg-listimages .column-4 { font-size: 12px; } #ngg-listimages .column-4 .meta, #ngg-listimages .column-4 label { font-size: 10px; color: #888; } #ngg-listimages .column-4 label input[type=checkbox] { margin: -2px 4px 0 0; } #ngg-listimages .column-5 input[type=text], #ngg-listimages .column-5 textarea, #ngg-listimages .column-6 textarea { width: 100%; padding: 3px 5px; font-size: 12px; color: #888; border: 1px solid #eee; margin: 1px 0; box-shadow: none; } #ngg-listimages .column-5 input[type=text] { height: 25px; } #ngg-listimages .column-5 textarea { height: 70px; } #ngg-listimages .column-6 textarea { height: 97px; } #ngg-listimages .column-7 select { font-size: 12px; } #ngg-listimages .row-actions { padding: 0 0 6px 4px; margin-bottom: -2px; position: relative; bottom: 4px; left: 0; right: 0; } #ngg-listimages .row_actions, #ngg-listimages .row_actions td { border-top: none; padding: 0 !important; } #ngg-listimages .row-actions a { font-size: 12px; } /* Updating Imagify for color consistency. * To Imagify: hope you guys don't mind, * but given our redesign, we'd like the colors * to be consitent on these pages. */ #ngg-listimages ul.imagify-datas-list .big { color: #9fbb1a; } #ngg-listimages .imagify-datas-more-action a { background: #9fbb1a; color: #fff; } .gallery_page_nggallery-manage-gallery .ui-dialog { border: none; padding: 0; max-width: 95% !important; z-index: 10000 !important; margin: 0 auto !important; } .gallery_page_nggallery-manage-album .ui-dialog { border: none; padding: 0; z-index: 10000 !important; width: 650px !important; max-width: 98% !important; } .gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom button, .gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom .button-primary, .gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom .button-secondary, .gallery_page_nggallery-manage-gallery .ui-dialog button, .gallery_page_nggallery-manage-gallery .ui-dialog .button-primary, .gallery_page_nggallery-manage-gallery .ui-dialog .button-secondary, .gallery_page_nggallery-manage-album .ui-dialog .button-primary, .gallery_page_nggallery-manage-album .ui-dialog .button-secondary { background-color: #9fbb1a !important; color: #fff !important; border: none !important; box-shadow: none !important; text-shadow: none !important; height: 35px !important; padding: 0 15px !important; line-height: 35px; width: auto !important; margin-right: 10px; text-transform: uppercase; letter-spacing: 1px; } .gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom button:hover, .gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom .button-primary:hover, .gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom .button-secondary:hover, .gallery_page_nggallery-manage-gallery .ui-dialog button:hover .gallery_page_nggallery-manage-gallery .ui-dialog .button-primary:hover, .gallery_page_nggallery-manage-gallery .ui-dialog .button-secondary:hover, .gallery_page_nggallery-manage-album .ui-dialog .button-primary:hover, .gallery_page_nggallery-manage-album .ui-dialog .button-secondary:hover { background-color: #A9C524 !important; } .gallery_page_nggallery-manage-gallery .ui-dialog-titlebar, .gallery_page_nggallery-manage-album .ui-dialog-titlebar{ background: black; padding: 10px; } .gallery_page_nggallery-manage-gallery .ui-dialog-titlebar .ui-dialog-title, .gallery_page_nggallery-manage-album .ui-dialog-titlebar .ui-dialog-title { text-transform: uppercase; letter-spacing: 1px; } .gallery_page_nggallery-manage-gallery .ui-dialog-titlebar button, .gallery_page_nggallery-manage-album .ui-dialog-titlebar button { background: #fff !important; border: none !important; box-shadow: none !important; text-shadow: none !important; height: 24px !important; width: 24px !important; padding: 0 !important; line-height: 1; float: none; margin-right: 0; border-radius: 50%; top: 17px; right: 10px; } .gallery_page_nggallery-manage-gallery .ui-dialog-titlebar button:hover, .gallery_page_nggallery-manage-gallery .ui-dialog-titlebar button:active, .gallery_page_nggallery-manage-gallery .ui-dialog-titlebar button:focus, .gallery_page_nggallery-manage-album .ui-dialog-titlebar button:hover, .gallery_page_nggallery-manage-album .ui-dialog-titlebar button:active, .gallery_page_nggallery-manage-album .ui-dialog-titlebar button:focus { background: #fff !important; } .gallery_page_nggallery-manage-gallery .ui-dialog .ngg-overlay-dialog, .gallery_page_nggallery-manage-album .ui-dialog .ngg-overlay-dialog { padding: 30px 20px; box-sizing: border-box; width: 100% !important; } .gallery_page_nggallery-manage-gallery .ngg-overlay-dialog table { border: none; } .gallery_page_nggallery-manage-gallery .ngg-overlay-dialog #ngg-overlay-dialog-main, .gallery_page_nggallery-manage-album .ngg-overlay-dialog #ngg-overlay-dialog-main { width: 70%; padding: 20px 20px 0; } .gallery_page_nggallery-manage-gallery .ngg-overlay-dialog td small { margin-left: 10px; display: block; text-align: center; width: 200px; margin: 0 auto 20px; } .gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom { text-align: center; padding: 30px 0 0 0; } .gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom input[type="button"] { float:none; margin-right: 0; } .gallery_page_nggallery-manage-gallery .ngg-overlay-dialog #thumbMsg { color: #669933; display: none; font-size: 11px; width: 100%; display: inline-block; height: 35px; line-height: 35px; margin: 10px 0; } .gallery_page_nggallery-manage-gallery .ui-dialog form { margin-top: 30px; margin-left: 30px; } .gallery_page_nggallery-manage-gallery .ngg-overlay-dialog input[type=radio]:focus { border: 1px solid #b4b9be; box-shadow: none; } .gallery_page_nggallery-manage-gallery input[type=checkbox]:checked:before { color: #9fbb1a; } .gallery_page_nggallery-manage-gallery .ngg-overlay-dialog input[type=radio]:checked:before { background: #9fbb1a; width: 14px; height: 14px; margin: 0; } /* SETTINGS FOR PROGRESS BAR */ div .progressborder { border:1px solid #DDDDDD; display: block; height: 30px; background-color: #464646; width: 100%; margin-top: 15px; margin-bottom: 15px; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; } div .progressbar { border: medium none ; display: block; height: 30px; background-color: #9fbb1a; width: 0%; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; } div .progressbar span { display: inline; position: absolute; color: white; font-weight: bold; padding: 5px 0 0 5px; } .show_details { height: 16px; line-height: 20px; overflow: hidden; min-width: 8em; padding: 3px; cursor:pointer; } .show_details span { border-bottom:1px solid #999; white-space:pre; } .show_details:hover { height: auto; overflow: visible; border: 1px solid #999; } /* SETTINGS FOR ALBUM PAGE */ .gallery_page_nggallery-manage-album .wrap>h2:first-child { display:none; } .gallery_page_nggallery-manage-album #ngg_page_content div.updated { margin: 0 0 15px 0; } .gallery_page_nggallery-manage-album #ngg_page_content div.updated#message { margin-bottom: 35px; } .ngg_manage_albums .widget { box-sizing: border-box; border: 1px solid #eee; padding: 10px 10px 20px; margin: 0 1% 0 0; width: 100%; } .ngg_manage_albums .widget:last-of-type { margin-right: 0; } .container { margin-top: 10px; } .ngg_manage_albums .container { margin-top: 30px; display: flex; flex-direction: row; justify-content: center; } .ngg_select_album { margin: 0 50px 0 2px; vertical-align: middle; } #newalbum, .ngg_new_album { vertical-align: middle; } .albumnav select[name="act_album"] { width:150px; } #editalbum select[name='pageid'] { width: 95%; } #ngg_page_content .ngg_manage_albums .widget-top { box-shadow: none; background: transparent; border: none; margin: -10px -10px 20px -10px; background: #f7f7f7; } div .groupItem { cursor: move; padding: 2px; line-height: 1.5; width: 100%; margin: 0; box-sizing: border-box; } div .innerhandle { background-color:#FBFBFB; } .groupItem .item_top { background-color:#9fbb1a; color: #FFFFFF; font-weight:400; line-height: 28px; height: 28px; padding: 0 5px; border-radius: 0; height: 40px; padding: 0 10px; line-height: 40px; } #ngg_page_content .groupItem .album_obj { background-color: black; } #ngg_page_content .groupItem .item_top a { color:#FFFFFF; float:right; text-decoration: none; } .groupItem .item_top a:hover { color:#FFFFFF; } .itemContent { border-color:#DFDFDF; border-style:none solid solid; border-width:0 1px 1px; padding:2px 0 20px 2px; } .itemContent p { border: 0; margin: 0; padding: 0; } .inlinepicture { float:left; display:inline; margin:0pt; padding:0pt 3px 1px; } .inlinepicture img { margin:3px; max-height:60px; } .sort_placeholder { border:1px dashed #bba !important; margin: 5px; background: #F9F9F9; } .widget-holder { min-height: 400px; padding-top:1px; } .target { background-color: transparent; } div.widget-top h3 { text-align:center; line-height:25px; margin: 0; padding: 5px 12px; font-size: 13px; letter-spacing: .5px; text-transform: uppercase; } div.widget-top { text-shadow:0 1px 0 #FFFFFF; background-repeat: repeat-x; background-position: 0 0; font-size: 13px; } .ui-autocomplete-start { background-position: 99% center; } /* SETTINGS FOR SORT GALLERY */ #ngg_page_content .ngg_gallery_sort .tablenav { margin: 15px 0; } #ngg_page_content .ngg_gallery_sort ul.subsubsub { margin: 10px 0 15px; } #ngg_page_content .ngg_gallery_sort .imageBox_theImage { width: auto; } #sortGallery { position:relative; } p#sortButton{ margin:0; position:absolute; right:0; top:0; } #ngg-sort-gallery-container { display: flex; flex-wrap: wrap; } .imageBox,.imageBoxHighlighted { width:130px; /* Total width of each image box */ height:160px; /* Total height of each image box */ overflow: hidden; text-overflow: ellipsis; padding: 5px; } .imageBox_theImage{ width:110px; /* Width of image */ height:125px; /* Height of image */ background-position: center; background-repeat: no-repeat; margin: 0 auto; margin-bottom:2px; } .imageBox_label{ /* Title of images - both selected and not selected */ text-align:center; font-family: arial; font-size:11px; padding-top:2px; margin: 0 auto; } /* DIV that indicates where the dragged image will be placed */ #insertionMarker{ height:150px; width:6px; position:absolute; } #insertionMarkerLine{ width:6px; /* No need to change this value */ height:145px; /* To adjust the height of the div that indicates where the dragged image will be dropped */ } #insertionMarker img{ float:left; } /* DIV that shows the image as you drag it */ #dragDropContent{ opacity:0.4; /* 40 % opacity */ filter:alpha(opacity=40); /* 40 % opacity */ /* No need to change these three values */ position:absolute; z-index:10; display:none; } /* UPGRADE PAGE */ .error_inline { background:#FFEBE8 none repeat scroll 0%; border:1px solid #CC0000; margin:5px auto; padding:10px; } /* ABOUT PAGE */ .ngg-list { font-size:11px; margin-left:15px; list-style-position:inside; list-style-type:disc; } #ngg-manage-images-items-per-page-label { float: right; line-height: 35px; margin-right: 5px; } #ngg-manage-images-items-per-page { float: right; margin-right: 30px; } /* Media Queries */ @media (max-width: 1200px) { div[data-id="details-link"] .two-col .col { width: 100%; min-width: 100%; } } @media (max-width: 1420px) { } @media (max-width: 1100px) { } @media (max-width: 1080px) { #ngg-gallery-wizard > span { display: none; } /* Manage Galleries */ .ngg_manage_galleries .tablenav.bottom { display: none; } .ngg_manage_images #gallery_fields td:nth-of-type(even) { margin-bottom: 8px; } .ngg_manage_images #gallery_fields td:nth-of-type(odd) { background: #f7f7f7; padding-left: 10px; font-weight: bold; } .ngg_manage_images #gallery_fields, .ngg_manage_images #gallery_fields tbody, .ngg_manage_images #gallery_fields tr, .ngg_manage_images #gallery_fields td { display:block; width: 100%; box-sizing: border-box; } .ngg_manage_images #gallery_fields td { padding: 10px 5px; border: 1px solid rgb(247, 248, 243); margin: 0; } } @media (max-width: 900px) { .ngg_manage_galleries tfoot { display:none; } .ngg_manage_galleries .wp-list-table tr:not(.inline-edit-row):not(.no-items) td:not(.check-column) { display: table-cell; } .ngg_manage_galleries th#id, .ngg_manage_galleries th#author, .ngg_manage_galleries th#page_id, .ngg_manage_galleries td.id, .ngg_manage_galleries td.author, .ngg_manage_galleries td.page_id { display: none !important; } #ngg-listimages thead .column-1, #ngg-listimages thead .column-2, #ngg-listimages thead .column-4, #ngg-listimages thead .column-5, #ngg-listimages thead .column-6, #ngg-listimages thead .column-7, #ngg-listimages thead .column-8, #ngg-listimages tfoot, #ngg-listimages td.column.column-2, #ngg-listimages td.column.column-8, #ngg-listimages td.column.column-6 { display: none; } #ngg-listimages .column-3 { min-width: 200px; } table#ngg-listimages, table#ngg-listimages thead { display: block; } #ngg-listimages .iedit td { padding-bottom: 30px !important; } } @media (max-width: 800px) { /* Manage Galleries */ table#ngg-listimages, table#ngg-listimages tbody, table#ngg-listimages tr, table#ngg-listimages td { display: block; } table#ngg-listimages tr { padding: 10px 5px !important; } #ngg-listimages thead, #ngg-listimages thead th { display: block; width: 100%; box-sizing: border-box; } #ngg-listimages .row_actions td:first-of-type { display:none; } #ngg-listimages tfoot { display:none; } #ngg-listimages .row_actions { display:none; display:block; clear: both; padding: 0 8px 10px !important; border-bottom: 1px solid #c1c97c; } .ngg-listimages tr.iedit td { display: block !important; float: left; box-sizing: border-box; padding-bottom: 10px !important; } #ngg-listimages td.column-1, #ngg-listimages td.column-2 { width: 10% !important; height: 150px; float: left; box-sizing: border-box; display:none; } #ngg-listimages td.column-3 { width: 55%; max-width: 300px; float: left; box-sizing: border-box; padding-bottom: 10px !important; } #ngg-listimages td.column-4 { width: 40% !important; float: left; box-sizing: border-box; } #ngg-listimages td.column-5, #ngg-listimages td.column-6, #ngg-listimages td.column-7 { padding: 0 5px !important; } #ngg-listimages td.column-6 { margin-top: -5px; margin-bottom: -8px; } .ngg-listimages td.column-7 { padding-bottom: 15px; } #ngg-manage-images-items-per-page, #ngg-manage-images-items-per-page-label { display: none; } #ngg-listimages .column-6 textarea { height: 60px; } .ngg_manage_images .tablenav.bottom .displaying-num { display:none; } } @media (max-width: 782px) { #ngg-gallery-wizard { display: none; } #ngg_page_content .ngg_manage_galleries .tablenav.top > div { display: block; width: 100%; } #ngg_page_content .ngg_manage_galleries .tablenav .tablenav-pages { margin-top: 20px; margin-bottom: 28px !important; } #ngg_page_content .ngg_manage_galleries .search-box input[type=text] { width: calc(100% - 150px) !important; } #ngg_page_content .ngg_manage_galleries .search-box input[type=submit].button-primary { height: 40px !important; } #ngg_page_content .ngg_manage_galleries .search-box-wrapper { flex-direction: column; } #ngg_page_content .ngg_manage_galleries form.search-form { width: 100%; } #ngg_page_content #editgalleries div.tablenav.top div.alignleft.actions input.button-primary { width: auto !important; display: inline-block; } #ngg_page_content #editgalleries div.tablenav.top div.alignleft.actions input.button-primary:first-of-type { margin-left: 5px; } #ngg_page_content #editgalleries div.tablenav.top div.tablenav-pages { display: none; } #ngg_page_content #editgalleries #bulkaction { width: auto !important; } } @media (max-width: 737px) { .gallery_page_nggallery-manage-gallery input[type=checkbox]:checked:before { font-size: 22px; } .ngg-overlay-dialog input[type="radio"] { height: 16px; width: 16px; } #ngg-gallery-wizard { display: none; } } @media (max-width: 640px) { /* Manage Galleries */ .ngg_manage_galleries th#description, .ngg_manage_galleries td.description { display: none !important; } /* Manage Albums */ .ngg_manage_albums .tablenav .actions { width: 100%; float: none; } .ngg_manage_albums .tablenav span { display: block; } .ngg_manage_albums .target-album, .ngg_manage_albums .widget.widget-right { width: 32% !important; margin: .5% !important; padding: 5px 5px 10px; } .groupItem .item_top { height: auto !important; line-height: 1.5; padding: 8px; font-size: 12px; } #ngg_page_content .groupItem .item_top a { display: none; } .ngg_manage_albums div[style="float:right;"] { float: none !important; } .gallery_page_nggallery-manage-gallery .ui-dialog { width: 95% !important; left: 2.5% !important; } .gallery_page_nggallery-manage-gallery .ui-dialog .ngg-overlay-dialog { padding: 30px 10px; } .ngg-overlay-dialog td { display: block; width: 100% !important; padding: 0 !important; } .ngg-overlay-dialog input[type="radio"] { margin: 2px 5px; height: 16px; width: 16px; } } /** * @TODO : Remove all of the following Thickbox specific rules once the Manage Gallery page no longer uses Thickbox. * This whole section was added as an annoying hack workaround to the fact that the Manage Gallery page seemingly cannot * be forced to correctly enqueue thickbox.css when inside of the attach-to-post controller once the latter was refactored * to no longer rely on POPE. */ #TB_overlay { background: #000; opacity: 0.7; filter: alpha(opacity=70); position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 100050; /* Above DFW. */ } #TB_window { position: fixed; background-color: #fff; z-index: 100050; /* Above DFW. */ visibility: hidden; text-align: left; top: 50%; left: 50%; -webkit-box-shadow: 0 3px 6px rgba( 0, 0, 0, 0.3 ); box-shadow: 0 3px 6px rgba( 0, 0, 0, 0.3 ); } #TB_window img#TB_Image { display: block; margin: 15px 0 0 15px; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; border-top: 1px solid #666; border-left: 1px solid #666; } #TB_caption{ height: 25px; padding: 7px 30px 10px 25px; float: left; } #TB_closeWindow { height: 25px; padding: 11px 25px 10px 0; float: right; } #TB_closeWindowButton { position: absolute; left: auto; right: 0; width: 29px; height: 29px; border: 0; padding: 0; background: none; cursor: pointer; outline: none; -webkit-transition: color .1s ease-in-out, background .1s ease-in-out; transition: color .1s ease-in-out, background .1s ease-in-out; } #TB_ajaxWindowTitle { float: left; font-weight: 600; line-height: 29px; overflow: hidden; padding: 0 29px 0 10px; text-overflow: ellipsis; white-space: nowrap; width: calc( 100% - 39px ); } #TB_title { background: #fcfcfc; border-bottom: 1px solid #ddd; height: 29px; } #TB_ajaxContent { clear: both; padding: 2px 15px 15px 15px; overflow: auto; text-align: left; line-height: 1.4em; } #TB_ajaxContent.TB_modal { padding: 15px; } #TB_ajaxContent p { padding: 5px 0px 5px 0px; } #TB_load { position: fixed; display: none; z-index: 100050; top: 50%; left: 50%; background-color: #E8E8E8; border: 1px solid #555; margin: -45px 0 0 -125px; padding: 40px 15px 15px; } #TB_HideSelect { z-index: 99; position: fixed; top: 0; left: 0; background-color: #fff; border: none; filter: alpha(opacity=0); opacity: 0; height: 100%; width: 100%; } #TB_iframeContent { clear: both; border: none; } .tb-close-icon { display: block; color: #666; text-align: center; line-height: 29px; width: 29px; height: 29px; position: absolute; top: 0; right: 0; } .tb-close-icon:before { content: "\f158"; font: normal 20px/29px dashicons; speak: never; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #TB_closeWindowButton:hover .tb-close-icon, #TB_closeWindowButton:focus .tb-close-icon { color: #006799; } #TB_closeWindowButton:focus .tb-close-icon { -webkit-box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8); box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8); } PK! l3Legacy/admin/css/images/ui-icons_cccccc_256x240.pngnu[PNG  IHDRIJPLTENtRNS2P."Tp@f` <BHJZ&0R,4j8D|($ blߝF>n~hhHIDATx]b۶H儒-{iZK:glkn-tIqq? E$dK>$>;PZsVh!Sy0E0}H)-t koܪKp\RϠ .E7 ) *V;~Pe Bx*,=$zDؾ JҸٻ9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;" i] dddddddd4y5  Rb@(8CdŪݡ,@T@ibrq0alX!pe, =4bW { 5Ƭhu~(Q^@3="b5XC@JCT76q_5 @,r šɩD)T|O@ ON-ՙ [n@RXIm݋(F @?=0puL;g$@6η K`>п @h գKVn"a" %l@.v$/U^ G:#`` uTtK~ŋZ5T%kxk]\*Q ,҇B44 OXK|yg+_M(lоEO V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V rh(]tI^}oצo S3 ";ʙb}"߰ ){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.}Q3.Nس})>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa 3 {oB &<L[ Nc.öi=`Q@d ͆I.Il`\t[< Cit484-r +f쑱BCB MH iy }>rxp|z;BǏ;burcK4tz1G~`ؚK| ̔>ۡO$~ Ao)0pzz }i`;ADm8n:cfA@s7L Z/..h8or? N93B~o_'`opO- :TG L;7]`B%˛>*wTpM0H}&t ^1'Oqr'2P͡+z,tIW''|en=dzgRm[NStK{҉mؓVt6ҲR`ζN&}B U(rۗ&1%Q''?l׸+&r{jN಻4) `N狌. ߭ ǣ)q 2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~Mz +4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6GFZ)O !lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5av]m1+3y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c- 賟Lδ>]5.sYs1f0;'̨Yg銛{@9 `aC(=%bo2=n1 jBoS$n#m=i0ci9}oI qT]W%.(؅]z\x f"]o'u䫵tk{v;AC3ֆwwR_#X (xҋ/q%W hpk_IX'b/fXKi"#####QCLi2t 5L0 QiH2;yTOok;ע ٶ`RNg{zy!Kxm?A(vU~mL(`o/!nmX-{v[ dw=n「sdwzn(}Oy~ m ?XU;,V'+ V&JRZ]᧭:zC'-߆@y 4u `Vۓwъ#zP@Q N>2/{\o)W~a3xLw :_Q;=pּdt\'8~3SRP6y+XQ*޺r ̗ѭ*޺r gl/\U^u$|mbVnw \V|D͊NVNy7k<;/E}?E*dzgO ~g/96f cD}% g$QG7o)U Jo,O@0߾Q(;bw:5 NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 3 u Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?sn~hhHIDATx]b۶H儒-{iZK:glkn-tIqq? E$dK>$>;PZsVh!Sy0E0}H)-t koܪKp\RϠ .E7 ) *V;~Pe Bx*,=$zDؾ JҸٻ9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;" i] dddddddd4y5  Rb@(8CdŪݡ,@T@ibrq0alX!pe, =4bW { 5Ƭhu~(Q^@3="b5XC@JCT76q_5 @,r šɩD)T|O@ ON-ՙ [n@RXIm݋(F @?=0puL;g$@6η K`>п @h գKVn"a" %l@.v$/U^ G:#`` uTtK~ŋZ5T%kxk]\*Q ,҇B44 OXK|yg+_M(lоEO V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V rh(]tI^}oצo S3 ";ʙb}"߰ ){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.}Q3.Nس})>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa 3 {oB &<L[ Nc.öi=`Q@d ͆I.Il`\t[< Cit484-r +f쑱BCB MH iy }>rxp|z;BǏ;burcK4tz1G~`ؚK| ̔>ۡO$~ Ao)0pzz }i`;ADm8n:cfA@s7L Z/..h8or? N93B~o_'`opO- :TG L;7]`B%˛>*wTpM0H}&t ^1'Oqr'2P͡+z,tIW''|en=dzgRm[NStK{҉mؓVt6ҲR`ζN&}B U(rۗ&1%Q''?l׸+&r{jN಻4) `N狌. ߭ ǣ)q 2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~Mz +4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6GFZ)O !lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5av]m1+3y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c- 賟Lδ>]5.sYs1f0;'̨Yg銛{@9 `aC(=%bo2=n1 jBoS$n#m=i0ci9}oI qT]W%.(؅]z\x f"]o'u䫵tk{v;AC3ֆwwR_#X (xҋ/q%W hpk_IX'b/fXKi"#####QCLi2t 5L0 QiH2;yTOok;ע ٶ`RNg{zy!Kxm?A(vU~mL(`o/!nmX-{v[ dw=n「sdwzn(}Oy~ m ?XU;,V'+ V&JRZ]᧭:zC'-߆@y 4u `Vۓwъ#zP@Q N>2/{\o)W~a3xLw :_Q;=pּdt\'8~3SRP6y+XQ*޺r ̗ѭ*޺r gl/\U^u$|mbVnw \V|D͊NVNy7k<;/E}?E*dzgO ~g/96f cD}% g$QG7o)U Jo,O@0߾Q(;bw:5 NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 3 u Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s R!!,c $PxB +*-[dඁ+i@ )`L ?'I`JGb Ph XB)0׸XQ# } No "tI+ZI!!,\ $P`8* 1h0rx8BQaV  !MDl!4%BBe PDY00!!,] $$I>Q] d"28 GqH9 A2ȀB", DH('4C \0`UL"r(!! ,d $dI`ìkBB m A72, (PX鲪 8@R%a K*D2E {$ft5C%!;PK!\3Legacy/admin/css/images/ui-icons_ffffff_256x240.pngnu[PNG  IHDRIJPLTE NtRNS2P."Tp@f` <BHJZ&0R,4j8D|($ blߝF>n~hhHIDATx]b۶H儒-{iZK:glkn-tIqq? E$dK>$>;PZsVh!Sy0E0}H)-t koܪKp\RϠ .E7 ) *V;~Pe Bx*,=$zDؾ JҸٻ9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;" i] dddddddd4y5  Rb@(8CdŪݡ,@T@ibrq0alX!pe, =4bW { 5Ƭhu~(Q^@3="b5XC@JCT76q_5 @,r šɩD)T|O@ ON-ՙ [n@RXIm݋(F @?=0puL;g$@6η K`>п @h գKVn"a" %l@.v$/U^ G:#`` uTtK~ŋZ5T%kxk]\*Q ,҇B44 OXK|yg+_M(lоEO V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V rh(]tI^}oצo S3 ";ʙb}"߰ ){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.}Q3.Nس})>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa 3 {oB &<L[ Nc.öi=`Q@d ͆I.Il`\t[< Cit484-r +f쑱BCB MH iy }>rxp|z;BǏ;burcK4tz1G~`ؚK| ̔>ۡO$~ Ao)0pzz }i`;ADm8n:cfA@s7L Z/..h8or? N93B~o_'`opO- :TG L;7]`B%˛>*wTpM0H}&t ^1'Oqr'2P͡+z,tIW''|en=dzgRm[NStK{҉mؓVt6ҲR`ζN&}B U(rۗ&1%Q''?l׸+&r{jN಻4) `N狌. ߭ ǣ)q 2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~Mz +4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6GFZ)O !lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5av]m1+3y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c- 賟Lδ>]5.sYs1f0;'̨Yg銛{@9 `aC(=%bo2=n1 jBoS$n#m=i0ci9}oI qT]W%.(؅]z\x f"]o'u䫵tk{v;AC3ֆwwR_#X (xҋ/q%W hpk_IX'b/fXKi"#####QCLi2t 5L0 QiH2;yTOok;ע ٶ`RNg{zy!Kxm?A(vU~mL(`o/!nmX-{v[ dw=n「sdwzn(}Oy~ m ?XU;,V'+ V&JRZ]᧭:zC'-߆@y 4u `Vۓwъ#zP@Q N>2/{\o)W~a3xLw :_Q;=pּdt\'8~3SRP6y+XQ*޺r ̗ѭ*޺r gl/\U^u$|mbVnw \V|D͊NVNy7k<;/E}?E*dzgO ~g/96f cD}% g$QG7o)U Jo,O@0߾Q(;bw:5 NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 3 u Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?sh2:first-child{display:none}.gallery_page_nggallery-tags #ngg_page_content div.updated{margin:0 0 15px 0}.gallery_page_nggallery-tags #ngg_page_content div.updated#message{margin-bottom:35px}.ngg_manage_tags,.ngg_manage_tags label{color:#666}.ngg_wrap .auto_list{width:98%;margin:3px 0;padding:3px 5px}.ngg_wrap .list_tags{width:280px;vertical-align:top;padding:20px!important;background:#f7f7f7}.ngg_wrap .list_tags #search{width:200px}.ngg_wrap .list_tags .navigation{margin:25px 0 20px}#ngg_page_content .list_tags .navigation .button-primary{width:48%!important;text-align:center;margin:.5%;font-size:9px;padding:0!important}.ngg_wrap .forms_manage{vertical-align:top;padding-left:30px}.ngg_wrap .forms_manage h3{margin-bottom:5px;margin-top:30px}.ngg_wrap .forms_manage td{padding:0}.ngg_wrap .forms_manage td p{margin-bottom:20px}.ngg_wrap .forms_manage .form-table{margin-top:0}.ngg_wrap .forms_manage .form-table td,.ngg_wrap .forms_manage .form-table th{vertical-align:middle;padding:0}.ngg_wrap .sort_order h3{margin:30px 0 10px}.ngg_wrap #ajax_area_tagslist ul{list-style:square;margin:10px 0 10px 20px;padding:0}.ngg_wrap #ajax_area_tagslist ul li{margin:0;padding:0;line-height:1.4}.ngg_wrap #ajax_area_tagslist ul li span{cursor:pointer}@media (max-width:640px){.ngg_wrap .list_tags{width:100%;display:block;box-sizing:border-box}.ngg_wrap .forms_manage{width:100%;display:block;box-sizing:border-box;padding:20px}.ngg_wrap .list_tags #search{width:200px;width:100%}}PK!O<<Legacy/admin/css/tags-admin.cssnu[.gallery_page_nggallery-tags .wrap>h2:first-child { display:none; } .gallery_page_nggallery-tags #ngg_page_content div.updated { margin: 0 0 15px 0; } .gallery_page_nggallery-tags #ngg_page_content div.updated#message { margin-bottom: 35px; } .ngg_manage_tags, .ngg_manage_tags label { color: #666; } .ngg_wrap .auto_list{ width: 98%; margin: 3px 0; padding: 3px 5px; } .ngg_wrap .list_tags { width: 280px; vertical-align: top; padding: 20px !important; background: #f7f7f7; } .ngg_wrap .list_tags #search{ width: 200px; } .ngg_wrap .list_tags .navigation { margin: 25px 0 20px; } #ngg_page_content .list_tags .navigation .button-primary { width: 48% !important; text-align: center; margin: 0.5%; font-size: 9px; padding: 0 !important; } .ngg_wrap .forms_manage { vertical-align: top; padding-left: 30px; } .ngg_wrap .forms_manage h3 { margin-bottom: 5px; margin-top: 30px; } .ngg_wrap .forms_manage td { padding: 0; } .ngg_wrap .forms_manage td p { margin-bottom: 20px; } .ngg_wrap .forms_manage .form-table { margin-top: 0; } .ngg_wrap .forms_manage .form-table th, .ngg_wrap .forms_manage .form-table td { vertical-align: middle; padding: 0; } /*.ngg_wrap .forms_manage .form-table tr:nth-of-type(2) th, .ngg_wrap .forms_manage .form-table tr:nth-of-type(3) th { padding-left: 20px; }*/ .ngg_wrap .sort_order h3 { margin: 30px 0 10px; } .ngg_wrap #ajax_area_tagslist ul { list-style: square; margin: 10px 0 10px 20px; padding: 0; } .ngg_wrap #ajax_area_tagslist ul li { margin: 0; padding: 0; line-height: 1.4; } .ngg_wrap #ajax_area_tagslist ul li span { cursor: pointer; } /* Media Queries */ @media (max-width: 640px) { .ngg_wrap .list_tags { width: 100%; display: block; box-sizing: border-box; } .ngg_wrap .forms_manage { width: 100%; display: block; box-sizing: border-box; padding: 20px; } .ngg_wrap .list_tags #search { width: 200px; width: 100%; } }PK! k//Legacy/admin/css/nggSorter.cssnu[.imageBox,.imageBoxHighlighted{ width:130px; /* Total width of each image box */ height:160px; /* Total height of each image box */ float:left; } .imageBox_theImage{ width:110px; /* Width of image */ height:125px; /* Height of image */ /* Don't change these values * */ background-position: center; background-repeat: no-repeat; margin: 0 auto; margin-bottom:2px; } .imageBox .imageBox_theImage{ border:1px solid #DDD; /* Border color for not selected images */ padding:2px; } .imageBoxHighlighted .imageBox_theImage{ border:3px solid #316AC5; /* Border color for selected image */ padding:0px; } .imageBoxHighlighted span{ /* Title of selected image */ background-color: #316AC5; color:#FFFFFF; padding:2px; } .imageBox_label{ /* Title of images - both selected and not selected */ text-align:center; font-family: arial; font-size:11px; padding-top:2px; margin: 0 auto; } /* DIV that indicates where the dragged image will be placed */ #insertionMarker{ height:150px; width:6px; position:absolute; } #insertionMarkerLine{ width:6px; /* No need to change this value */ height:145px; /* To adjust the height of the div that indicates where the dragged image will be dropped */ } #insertionMarker img{ float:left; } /* DIV that shows the image as you drag it */ #dragDropContent{ opacity:0.4; /* 40 % opacity */ filter:alpha(opacity=40); /* 40 % opacity */ /* No need to change these three values */ position:absolute; z-index:10; display:none; }PK!#Legacy/admin/css/jquery.ui.tabs.cssnu[/* Caution! Ensure accessibility in print and other media types... */ @media projection, screen { /* Use class for showing/hiding tab content, so that visibility can be better controlled in different media types... */ .ui-tabs-hide { display: none; } } /* Hide useless elements in print layouts... */ @media print { .ui-tabs-nav { display: none; } } /* Skin */ #slider { border-color:#EBEBEB rgb(204, 204, 204) rgb(204, 204, 204) rgb(235, 235, 235); border-style:solid; border-width:1px; margin:15px 15% 0pt 15px; padding:2px; } #tabs{ display: block; background:#F1F1F1 none repeat scroll 0%; font-size:14px; overflow:hidden; } .ui-tabs-nav { list-style: none; margin: 0; padding: 0 0 0 10px; } .ui-tabs-nav:after { /* clearing without presentational markup, IE gets extra treatment */ display: block; clear: both; content: " "; } .ui-tabs-nav li { float: left; padding: 6px 5px; min-width: 84px; /* be nice to Opera */ margin: 2px 2px 0px 1px !important; text-decoration: none; list-style: none; } .ui-tabs-nav a, .ui-tabs-nav a span { display: block; padding: 0 1px; } .ui-tabs-nav a { margin: 1px 0 0; /* position: relative makes opacity fail for disabled tab in IE */ padding-left: 0; color: #2583AD; line-height: 1.2; text-align: center; text-decoration: none; white-space: nowrap; /* required in IE 6 */ outline: 0; /* prevent dotted border in Firefox */ } .ui-tabs-nav .ui-tabs-selected{ background: #6D6D6D url(../images/menu-bits.gif) repeat-x scroll left top; border-color: #6D6D6D; color: #FFFFFF; text-shadow:0 -1px 0 #666666; -moz-border-radius-topright: 6px; -khtml-border-top-right-radius: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; -moz-border-radius-topleft: 6px; -khtml-border-top-left-radius: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; } .ui-tabs-selected a, .ui-tabs-selected a:hover { color:#FFFFFF !important; } .ui-tabs-nav .ui-tabs-selected a, .ui-tabs-nav .ui-tabs-selected a:hover { position: relative; top: 1px; z-index: 2; margin-top: 0; } .ui-tabs-nav li a:hover { color:#D54E21; } .ui-tabs-nav a span { width: 64px; /* IE 6 treats width as min-width */ min-width: 64px; height: 18px; /* IE 6 treats height as min-height */ min-height: 18px; padding-top: 6px; padding-right: 0; } *>.ui-tabs-nav a span { /* hide from IE 6 */ width: auto; height: auto; } .ui-tabs-nav .ui-tabs-selected a span { padding-bottom: 1px; } .ui-tabs-nav .ui-tabs-selected a, .ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active { background-position: 100% -150px; } .ui-tabs-nav a, .ui-tabs-nav .ui-tabs-disabled a:hover, .ui-tabs-nav .ui-tabs-disabled a:focus, .ui-tabs-nav .ui-tabs-disabled a:active { background-position: 100% -100px; } .ui-tabs-nav .ui-tabs-selected a span, .ui-tabs-nav a:hover span, .ui-tabs-nav a:focus span, .ui-tabs-nav a:active span { background-position: 0 -50px; } .ui-tabs-nav a span, .ui-tabs-nav .ui-tabs-disabled a:hover span, .ui-tabs-nav .ui-tabs-disabled a:focus span, .ui-tabs-nav .ui-tabs-disabled a:active span { background-position: 0 0; } .ui-tabs-nav .ui-tabs-selected a:link, .ui-tabs-nav .ui-tabs-selected a:visited, .ui-tabs-nav .ui-tabs-disabled a:link, .ui-tabs-nav .ui-tabs-disabled a:visited { /* @ Opera, use pseudo classes otherwise it confuses cursor... */ cursor: text; } .ui-tabs-nav a:hover, .ui-tabs-nav a:focus, .ui-tabs-nav a:active, .ui-tabs-nav .ui-tabs-unselect a:hover, .ui-tabs-nav .ui-tabs-unselect a:focus, .ui-tabs-nav .ui-tabs-unselect a:active { /* @ Opera, we need to be explicit again here now... */ cursor: pointer; } .ui-tabs-disabled { opacity: .4; filter: alpha(opacity=40); } .ui-tabs-panel { border-top: 1px solid #97a5b0 !important; padding: 1em 8px; background: #fff; /* declare background color for container to avoid distorted fonts in IE while fading */ /* overwrite wp-admin */ border:none !important; height:100% !important; margin:0pt 0pt 0pt 0px !important; overflow:visible !important; } .ui-tabs-panel a { display:inline; } /* Additional IE specific bug fixes... */ * html .ui-tabs-nav { /* auto clear, @ IE 6 & IE 7 Quirks Mode */ display: inline-block; } *:first-child+html .ui-tabs-nav { /* @ IE 7 Standards Mode - do not group selectors, otherwise IE 6 will ignore complete rule (because of the unknown + combinator)... */ display: inline-block; } PK! ;;#Legacy/admin/css/nggColorPicker.cssnu[#colorSelector{ background:transparent url(../images/select.png) repeat scroll 0 0; height:36px; position:relative; width:36px; } #colorSelector div{ background:transparent url(../images/select.png) repeat scroll center center; height:30px; left:3px; position:absolute; top:3px; width:30px; }PK!X0ee!Legacy/admin/css/nggadmin.min.cssnu[#iframely h2.title{display:none}.toplevel_page_nextgen-gallery #ngg_page_content{width:98%}.toplevel_page_nextgen-gallery #ngg_page_content .about-wrap.ngg_overview{width:100%}.toplevel_page_nextgen-gallery #ngg_page_content .ngg_page_content_main{padding-right:40px!important}#newversion{border-color:#ccc;border-style:solid;border-width:1px;margin-right:7px;margin-top:10px;padding:2px}.ngg-dashboard-widget ul.settings span{padding-left:10px;color:#2583ad;font-weight:700}.ngg-overview .postbox .handlediv{float:right;height:24px;width:24px}#ngg_page_content .ngg_overview .ngg_page_content_header h2{padding-top:2px}#ngg_page_content .ngg_overview .ngg_page_content_main h2{text-align:left;font-size:22px;font-weight:400;color:#000;margin:20px 0 20px;text-transform:uppercase;letter-spacing:2px}#ngg_page_content .ngg_overview .ngg_page_content_main .about-text{font-size:17px;max-width:none;margin:20px 0;color:#000;font-weight:400}#ngg-gallery-wizard{min-height:auto;position:absolute;top:0;right:0;text-align:right;margin:0 20px 0 0;line-height:80px;color:#fff;font-size:14px;margin-right:0;color:#000;font-weight:400;letter-spacing:.5px}#ngg_page_content #ngg-gallery-wizard a{font-weight:700;text-decoration:none;margin-left:20px;height:50px!important;line-height:50px}.warning{color:#9f6000;background-color:#feefb3;border:1px solid;margin:5px 0;padding:5px}#donator_message{margin:5px 0 15px;background-color:#bde5f8;border-color:#00529b;-moz-border-radius-bottomleft:3px;-moz-border-radius-bottomright:3px;-moz-border-radius-topleft:3px;-moz-border-radius-topright:3px;border-style:solid;border-width:1px;margin:5px 15px 2px;padding:0 .6em}#donator_message p{line-height:1;margin:.5em 0;padding:2px;padding-bottom:10px}#donator_message span{padding-top:10px;float:right}#plugin_check img{float:right}#plugin_check p.message{font-size:90%;color:#666}.toplevel_page_nextgen-gallery .feature-video iframe{box-shadow:0 0 8px 4px rgba(0,0,0,.03);width:800px;height:450px;max-width:100%}div[data-id=welcome-link] .about-text{margin:0 0 40px!important}div[data-id=pro-link] .feature-section{position:relative;margin:40px 0;padding-bottom:56.25%}div[data-id=pro-link] .feature-section iframe{width:900px;height:506px;max-width:100%;position:absolute;top:0;left:0;width:100%;height:100%}#ngg_page_content .button-primary.ngg-pro-upgrade{height:50px!important;padding:0 40px!important;line-height:50px}div[data-id=genesis-link] .feature-section,div[data-id=genesis-link] .feature-section .col,div[data-id=videos-link] .feature-section,div[data-id=videos-link] .feature-section .col{padding:0;margin:0}.ngg-admin .ui-dialog{max-width:100%}.ngg-options th{width:22%}a.switch-expert{text-decoration:none}#wm-preview{float:right;font-size:90%;width:35%;border-color:#ebebeb #ccc #ccc #ebebeb;border-style:solid;border-width:1px;margin-bottom:10px;margin-left:10px;margin-right:8px;padding:2px}#wm-preview h3{background:#f9f9f9 none repeat scroll 0;font-size:14px;font-weight:700;margin:0 0 10px;padding:8px 5px}#wm-position{width:100%;margin-left:40px}.wm-table{border-collapse:collapse;margin-top:1em;width:60%;clear:none}.wm-table td{border-bottom:8px solid #fff;line-height:20px;margin-bottom:9px;padding:10px}.wm-table th{border-bottom:8px solid #fff;padding:10px;text-align:left}.wm-table tr{background:#f9f9f9 none repeat scroll 0}.ngg-admin.gallery_page_nggallery-manage-gallery #ngg_page_content .notice,.ngg-admin.gallery_page_nggallery-manage-gallery #ngg_page_content div.error,.ngg-admin.gallery_page_nggallery-manage-gallery #ngg_page_content div.updated{margin:10px 0 40px 0}.ngg_admin_notice ul{list-style:circle inside;margin:0;padding:0}.gallery_page_nggallery-manage-gallery #ngg_page_content .ngg_page_content_main{padding-top:30px}.ngg-admin.gallery_page_nggallery-manage-gallery #ngg_page_content div.updated#message{margin-bottom:35px}.gallery_page_nggallery-manage-gallery #ngg_page_content>.wrap>h2{display:none}#ngg_page_content .ngg_manage_galleries .tablenav{margin:0 0 30px}#ngg_page_content .ngg_manage_images .handlediv{float:none;width:100%;height:50px}#gallerydiv h3{margin-left:10px;display:inline-block;height:50px;float:left;margin:0;line-height:50px;text-transform:uppercase;font-size:16px;letter-spacing:1.5px}#gallerydiv span.toggle-indicator{display:inline-block;float:left;line-height:50px}#gallerydiv span.toggle-indicator:before{font-size:24px;margin:12px 20px 0 10px}#gallerydiv span.toggle-indicator:hover{cursor:pointer}#gallerydiv h3:active,#gallerydiv h3:focus,#gallerydiv span.toggle-indicator:active,#gallerydiv span.toggle-indicator:focus{outline:0;border:none;-moz-outline-style:none}#ngg_page_content .ngg_manage_images .tablenav{margin:50px 0 30px}#ngg_page_content .ngg_manage_galleries .tablenav.top>div,#ngg_page_content .ngg_manage_images .tablenav.top>div{margin-bottom:10px}#ngg_page_content .ngg_manage_galleries .search-box-wrapper{display:flex;flex-direction:row;justify-content:center;width:100%}#ngg_page_content .ngg_manage_galleries div.search-box{display:flex;flex-direction:row;justify-content:center}#ngg_page_content .ngg_manage_galleries .search-box input[type=text]{width:calc(100% - 150px)!important;height:35px!important;margin-right:4px!important}#ngg_page_content .ngg_manage_galleries .search-box input[type=submit].button-primary{width:150px!important;height:35px!important;padding:0!important}#ngg_page_content .ngg_manage_galleries form.search-form{width:100%}#ngg_page_content .ngg_manage_galleries form.search-form:first-of-type{padding-right:25px}#ngg_page_content #editgalleries .displaying-num{margin-right:7px!important;font-size:14px;letter-spacing:1px}#ngg_page_content #editgalleries #bulkaction{min-height:35px;max-height:35px}#ngg_page_content .ngg_manage_galleries .tablenav.bottom{margin:15px 0 0}#ngg_page_content .ngg_manage_images .tablenav.bottom{margin:25px 0 0}.ngg-admin #ngg_page_content .ngg_manage_images td{vertical-align:top}#ngg_page_content .ngg_manage_galleries .tablenav input{height:28px;width:50px;padding:0 3px}#ngg_page_content .ngg_manage_galleries .tablenav input.current-page{width:50px!important}#ngg_page_content .ngg_manage_images .tablenav .tablenav-pages{margin-top:0}#ngg_page_content .ngg_manage_galleries .tablenav .tablenav-pages{margin-top:6px}#ngg_page_content .ngg_manage_galleries .tablenav .tablenav-pages a,#ngg_page_content .ngg_manage_images .tablenav .tablenav-pages a{background:#000;border:none;color:#fff!important;margin:0 2px;text-decoration:none;font-size:20px;padding:4px;line-height:20px;padding:2px 8px 6px 8px}#ngg_page_content .ngg_manage_images .tablenav input,#ngg_page_content .ngg_manage_images .tablenav select{width:auto;margin-top:0}#ngg_page_content #ngg-manage-images-items-per-page,#ngg_page_content .ngg_manage_images .tablenav input.current-page{padding:4px!important;text-align-last:center;background-image:none}#ngg_page_content .ngg_manage_galleries table{box-shadow:none;border:1px solid rgba(159,187,26,.08)!important}#ngg_page_content .ngg_manage_galleries table tfoot,#ngg_page_content .ngg_manage_galleries table thead{background-color:#000}#ngg_page_content .ngg_manage_galleries table tfoot td,#ngg_page_content .ngg_manage_galleries table tfoot th,#ngg_page_content .ngg_manage_galleries table thead td,#ngg_page_content .ngg_manage_galleries table thead th{background-color:transparent;border:none}#ngg_page_content .ngg_manage_galleries table td,#ngg_page_content .ngg_manage_galleries table th{padding:12px 10px;font-size:14px}#ngg_page_content .ngg_manage_galleries table th{font-weight:700!important;color:#fff}.ngg_manage_galleries th#id{width:33px}.ngg_manage_galleries th#title{min-width:140px}.ngg_manage_galleries td.title{text-transform:uppercase;font-weight:400;font-size:13px!important}.ngg_manage_galleries th#author{min-width:80px}.ngg_manage_galleries th#page_id{min-width:60px}#ngg_page_content .ngg_manage_galleries table tr.alternate{background-color:#f7f7f7}#ngg_page_content .ngg_manage_galleries th a{padding:0!important;color:#fff}div#poststuff{min-width:auto}div#poststuff #gallerydiv{cursor:pointer}p#ngg-inlinebutton{float:right;margin:0;position:relative;top:-25pt}#gallery_fields{width:100%}#gallery_fields td{padding:5px;min-width:105px}#gallery_fields tr td:nth-of-type(2){padding-right:60px}#gallery_fields input[type=text],#gallery_fields select,#gallery_fields textarea{min-width:220px;width:99%;color:#888}table#ngg-listimages{border:1px solid #f7f7f7}#ngg-listimages tfoot,#ngg-listimages thead{background:#000}#ngg-listimages tfoot{background:#000}#ngg-listimages.widefat thead th,.ngg-admin #ngg_page_content .widefat tfoot th{padding:12px 10px!important}#ngg-listimages tr.alternate{background-color:#f7f7f7}#ngg-listimages td{padding:15px 5px!important}#ngg-listimages .iedit,#ngg-listimages .iedit td,#ngg-listimages th{border:none}#ngg-listimages .iedit td,#ngg-listimages th{padding:15px 5px}#ngg-listimages th{font-size:12px;font-weight:700}#ngg-listimages .column select{width:100%!important}#ngg-listimages .column-1 input{margin:0 0 0 8px}#ngg-listimages .column-1{width:24px}#ngg-listimages .column-2{width:30px}#ngg-listimages .column-3{min-width:80px;width:15%}#ngg-listimages .column-3 .thumb{max-height:100%;max-width:100%}#ngg-listimages .column-4{width:15%;max-width:220px}#ngg-listimages .column-4{font-size:12px}#ngg-listimages .column-4 .meta,#ngg-listimages .column-4 label{font-size:10px;color:#888}#ngg-listimages .column-4 label input[type=checkbox]{margin:-2px 4px 0 0}#ngg-listimages .column-5 input[type=text],#ngg-listimages .column-5 textarea,#ngg-listimages .column-6 textarea{width:100%;padding:3px 5px;font-size:12px;color:#888;border:1px solid #eee;margin:1px 0;box-shadow:none}#ngg-listimages .column-5 input[type=text]{height:25px}#ngg-listimages .column-5 textarea{height:70px}#ngg-listimages .column-6 textarea{height:97px}#ngg-listimages .column-7 select{font-size:12px}#ngg-listimages .row-actions{padding:0 0 6px 4px;margin-bottom:-2px;position:relative;bottom:4px;left:0;right:0}#ngg-listimages .row_actions,#ngg-listimages .row_actions td{border-top:none;padding:0!important}#ngg-listimages .row-actions a{font-size:12px}#ngg-listimages ul.imagify-datas-list .big{color:#9fbb1a}#ngg-listimages .imagify-datas-more-action a{background:#9fbb1a;color:#fff}.gallery_page_nggallery-manage-gallery .ui-dialog{border:none;padding:0;max-width:95%!important;z-index:10000!important;margin:0 auto!important}.gallery_page_nggallery-manage-album .ui-dialog{border:none;padding:0;z-index:10000!important;width:650px!important;max-width:98%!important}.gallery_page_nggallery-manage-album .ui-dialog .button-primary,.gallery_page_nggallery-manage-album .ui-dialog .button-secondary,.gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom .button-primary,.gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom .button-secondary,.gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom button,.gallery_page_nggallery-manage-gallery .ui-dialog .button-primary,.gallery_page_nggallery-manage-gallery .ui-dialog .button-secondary,.gallery_page_nggallery-manage-gallery .ui-dialog button{background-color:#9fbb1a!important;color:#fff!important;border:none!important;box-shadow:none!important;text-shadow:none!important;height:35px!important;padding:0 15px!important;line-height:35px;width:auto!important;margin-right:10px;text-transform:uppercase;letter-spacing:1px}.gallery_page_nggallery-manage-album .ui-dialog .button-primary:hover,.gallery_page_nggallery-manage-album .ui-dialog .button-secondary:hover,.gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom .button-primary:hover,.gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom .button-secondary:hover,.gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom button:hover,.gallery_page_nggallery-manage-gallery .ui-dialog .button-secondary:hover,.gallery_page_nggallery-manage-gallery .ui-dialog button:hover .gallery_page_nggallery-manage-gallery .ui-dialog .button-primary:hover{background-color:#a9c524!important}.gallery_page_nggallery-manage-album .ui-dialog-titlebar,.gallery_page_nggallery-manage-gallery .ui-dialog-titlebar{background:#000;padding:10px}.gallery_page_nggallery-manage-album .ui-dialog-titlebar .ui-dialog-title,.gallery_page_nggallery-manage-gallery .ui-dialog-titlebar .ui-dialog-title{text-transform:uppercase;letter-spacing:1px}.gallery_page_nggallery-manage-album .ui-dialog-titlebar button,.gallery_page_nggallery-manage-gallery .ui-dialog-titlebar button{background:#fff!important;border:none!important;box-shadow:none!important;text-shadow:none!important;height:24px!important;width:24px!important;padding:0!important;line-height:1;float:none;margin-right:0;border-radius:50%;top:17px;right:10px}.gallery_page_nggallery-manage-album .ui-dialog-titlebar button:active,.gallery_page_nggallery-manage-album .ui-dialog-titlebar button:focus,.gallery_page_nggallery-manage-album .ui-dialog-titlebar button:hover,.gallery_page_nggallery-manage-gallery .ui-dialog-titlebar button:active,.gallery_page_nggallery-manage-gallery .ui-dialog-titlebar button:focus,.gallery_page_nggallery-manage-gallery .ui-dialog-titlebar button:hover{background:#fff!important}.gallery_page_nggallery-manage-album .ui-dialog .ngg-overlay-dialog,.gallery_page_nggallery-manage-gallery .ui-dialog .ngg-overlay-dialog{padding:30px 20px;box-sizing:border-box;width:100%!important}.gallery_page_nggallery-manage-gallery .ngg-overlay-dialog table{border:none}.gallery_page_nggallery-manage-album .ngg-overlay-dialog #ngg-overlay-dialog-main,.gallery_page_nggallery-manage-gallery .ngg-overlay-dialog #ngg-overlay-dialog-main{width:70%;padding:20px 20px 0}.gallery_page_nggallery-manage-gallery .ngg-overlay-dialog td small{margin-left:10px;display:block;text-align:center;width:200px;margin:0 auto 20px}.gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom{text-align:center;padding:30px 0 0 0}.gallery_page_nggallery-manage-gallery #ngg-overlay-dialog-bottom input[type=button]{float:none;margin-right:0}.gallery_page_nggallery-manage-gallery .ngg-overlay-dialog #thumbMsg{color:#693;display:none;font-size:11px;width:100%;display:inline-block;height:35px;line-height:35px;margin:10px 0}.gallery_page_nggallery-manage-gallery .ui-dialog form{margin-top:30px;margin-left:30px}.gallery_page_nggallery-manage-gallery .ngg-overlay-dialog input[type=radio]:focus{border:1px solid #b4b9be;box-shadow:none}.gallery_page_nggallery-manage-gallery input[type=checkbox]:checked:before{color:#9fbb1a}.gallery_page_nggallery-manage-gallery .ngg-overlay-dialog input[type=radio]:checked:before{background:#9fbb1a;width:14px;height:14px;margin:0}div .progressborder{border:1px solid #ddd;display:block;height:30px;background-color:#464646;width:100%;margin-top:15px;margin-bottom:15px;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}div .progressbar{border:medium none;display:block;height:30px;background-color:#9fbb1a;width:0%;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}div .progressbar span{display:inline;position:absolute;color:#fff;font-weight:700;padding:5px 0 0 5px}.show_details{height:16px;line-height:20px;overflow:hidden;min-width:8em;padding:3px;cursor:pointer}.show_details span{border-bottom:1px solid #999;white-space:pre}.show_details:hover{height:auto;overflow:visible;border:1px solid #999}.gallery_page_nggallery-manage-album .wrap>h2:first-child{display:none}.gallery_page_nggallery-manage-album #ngg_page_content div.updated{margin:0 0 15px 0}.gallery_page_nggallery-manage-album #ngg_page_content div.updated#message{margin-bottom:35px}.ngg_manage_albums .widget{box-sizing:border-box;border:1px solid #eee;padding:10px 10px 20px;margin:0 1% 0 0;width:100%}.ngg_manage_albums .widget:last-of-type{margin-right:0}.container{margin-top:10px}.ngg_manage_albums .container{margin-top:30px;display:flex;flex-direction:row;justify-content:center}.ngg_select_album{margin:0 50px 0 2px;vertical-align:middle}#newalbum,.ngg_new_album{vertical-align:middle}.albumnav select[name=act_album]{width:150px}#editalbum select[name=pageid]{width:95%}#ngg_page_content .ngg_manage_albums .widget-top{box-shadow:none;background:0 0;border:none;margin:-10px -10px 20px -10px;background:#f7f7f7}div .groupItem{cursor:move;padding:2px;line-height:1.5;width:100%;margin:0;box-sizing:border-box}div .innerhandle{background-color:#fbfbfb}.groupItem .item_top{background-color:#9fbb1a;color:#fff;font-weight:400;line-height:28px;height:28px;padding:0 5px;border-radius:0;height:40px;padding:0 10px;line-height:40px}#ngg_page_content .groupItem .album_obj{background-color:#000}#ngg_page_content .groupItem .item_top a{color:#fff;float:right;text-decoration:none}.groupItem .item_top a:hover{color:#fff}.itemContent{border-color:#dfdfdf;border-style:none solid solid;border-width:0 1px 1px;padding:2px 0 20px 2px}.itemContent p{border:0;margin:0;padding:0}.inlinepicture{float:left;display:inline;margin:0;padding:0 3px 1px}.inlinepicture img{margin:3px;max-height:60px}.sort_placeholder{border:1px dashed #bba!important;margin:5px;background:#f9f9f9}.widget-holder{min-height:400px;padding-top:1px}.target{background-color:transparent}div.widget-top h3{text-align:center;line-height:25px;margin:0;padding:5px 12px;font-size:13px;letter-spacing:.5px;text-transform:uppercase}div.widget-top{text-shadow:0 1px 0 #fff;background-repeat:repeat-x;background-position:0 0;font-size:13px}.ui-autocomplete-start{background-position:99% center}#ngg_page_content .ngg_gallery_sort .tablenav{margin:15px 0}#ngg_page_content .ngg_gallery_sort ul.subsubsub{margin:10px 0 15px}#ngg_page_content .ngg_gallery_sort .imageBox_theImage{width:auto}#sortGallery{position:relative}p#sortButton{margin:0;position:absolute;right:0;top:0}#ngg-sort-gallery-container{display:flex;flex-wrap:wrap}.imageBox,.imageBoxHighlighted{width:130px;height:160px;overflow:hidden;text-overflow:ellipsis;padding:5px}.imageBox_theImage{width:110px;height:125px;background-position:center;background-repeat:no-repeat;margin:0 auto;margin-bottom:2px}.imageBox_label{text-align:center;font-family:arial;font-size:11px;padding-top:2px;margin:0 auto}#insertionMarker{height:150px;width:6px;position:absolute}#insertionMarkerLine{width:6px;height:145px}#insertionMarker img{float:left}#dragDropContent{opacity:.4;position:absolute;z-index:10;display:none}.error_inline{background:#ffebe8 none repeat scroll 0;border:1px solid #c00;margin:5px auto;padding:10px}.ngg-list{font-size:11px;margin-left:15px;list-style-position:inside;list-style-type:disc}#ngg-manage-images-items-per-page-label{float:right;line-height:35px;margin-right:5px}#ngg-manage-images-items-per-page{float:right;margin-right:30px}@media (max-width:1200px){div[data-id=details-link] .two-col .col{width:100%;min-width:100%}}@media (max-width:1080px){#ngg-gallery-wizard>span{display:none}.ngg_manage_galleries .tablenav.bottom{display:none}.ngg_manage_images #gallery_fields td:nth-of-type(even){margin-bottom:8px}.ngg_manage_images #gallery_fields td:nth-of-type(odd){background:#f7f7f7;padding-left:10px;font-weight:700}.ngg_manage_images #gallery_fields,.ngg_manage_images #gallery_fields tbody,.ngg_manage_images #gallery_fields td,.ngg_manage_images #gallery_fields tr{display:block;width:100%;box-sizing:border-box}.ngg_manage_images #gallery_fields td{padding:10px 5px;border:1px solid #f7f8f3;margin:0}}@media (max-width:900px){.ngg_manage_galleries tfoot{display:none}.ngg_manage_galleries .wp-list-table tr:not(.inline-edit-row):not(.no-items) td:not(.check-column){display:table-cell}.ngg_manage_galleries td.author,.ngg_manage_galleries td.id,.ngg_manage_galleries td.page_id,.ngg_manage_galleries th#author,.ngg_manage_galleries th#id,.ngg_manage_galleries th#page_id{display:none!important}#ngg-listimages td.column.column-2,#ngg-listimages td.column.column-6,#ngg-listimages td.column.column-8,#ngg-listimages tfoot,#ngg-listimages thead .column-1,#ngg-listimages thead .column-2,#ngg-listimages thead .column-4,#ngg-listimages thead .column-5,#ngg-listimages thead .column-6,#ngg-listimages thead .column-7,#ngg-listimages thead .column-8{display:none}#ngg-listimages .column-3{min-width:200px}table#ngg-listimages,table#ngg-listimages thead{display:block}#ngg-listimages .iedit td{padding-bottom:30px!important}}@media (max-width:800px){table#ngg-listimages,table#ngg-listimages tbody,table#ngg-listimages td,table#ngg-listimages tr{display:block}table#ngg-listimages tr{padding:10px 5px!important}#ngg-listimages thead,#ngg-listimages thead th{display:block;width:100%;box-sizing:border-box}#ngg-listimages .row_actions td:first-of-type{display:none}#ngg-listimages tfoot{display:none}#ngg-listimages .row_actions{display:none;display:block;clear:both;padding:0 8px 10px!important;border-bottom:1px solid #c1c97c}.ngg-listimages tr.iedit td{display:block!important;float:left;box-sizing:border-box;padding-bottom:10px!important}#ngg-listimages td.column-1,#ngg-listimages td.column-2{width:10%!important;height:150px;float:left;box-sizing:border-box;display:none}#ngg-listimages td.column-3{width:55%;max-width:300px;float:left;box-sizing:border-box;padding-bottom:10px!important}#ngg-listimages td.column-4{width:40%!important;float:left;box-sizing:border-box}#ngg-listimages td.column-5,#ngg-listimages td.column-6,#ngg-listimages td.column-7{padding:0 5px!important}#ngg-listimages td.column-6{margin-top:-5px;margin-bottom:-8px}.ngg-listimages td.column-7{padding-bottom:15px}#ngg-manage-images-items-per-page,#ngg-manage-images-items-per-page-label{display:none}#ngg-listimages .column-6 textarea{height:60px}.ngg_manage_images .tablenav.bottom .displaying-num{display:none}}@media (max-width:782px){#ngg-gallery-wizard{display:none}#ngg_page_content .ngg_manage_galleries .tablenav.top>div{display:block;width:100%}#ngg_page_content .ngg_manage_galleries .tablenav .tablenav-pages{margin-top:20px;margin-bottom:28px!important}#ngg_page_content .ngg_manage_galleries .search-box input[type=text]{width:calc(100% - 150px)!important}#ngg_page_content .ngg_manage_galleries .search-box input[type=submit].button-primary{height:40px!important}#ngg_page_content .ngg_manage_galleries .search-box-wrapper{flex-direction:column}#ngg_page_content .ngg_manage_galleries form.search-form{width:100%}#ngg_page_content #editgalleries div.tablenav.top div.alignleft.actions input.button-primary{width:auto!important;display:inline-block}#ngg_page_content #editgalleries div.tablenav.top div.alignleft.actions input.button-primary:first-of-type{margin-left:5px}#ngg_page_content #editgalleries div.tablenav.top div.tablenav-pages{display:none}#ngg_page_content #editgalleries #bulkaction{width:auto!important}}@media (max-width:737px){.gallery_page_nggallery-manage-gallery input[type=checkbox]:checked:before{font-size:22px}.ngg-overlay-dialog input[type=radio]{height:16px;width:16px}#ngg-gallery-wizard{display:none}}@media (max-width:640px){.ngg_manage_galleries td.description,.ngg_manage_galleries th#description{display:none!important}.ngg_manage_albums .tablenav .actions{width:100%;float:none}.ngg_manage_albums .tablenav span{display:block}.ngg_manage_albums .target-album,.ngg_manage_albums .widget.widget-right{width:32%!important;margin:.5%!important;padding:5px 5px 10px}.groupItem .item_top{height:auto!important;line-height:1.5;padding:8px;font-size:12px}#ngg_page_content .groupItem .item_top a{display:none}.ngg_manage_albums div[style="float:right;"]{float:none!important}.gallery_page_nggallery-manage-gallery .ui-dialog{width:95%!important;left:2.5%!important}.gallery_page_nggallery-manage-gallery .ui-dialog .ngg-overlay-dialog{padding:30px 10px}.ngg-overlay-dialog td{display:block;width:100%!important;padding:0!important}.ngg-overlay-dialog input[type=radio]{margin:2px 5px;height:16px;width:16px}}#TB_overlay{background:#000;opacity:.7;position:fixed;top:0;right:0;bottom:0;left:0;z-index:100050}#TB_window{position:fixed;background-color:#fff;z-index:100050;visibility:hidden;text-align:left;top:50%;left:50%;-webkit-box-shadow:0 3px 6px rgba(0,0,0,.3);box-shadow:0 3px 6px rgba(0,0,0,.3)}#TB_window img#TB_Image{display:block;margin:15px 0 0 15px;border-right:1px solid #ccc;border-bottom:1px solid #ccc;border-top:1px solid #666;border-left:1px solid #666}#TB_caption{height:25px;padding:7px 30px 10px 25px;float:left}#TB_closeWindow{height:25px;padding:11px 25px 10px 0;float:right}#TB_closeWindowButton{position:absolute;left:auto;right:0;width:29px;height:29px;border:0;padding:0;background:0 0;cursor:pointer;outline:0;-webkit-transition:color .1s ease-in-out,background .1s ease-in-out;transition:color .1s ease-in-out,background .1s ease-in-out}#TB_ajaxWindowTitle{float:left;font-weight:600;line-height:29px;overflow:hidden;padding:0 29px 0 10px;text-overflow:ellipsis;white-space:nowrap;width:calc(100% - 39px)}#TB_title{background:#fcfcfc;border-bottom:1px solid #ddd;height:29px}#TB_ajaxContent{clear:both;padding:2px 15px 15px 15px;overflow:auto;text-align:left;line-height:1.4em}#TB_ajaxContent.TB_modal{padding:15px}#TB_ajaxContent p{padding:5px 0 5px 0}#TB_load{position:fixed;display:none;z-index:100050;top:50%;left:50%;background-color:#e8e8e8;border:1px solid #555;margin:-45px 0 0 -125px;padding:40px 15px 15px}#TB_HideSelect{z-index:99;position:fixed;top:0;left:0;background-color:#fff;border:none;opacity:0;height:100%;width:100%}#TB_iframeContent{clear:both;border:none}.tb-close-icon{display:block;color:#666;text-align:center;line-height:29px;width:29px;height:29px;position:absolute;top:0;right:0}.tb-close-icon:before{content:"\f158";font:normal 20px/29px dashicons;speak:never;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}#TB_closeWindowButton:focus .tb-close-icon,#TB_closeWindowButton:hover .tb-close-icon{color:#006799}#TB_closeWindowButton:focus .tb-close-icon{-webkit-box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8);box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}PK!Xf88Legacy/admin/overview.phpnu[ '', 'status' => 'ok', ]; \Imagely\NGG\Display\DisplayManager::enqueue_fontawesome(); if ( $action_status['message'] != '' ) { ?>

    ' . __('Launch Gallery Wizard', 'nggallery') . ''; ?>
    */ ?>

    NextGEN Gallery University on YouTube to see all available vidoes.', 'nggallery' ), esc_url( 'https://www.youtube.com/playlist?list=PL9cmsdHslD0vIcJjBggJ-XMjtwvqrRgoM' ) ); ?>

    NextGEN Gallery University on YouTube.', 'nggallery' ), esc_url( 'https://www.youtube.com/playlist?list=PL9cmsdHslD0vIcJjBggJ-XMjtwvqrRgoM' ) ); ?>

    [ __( 'Filmstrip Gallery', 'nggallery' ) => [ true, false ], __( 'Masonry Gallery', 'nggallery' ) => [ true, false ], __( 'Mosaic Gallery', 'nggallery' ) => [ true, false ], __( 'Tiled Gallery', 'nggallery' ) => [ true, false ], __( 'Film Gallery', 'nggallery' ) => [ true, false ], __( 'Blogstyle Gallery', 'nggallery' ) => [ true, false ], ], __( 'Ecommerce', 'nggallery' ) => [ __( 'Ecommerce', 'nggallery' ) => [ true, false ], __( 'Paid Digital Downloads', 'nggallery' ) => [ true, false ], __( 'Coupons', 'nggallery' ) => [ true, false ], __( 'Price Lists', 'nggallery' ) => [ true, false ], __( 'Automated Tax Calculations', 'nggallery' ) => [ true, false ], __( 'Automated Print Fulfillment', 'nggallery' ) => [ true, false ], __( 'Proofing', 'nggallery' ) => [ true, false ], ], __( 'Interface', 'nggallery' ) => [ __( 'Hover Captions', 'nggallery' ) => [ true, false ], __( 'Lazy Loading', 'nggallery' ) => [ true, false ], __( 'Infinite Scroll', 'nggallery' ) => [ true, false ], ], __( 'Image Upload / Processing', 'nggallery' ) => [ __( 'Lightroom Plugin', 'nggallery' ) => [ true, false ], ], __( 'Other', 'nggallery' ) => [ __( 'Digital Downloads', 'nggallery' ) => [ true, false ], __( 'Image Protection', 'nggallery' ) => [ true, false ], __( 'Image Commenting', 'nggallery' ) => [ true, false ], __( 'Image Deeplinking', 'nggallery' ) => [ true, false ], __( 'Full-Screen Lightbox', 'nggallery' ) => [ true, false ], __( 'Image Social Sharing', 'nggallery' ) => [ true, false ], __( 'Lightbox Slideshow', 'nggallery' ) => [ true, false ], ], ]; ?> $block ) { ?> $supports ) { ?>

    Get NextGEN Pro Today and Unlock all the Powerful Features

    Bonus: NextGEN Gallery users get 50% off the regular price using in the link above.

    $preset ) { if ( $current === 1 ) { ?>
    get_saved_meta(); $exifdata = $meta->get_EXIF(); $iptcdata = $meta->get_IPTC(); $xmpdata = $meta->get_XMP(); $class = ''; ?>

    $value ) { if ( in_array( $key, [ 'created_timestamp', 'timestamp' ] ) && is_numeric( $value ) ) { $value = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $value ); } if ( is_array( $value ) ) { continue; } $class = ( $class == 'class="alternate"' ) ? '' : 'class="alternate"'; echo ''; } ?>
    ' . esc_html( $meta->i18n_name( $key ) ) . ' ' . esc_html( $value ) . '
    ' . esc_html__( 'No meta data saved', 'nggallery' ) . '';} ?>

    $value ) { if ( in_array( $key, [ 'created_timestamp', 'timestamp' ] ) && is_numeric( $value ) ) { $value = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $value ); } if ( $key == 'created_date' ) { $value = date_i18n( get_option( 'date_format' ), strtotime( $value ) ); } $class = ( $class == 'class="alternate"' ) ? '' : 'class="alternate"'; echo ''; } ?>
    ' . esc_html( $meta->i18n_name( $key ) ) . ' ' . esc_html( $value ) . '
    ' . esc_html__( 'No exif data', 'nggallery' ) . '';} ?>

    $value ) { if ( in_array( $key, [ 'created_timestamp', 'timestamp' ] ) && is_numeric( $value ) ) { $value = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $value ); } $class = ( $class == 'class="alternate"' ) ? '' : 'class="alternate"'; echo ''; } ?>
    ' . esc_html( $meta->i18n_name( $key ) ) . ' ' . esc_html( $value ) . '

    $value ) { if ( in_array( $key, [ 'created_timestamp', 'timestamp' ] ) && is_numeric( $value ) ) { $value = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $value ); } $class = ( $class == 'class="alternate"' ) ? '' : 'class="alternate"'; echo ''; } ?>
    ' . esc_html( $meta->i18n_name( $key ) ) . ' ' . esc_html( $value ) . '
    PK!ƘuLegacy/admin/ajax.phpnu[reimport_metadata( $id ) ? '1' : '0'; break; case 'get_image_ids': $result = nggAdmin::get_image_ids( $id ); break; // This will read the EXIF and then write it with the Orientation tag reset. case 'strip_orientation_tag': $storage = \Imagely\NGG\DataStorage\Manager::get_instance(); $image_path = $storage->get_image_abspath( $id ); $backup_path = $image_path . '_backup'; $exif_abspath = @file_exists( $backup_path ) ? $backup_path : $image_path; $exif_iptc = @\Imagely\NGG\DataStorage\EXIFWriter::read_metadata( $exif_abspath ); foreach ( $storage->get_image_sizes( $id ) as $size ) { if ( $size === 'backup' ) { continue; } @\Imagely\NGG\DataStorage\EXIFWriter::write_metadata( $storage->get_image_abspath( $id, $size ), $exif_iptc ); } $result = '1'; break; default: do_action( 'ngg_ajax_' . $_POST['operation'] ); die( '-1' ); break; } // A success should return a '1'. die( $result ); } // The script should never stop here. die( '0' ); } add_action( 'wp_ajax_createNewThumb', 'createNewThumb' ); function createNewThumb() { // check for correct capability. if ( ! is_user_logged_in() ) { die( '-1' ); } // check for correct NextGEN capability. if ( ! current_user_can( 'NextGEN Manage gallery' ) ) { die( '-1' ); } if ( ! wp_verify_nonce( $_POST['nonce'], 'ngg_update_thumbnail' ) ) { die( '-1' ); } $id = (int) $_POST['id']; $x = round( $_POST['x'] * $_POST['rr'], 0 ); $y = round( $_POST['y'] * $_POST['rr'], 0 ); $w = round( $_POST['w'] * $_POST['rr'], 0 ); $h = round( $_POST['h'] * $_POST['rr'], 0 ); $crop_frame = [ 'x' => $x, 'y' => $y, 'width' => $w, 'height' => $h, ]; $storage = \Imagely\NGG\DataStorage\Manager::get_instance(); // XXX NextGEN Legacy wasn't handling watermarks or reflections at this stage, so we're forcefully disabling them to maintain compatibility. $params = [ 'watermark' => false, 'reflection' => false, 'crop' => true, 'crop_frame' => $crop_frame, ]; $result = $storage->generate_thumbnail( $id, $params ); if ( $result ) { echo 'OK'; } else { header( 'HTTP/1.1 500 Internal Server Error' ); echo 'KO'; } exit(); } add_action( 'wp_ajax_rotateImage', 'ngg_rotateImage' ); function ngg_rotateImage() { // check for correct capability. if ( ! is_user_logged_in() ) { die( '-1' ); } if ( ! wp_verify_nonce( $_POST['nonce'], 'ngg-rotate-image' ) ) { die( '-1' ); } // check for correct NextGEN capability. if ( ! current_user_can( 'NextGEN Manage gallery' ) ) { die( '-1' ); } require_once dirname( __DIR__ ) . '/ngg-config.php'; // include the ngg function. include_once __DIR__ . '/functions.php'; $id = (int) $_POST['id']; $result = '-1'; switch ( $_POST['ra'] ) { case 'cw': $result = nggAdmin::rotate_image( $id, 'CW' ); break; case 'ccw': $result = nggAdmin::rotate_image( $id, 'CCW' ); break; case 'fv': // Note: H/V have been inverted here to make it more intuitive. $result = nggAdmin::rotate_image( $id, 0, 'H' ); break; case 'fh': // Note: H/V have been inverted here to make it more intuitive. $result = nggAdmin::rotate_image( $id, 0, 'V' ); break; } // recreate the thumbnail. nggAdmin::create_thumbnail( $id ); if ( $result == 1 ) { die( '1' ); } header( 'HTTP/1.1 500 Internal Server Error' ); die( $result ); } PK!Ŵ:: Legacy/admin/images/facebook.pngnu[PNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<IDATxWKhQI&ĚDPt#h[S7* hJ*sa? hA "[)e)ZIic1R]͛yyof=5~sl _^C:ް~(v3NӦ:XJ dž@&G!tr݊;20|ZH&5xWd <Q`)7.uBn]cihbaZ\7JMK@{Es18*l0?:4RĘB` Bޫ,yӜeX2@UsUØbxBdj.9p YsQѢ⁸3J_01: Ma4tL@Y:sLtLbSE$ڹ?;ؑͤW^2L 1<l[ehj:(2L΀րE)SzP wҙ Հar P !X<~q-I0mQԄ 6Cc81?='-KԀaKW-X-Cn}nE0 R+ݓP%A0XR%1 xSTFݹ'==Or !Xޜ7öCEq]=rOxu?~q4JGG0g|!Hu7 e:I&} ,=k1ZIG8<IK@X_x^=<--/}-C[maIGstM| DHIJj#**Wi'0LVlW4M(6Cr)L璺J U5,ֺol;nnسrٓG!!S1fР}@qmBR1L> D;`3nz\;ሹ ye F'`7b,B+ &Gx+r 0<k {!y`KWZuP}U+3dуd\ L[ xdj̏ɵ&dý4S`vz!ى_PNAýAECt7>.ɺWyamwmbxtxރ ~/pa?D5A|ͭԕP: fO}vÝd/qUUTUյvFlmm]2ƬXk;u]wʲ4UUMx Adobe Photoshop CC 2015 (Macintosh) 2019-03-15T15:09:41-06:00 2019-03-15T15:14:16-06:00 2019-03-15T15:14:16-06:00 image/png 3 xmp.iid:f347c3b3-221f-441c-9330-4de0f7b2d965 adobe:docid:photoshop:b0d8d0ad-87f5-117c-9530-dc0cd962cc77 xmp.did:847520e6-7b88-417e-8583-b2fb23206b30 created xmp.iid:847520e6-7b88-417e-8583-b2fb23206b30 2019-03-15T15:09:41-06:00 Adobe Photoshop CC 2015 (Macintosh) saved xmp.iid:4e5ee218-6462-4e96-a64d-1f8638544487 2019-03-15T15:14:16-06:00 Adobe Photoshop CC 2015 (Macintosh) / saved xmp.iid:f347c3b3-221f-441c-9330-4de0f7b2d965 2019-03-15T15:14:16-06:00 Adobe Photoshop CC 2015 (Macintosh) / 1 10000/10000 10000/10000 2 65535 120 120 O cHRMz%u0`:o_FIDATx{Uu?{֭ Q1Y:"N0k1L2f0q%G`sʈOP2"T| Qh^MWս;;n=G[]pZVխ_8쳷IbD^*.x+2I5Ff;%-vV2CX$ j`A`DYA`rA6R4?rc.NMQ22 lh-vLS&1݅6;n#*迷Cd(2DE,Y "f DJj#I)3 7:u78g{ 0CcKI{f v=ƆVM6W!j'' Lh.E/ l lp7|#`׺BA`g(iGz_ۀS~>SBׁ)LWS#f&Lg"6!{p=S%;9uP#~JO*g!*@΍shLK&|'bs]K\`둪] L{+%3G /5a|Uو KG.lHgJL,Z c鋒 }=_{ɿ`Bs.ٟ<P! kd}/ΦP_ {s$)Q\\IN><_Cŗ#?"+߬{W"3 .>lDP 8" ;ރ^UEz.Xo*/ sR:ˠTQ|j:`ZHQ 0:\9o7[/9EF*axJ8zA\i# n*?:_ .i,"KFTe'>td\~^p;tgO~Z{ޮZEkOyq9{v2< ,4ރ\-~%l֍#p[&\wswvݗC8 lNt)e@{?5=q~N2~I~;_Jy_neXNzjޘotA=u2cwWrsy̞?4o҈:fǍrhjiXʣCمUbRҝ9v77#<$7nŏ(#hi8*$ᖸn} tQɍoOq!Zڄ[7冣{ȱvB -&aY`6kV8y0Pg3zTk3B/2X!I枌Y t-6w)sf *9<%Xte0|E3ѝn?33>N)S =}HǗsksEjnX, –HqTtZaj>\C9}xnnjT:]!$N[ND0[^>}[V)qԘx xJgЈ=⽓QR!P V Fk6b_li-?NZS%IA7VYo\;E ڭJ|YlPU<3ڪh̩6tM6S/k〭~HnΨ,x6X9s_AotbV905ΉVIkMv 1ЫZ/#T J*bS,񓳁Ӈ `_.tJrWO[c0f"89Xu0pfvjmrNO,yb)[\4/r {򼐵luN>Sb$5+xVax6 y3ab?`?j=<Ջ Zl+Ҵ@Q#OUO_yY9a%Q9E6HՃ9 ]S^g%缣~Y^mi(͏S3Gig]'fZBQzb!ϘWs߮Ol3r˳ _M,vDѡ;Í')4/*]ج-G?MH:XdXg`ۑ=`hfBx`]leS}܃b.ðWadAI[f2i[MX6U:(iMh4iњ2) =4!ZV{1L+5z2~ V6IU-C&izm10aܻޘm?1W/yKNU !;z΋q4WJe|č4EՁ( {H?D+0};4!BF]O6V ,ca6Vd9bMSVZ`s*ڬeQΠ)ѿ}QC#:hHH#fxڈ?z^ Bط$ݨBTdBo15a i'`q]_9kgH6`#! oZDeٻ) MKgGo_zPN->E~nh\]x=fчxωHe }sؠB;zѷwOr/~r[zw #6:*&ۧtaLKFuԹ.s.vsкXgwm sS678}Kwin?It{D1dD,( \QC \T>AJCcE&0IݲO6cE`RKд}' k>{[~?UNݱJjjR:s&C9⮡,Dhǜ wɆ>@1v}+ծRiRkvFvff#Bþ I K:u-^S! V"ZyH;c9,=6 C0[QklмLie㾣&J`{;0&xid!2`l>!n@GMw)൏ R-> B[u lA~ O+0D50wdzq&Jx?;/60[ѦGŒr]|S.c`a5CrGUז)gh]>* Xxt}q(7Vsk򢋲_ˮ֚S}Mt71$$HS|,Ft_-+uXi ,E3WصͯJ]u뒺.3pQ%ƙ47HqmįuM$߰T3;本ւz=Z+ϴQ).?ceYڔ^AObyփT|:]H)ț^k˖vY%Ss0zjwzrT?cɺ6O|h1hΓsD>Z# hRM*ʰ2ɼ Oԝ49=qlc ULOHHͅ-EY܏Ts T@ai&,Y2avFNQ-`:Ң1ʹԒ@mlNݘ R6`g&jƊ ^CagcPb ܆wyxiQrF>[$7u\S]Jѭp=p;r7aAMm+IyX[}LKmJyH~j9U3^'S|ZJl)üzFXSj=O3CG9.ǫ_UCY{RY[\1Uh\"?=_q_57y^d: Xf"G{;fq|WC5ò~%]{+RRĿ{QI[/'mEp;k|(秀V5]X{^Tt zjZ跰xFo-綦Ք5iߚR~y~zi1T%$eLY_oM~Fq0eL!\d`GfxK4E>B8%F|< P9=dgcxSYOWT(ƒp#ԝK16#;=g"4YgSXn6woR)ֿr 3 rHq~1?('8ʵm 0݉gft}cr숕{ 3vC˸SnWئŪm9K4Aadt:1Лk&htwo? ܾ5IENDB`PK!jfLegacy/admin/images/select.pngnu[PNG  IHDR$$gAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxJ@w7zIR"\ ^ H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-?iTXtXML:com.adobe.xmp 2016-02-20T15:50:05-07:00 2017-06-04T13:43:19-06:00 2017-06-04T13:43:19-06:00 Adobe Photoshop CC 2015 (Macintosh) image/png 3 sRGB IEC61966-2.1 xmp.iid:0a0ea03a-292c-48c7-bdfc-603d81fdfd18 adobe:docid:photoshop:d6683a1d-0fea-117a-8834-df3f7cfb76ae xmp.did:22a37fe0-9407-4d59-805e-f8bf053f45d6 saved xmp.iid:22a37fe0-9407-4d59-805e-f8bf053f45d6 2016-05-30T16:42:30-06:00 Adobe Photoshop CC 2015 (Macintosh) / converted from application/vnd.adobe.photoshop to image/png derived converted from application/vnd.adobe.photoshop to image/png saved xmp.iid:118a24b3-6bba-4ad5-83cf-767b8365204b 2016-05-30T16:42:30-06:00 Adobe Photoshop CC 2015 (Macintosh) / saved xmp.iid:0a0ea03a-292c-48c7-bdfc-603d81fdfd18 2017-06-04T13:43:19-06:00 Adobe Photoshop CC 2015 (Macintosh) / xmp.iid:22a37fe0-9407-4d59-805e-f8bf053f45d6 xmp.did:22a37fe0-9407-4d59-805e-f8bf053f45d6 xmp.did:22a37fe0-9407-4d59-805e-f8bf053f45d6 1 3000000/10000 3000000/10000 2 1 120 119 V cHRMz%u0`:o_F^IDATxyUǿVuLB@,!Y,D ~"('(xFy|*$HL&o/U5: 3]Ku&C>|{Ws=\aY%_#(\BJP"%.a8~q/z â<(inayj70LZ Nq  @OC`=JDx<Ʊp$p},6 ^+ cN`K>e_:X .\Nv8p}X<l)YH)8bK̛E;ܑpn/ A2eLd)(p.~O*< DҢ@y.j-TtOI@zH {+l{3خǕRBO_hDOApm?m/cC5B0MHMgGx=sQQs qh|;)6 ɓ3߰-#;< -/\j7uUJ b .,n@Ŋ- ܗNj?t,vw~( 0hjtK O\+ ,uI8jLYHIVw5WJAU*m11ДE}mW,d/jK/WL.4A8l+N}=:>ߓiâ?`)j?vkSU$݆ UI&S!(C٧|iv#g7ڲ RRHka!TRGnFI=| ~dC2 U0drhLx6^B |$e@VGDS갰\;ɵshB'e&Y"TXj^N>9>\2YOAn2|IO"d--BPx:'Z68)uT5e-TF^4g[Rlz+&~=HW ٭i8;6= P,6[Ԗ+9n#m+~( 'xL}dKl2%frvL> b)!TPRh۩{!dt7궧 _/Dz\.}2Y5X*fMdQW)CI-p܊JvB|X^Nj}SϦ"?6@0Bj9`Iŀe+zSCTUק T83DHʀiM{O,SqD[\M.(>hv=ti.gGJj#eķ#!3FJqdrh4፤R6ֳ}7<#G$*CfEy@*imI.4zHRLG"0` νæE@ (j܃ɷ!쥾| }pSk&4VYLkح|:` U2Yo\l |H~̼)iI,9H8c+ 0uhez%>ڲ ңVgt66IJH$$4Z&Ά`Z)5:!QEm{%,r}e0d+܆in´$Td+RLEЯ (B oݍKFE)GI Q[eEH'Ri DeZタ|۔등eʯx Z8*$CyծoQ]^9ʲzBY;;oݙͶźƽ45j^Eh"4"9W%B|%x*#W 6ݶ?&>7˴wufh?ٶΏ soPA̷41 ѩLW1ڤQac}#As]Cu)4j4QbC[9l/9ա#ßDmL!荴s!Wֿͺ3_Befezl)4O"ivy7RVfZ3~7Na F8 gKo!2)3+(w'm 8ML΅L_o9xgʄfɐǛ"/ 2~9J~~āLN"P1"HuW;!&g◭cfFXȚVZILkܛs9fŞhKW6F!n*}%嬦x0Fݖ n`01CO ~-3.B kŐ̌xߣ1B  P3.Q֞bgYHnUS\` "nw+ #GDAˎ1. ` T@!Ńc2J]&؋B&l,".WY^d\O^Iq=_: !_DKG5Q>e/:V ͶE$xK&EbY&7nRG̅`/,:66,-M$EMTqe#Cffv7LJzyw'}F©Մ@;P#xP_VjY߱M=kinvJ4? ^iAB2|ю&S7ۯd詝6܅$ uQs ]!2DF]"EVfr~]G'?؋lT(*ڠr"/{m+iqexndL"0FzOIA΁W٩fW0fhY& xqc ;"K3 |:,[Eu~' WvBW'z4|`^zk\)Mav턎L_V{hz#~I=7i}*hpO#og|@@Ũ|u *{tr ~ق=M84s"x5;J4|UI❻( a.Euamv¡BUB7a7y"pG8+T b)B@(d&SVNJUOr' I6iV&{:=?{}bM$SvR͠z5_ޒBlVEm[#cY ?\wwvb:<\J%eZ#'/L&r5$^ ! G`@@F&6%4FWѺ.ICu=e {6W.⵺Sf:bO$˗>,k7rKR|>a:mёb۶b{Oj?v9 M-Qrf:bO< nT!x4 7BpUEgg-[,n4+PEba͵ uqo Vcy&ۓnHYOԻ!׏.pY q+{|bA-[1M'S4q2eT塿EM]%;HnB4tK.gq[&ioO ;CJ׎OCo%yf zVz Z뚇.(z3?nyH.~bxp˦ }`!bmKhW2J\ _Ū[󄂬RSkf[I[&+!w>6/¸\ ~Pi>M,SX+hHs|4h@ y5Qjkd lDlfK'>^!)jY&'|dҤ3IB!cȽ9&:K T;M"}gabtQ ->xE/`j _Huk]5P|M`J {sO0MMHe!ך?dM7?CPAj@Z%Y=*&>rH !4[50M\)y>$Kn!+2X/W )I0D%&:pSNpO^r;alԁ%۫y==R/&Zh3Jquy-irɽ`&':z14b8!UKw'tCsՠ҅HUWnMࢨC«᧣z87>{2{} H.*E-r'٨䯣+"oNYj{_nMխD.Ln]MKm#0u-!E,T{#-QSI.~Qf"skNuyh(*a0>LKK>MǴ Zg=F>+s6Q|CB[хg8\EJW=t!7jl%i$) -E#Ps||^lzdάl"[ 1 | 5y. QY^4 5N?w}wQWQeU|;h5]S-{*w7-M5y_^xinxy$-}fc%l.ɖealc.&̲WAPgi)(g([ZCo*&~={ˌ2֕]D&(H6rOߗYgfB!CO4o˜!#~ygD-J~cq#Ь E͚`T'ٻ jzfr.QB- xemCToˠBD*>!EUR3lc#~X?\PڞȵA}x{| u6oEn1X! O,EQR$@g0#nѿFXnх!-޲sk:_"kJw>/H'~~q (X 3{ '', 'status' => 'ok', ]; if ( isset( $_POST['tag_action'] ) ) { check_admin_referer( 'nggallery_admin_tags' ); if ( $_POST['tag_action'] == 'renametag' ) { $oldtag = ( isset( $_POST['renametag_old'] ) ) ? $_POST['renametag_old'] : ''; $newtag = ( isset( $_POST['renametag_new'] ) ) ? $_POST['renametag_new'] : ''; $action_status = nggTags::rename_tags( $oldtag, $newtag ); Transient::flush( 'displayed_gallery_rendering' ); } elseif ( $_POST['tag_action'] == 'deletetag' ) { $todelete = ( isset( $_POST['deletetag_name'] ) ) ? $_POST['deletetag_name'] : ''; $action_status = nggTags::delete_tags( $todelete ); Transient::flush( 'displayed_gallery_rendering' ); } elseif ( $_POST['tag_action'] == 'editslug' ) { $matchtag = esc_html( ( isset( $_POST['tagname_match'] ) ) ? $_POST['tagname_match'] : '' ); $newslug = ( isset( $_POST['tagslug_new'] ) ) ? $_POST['tagslug_new'] : ''; $newslug = esc_html( \Imagely\NGG\DataStorage\Sanitizer::strip_html( $newslug ) ); $action_status = nggTags::edit_tag_slug( $matchtag, $newslug ); Transient::flush( 'displayed_gallery_rendering' ); } } // Som useful variables. $admin_base_url = admin_url() . 'admin.php?page=nggallery-tags'; $nb_tags = 50; // Number of tags to show on a single page. // Manage URL. $sort_order = ( isset( $_GET['tag_sortorder'] ) ) ? esc_attr( stripslashes( $_GET['tag_sortorder'] ) ) : 'desc'; $search_url = ( isset( $_GET['search'] ) ) ? '&search=' . esc_attr( stripslashes( $_GET['search'] ) ) : ''; $action_url = $admin_base_url . '&tag_sortorder=' . $sort_order . $search_url; // Tags Filters. $order_array = [ 'desc' => __( 'Most popular', 'nggallery' ), 'asc' => __( 'Least used', 'nggallery' ), 'natural' => __( 'Alphabetical', 'nggallery' ), ]; // Build Tags Param. $param = 'hide_empty=false'; switch ( $sort_order ) { case 'natural': $param .= '&number=' . $nb_tags . '&orderby=name&order=asc'; break; case 'asc': $param .= '&number=' . $nb_tags . '&orderby=count&order=asc'; break; default: $param .= '&number=' . $nb_tags . '&orderby=count&order=desc'; break; } // Search. if ( ! empty( $_GET['search'] ) ) { $search = sanitize_text_field( wp_unslash( $_GET['search'] ) ); $param .= '&name__like=' . $search; } // Offset. if ( ! empty( $_GET['offset'] ) ) { $param .= '&offset=' . intval( $_GET['offset'] ); } // Navigation urls. if ( empty( $_GET['offset'] ) ) { $offset = 0; } else { $offset = intval( $_GET['offset'] ); } $tag_count = (int) wp_count_terms( [ 'ignore_empty' => true, 'taxonomy' => 'ngg_tag', ] ); if ( $offset + $nb_tags < $tag_count ) { $next_offset = '' . min( $offset + $nb_tags, $tag_count - $nb_tags ); } else { $next_offset = ''; } if ( $nb_tags < $tag_count && $offset > 0 ) { $prev_offset = '' . max( $offset - $nb_tags, 0 ); } else { $prev_offset = ''; } ?>

    $title ) { $output[] = ( $sort == $sort_order ) ? '' . $title . '' : '' . $title . ''; } echo implode( ' | ', $output ); $output = []; unset( $output ); ?>
      ' . $tag->name . ' ('.$tag->count.')'."\n";. echo '
    • ' . esc_html( $tag->name ) . ' ' . '(' . esc_html( $tag->count ) . ')
    • ' . "\n"; } unset( $tags ); ?>

    Slug definition. You can specify multiple tags to rename by separating them with commas.', 'nggallery' ); ?>

    PK!!**Legacy/admin/roles.phpnu[


    :
    :
    :
    :
    :
    :
    :
    :
    :
    :
    role_objects; $sorted = []; if ( class_exists( 'RoleManager' ) ) { foreach ( $roles as $role_key => $role_name ) { $role = get_role( $role_key ); if ( empty( $role ) ) { continue; } $role_user_level = array_reduce( array_keys( $role->capabilities ), [ 'WP_User', 'level_reduction' ], 0 ); $sorted[ $role_user_level ] = $role; } $sorted = array_values( $sorted ); } else { $role_order = [ 'subscriber', 'contributor', 'author', 'editor', 'administrator' ]; foreach ( $role_order as $role_key ) { $sorted[ $role_key ] = get_role( $role_key ); } } return $sorted; } function ngg_get_role( $capability ) { // This function return the lowest roles which has the capabilities. $check_order = ngg_get_sorted_roles(); $args = array_slice( func_get_args(), 1 ); $args = array_merge( [ $capability ], $args ); foreach ( $check_order as $check_role ) { if ( empty( $check_role ) ) { return false; } if ( call_user_func_array( [ &$check_role, 'has_cap' ], $args ) ) { return $check_role->name; } } return false; } function ngg_set_capability( $lowest_role, $capability ) { // This function set or remove the $capability. $check_order = ngg_get_sorted_roles(); $add_capability = false; foreach ( $check_order as $the_role ) { $role = $the_role->name; if ( $lowest_role == $role ) { $add_capability = true; } // If you rename the roles, then please use a role manager plugin. if ( empty( $the_role ) ) { continue; } $add_capability ? $the_role->add_cap( $capability ) : $the_role->remove_cap( $capability ); } } ?>PK!w*6 6 Legacy/admin/rotate.phpnu[get_image_url( $id, 'full' ); ?>



    PK!8q;q;Legacy/admin/media-upload.phpnu[ __( 'NextGEN Gallery', 'nggallery' ) ]; return array_merge( $tabs, $newtab ); } function media_upload_nextgen() { // Not in use. $errors = false; // Generate TinyMCE HTML output. if ( isset( $_POST['send'] ) ) { $keys = array_keys( $_POST['send'] ); $send_id = (int) array_shift( $keys ); $image = $_POST['image'][ $send_id ]; $alttext = stripslashes( htmlspecialchars( $image['alttext'], ENT_QUOTES ) ); $description = stripslashes( htmlspecialchars( $image['description'], ENT_QUOTES ) ); // here is no new line allowed. $clean_description = preg_replace( "/\n|\r\n|\r$/", ' ', $description ); $img = nggdb::find_image( $send_id ); $thumbcode = $img->get_thumbcode(); $class = "ngg-singlepic ngg-{$image['align']}"; // Create a shell displayed-gallery so we can inspect its settings. $args = new stdClass(); $args->display_type = NGG_BASIC_SINGLEPIC; $displayed_gallery = new \Imagely\NGG\DataTypes\DisplayedGallery( $args ); $width = $displayed_gallery->display_settings['width']; $height = $displayed_gallery->display_settings['height']; // Build output. if ( $image['size'] == 'thumbnail' ) { $html = "{$alttext}"; } else { $html = ''; } // Wrap the link to the fullsize image around. $html = "{$html}"; if ( $image['size'] == 'full' ) { $html = "{$alttext}"; } if ( $image['size'] == 'singlepic' ) { $html = "[singlepic id={$send_id} w={$width} h={$height} float={$image['align']}]"; } media_upload_nextgen_save_image(); // Return it to TinyMCE. return media_send_to_editor( $html ); } // Save button. if ( isset( $_POST['save'] ) ) { media_upload_nextgen_save_image(); } wp_iframe( 'media_upload_nextgen_form', $errors ); die(); } function media_upload_nextgen_save_image() { global $wpdb; check_admin_referer( 'ngg-media-form' ); if ( ! empty( $_POST['image'] ) ) { foreach ( $_POST['image'] as $image_id => $image ) { // create a unique slug. $image_slug = nggdb::get_unique_slug( sanitize_title( $image['alttext'] ), 'image' ); $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->nggpictures} SET `image_slug` = %s, `alttext` = %s, `description` = %s WHERE pid = %d", [ $image_slug, $image['alttext'], $image['description'], $image_id, ] ) ); wp_cache_delete( $image_id, 'ngg_image' ); } } } function media_upload_nextgen_form( $errors ) { global $wpdb, $ngg; media_upload_header(); $from = isset( $_GET['from'] ) && 'block-editor' === $_GET['from'] ? 'block-editor' : 'classic-editor'; $post_id = intval( $_REQUEST['post_id'] ); $galleryID = 0; $total = 1; $picarray = []; $chromeless = isset( $_GET['chromeless'] ) ? $_GET['chromeless'] : null; $chromeless_url = $chromeless ? ( '&chromeless=' . $chromeless ) : null; $form_action_url = site_url( "wp-admin/media-upload.php?type={$GLOBALS['type']}&tab=nextgen&post_id=$post_id" . $chromeless_url, 'admin' ); // Get number of images in gallery. if ( isset( $_REQUEST['select_gal'] ) ) { $galleryID = (int) $_REQUEST['select_gal']; $total = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->nggpictures} WHERE `galleryid` = %d", [ $galleryID, ] ) ); } // Build navigation. $_GET['paged'] = isset( $_GET['paged'] ) ? intval( $_GET['paged'] ) : 0; if ( $_GET['paged'] < 1 ) { $_GET['paged'] = 1; } $start = ( $_GET['paged'] - 1 ) * 10; if ( $start < 1 ) { $start = 0; } // Get the images. if ( $galleryID != 0 ) { // Using %i in $wpdb->prepare() to signify column identifiers was only added in WP 6.2 // // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared $picarray = $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT `pid` FROM {$wpdb->nggpictures} WHERE `galleryid` = %d AND `exclude` != 1 ORDER BY {$ngg->options['galSort']}, `pid` {$ngg->options['galSortDir']} LIMIT {$start}, 10", [ $galleryID, ] ) ); // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared } // WP-Core code for Post-thumbnail. $calling_post_id = 0; if ( isset( $_GET['post_id'] ) ) { $calling_post_id = $_GET['post_id']; } ?>
    add_query_arg( 'paged', '%#%' ), 'format' => '', 'total' => ceil( $total / 10 ), 'current' => $_GET['paged'], ] ); if ( $page_links ) { echo "
    $page_links
    "; } ?>


    get_image_dimensions( $picid, 'thumb' ); extract( $dimensions ); $thumb_url = $storage->get_image_url( $picid, 'thumb' ); ?>
    alttext ) ) ? wp_html_excerpt( esc_html( $picture->filename ), 60 ) : stripslashes( wp_html_excerpt( esc_html( $picture->alttext ), 60 ) ); ?>
    <?php echo esc_attr( $picture->alttext ); ?>
    filename ); ?>
    alttext ) ); ?>
     
    " . esc_html__( 'Use as featured image', 'nggallery' ) . ''; echo ""; ?>

    gid = (int) $_GET['gid']; $this->gallery = GalleryMapper::get_instance()->find( $this->gid, true ); } if ( isset( $_GET['pid'] ) ) { $this->pid = (int) $_GET['pid']; } if ( isset( $_GET['mode'] ) ) { $this->mode = trim( sanitize_text_field( wp_unslash( $_GET['mode'] ) ) ); } // Check for pagination request, avoid post process of other submit button, exclude search results. // Nonce verification not necessary here: we are only determining which page to view, whose ID is always // cast to an integer. NextGEN has historically used POST in places it shouldn't, such as pagination here. // // phpcs:disable WordPress.Security.NonceVerification.Missing if ( isset( $_POST['post_paged'] ) && ! isset( $_GET['s'] ) ) { if ( $_GET['paged'] != $_POST['post_paged'] ) { $_GET['paged'] = absint( $_POST['post_paged'] ); return; } } // phpcs:enable WordPress.Security.NonceVerification.Missing // Should be only called via manage galleries overview. if ( isset( $_POST['nggpage'] ) && 'manage-galleries' === $_POST['nggpage'] && wp_verify_nonce( sanitize_key( wp_unslash( $_POST['_wpnonce'] ) ), 'ngg_bulkgallery' ) ) { $this->post_processor_galleries(); } // Should be only called via a edit single gallery page. if ( isset( $_POST['nggpage'] ) && 'manage-images' === $_POST['nggpage'] && wp_verify_nonce( sanitize_key( wp_unslash( $_POST['_wpnonce'] ) ), 'ngg_updategallery' ) ) { $this->post_processor_images(); } // Look for other POST process. if ( ! empty( $_POST ) || ! empty( $_GET ) ) { $this->processor(); } M_NextGen_Admin::emit_do_notices_action(); } public function controller() { switch ( $this->mode ) { case 'sort': include_once __DIR__ . '/manage-sort.php'; nggallery_sortorder( $this->gid ); break; case 'edit': $this->setup_gallery_fields(); $this->setup_image_rows(); include_once __DIR__ . '/manage-images.php'; nggallery_picturelist( $this ); break; case 'main': default: include_once __DIR__ . '/manage-galleries.php'; nggallery_manage_gallery_main(); break; } } public function processor() { global $ngg, $nggdb; // Delete a picture. if ( $this->mode == 'delpic' ) { // TODO:Remove also Tag reference. check_admin_referer( 'ngg_delpicture' ); $image = $nggdb->find_image( $this->pid ); if ( $image ) { do_action( 'ngg_delete_picture', $this->pid, $image ); if ( $ngg->options['deleteImg'] ) { $storage = StorageManager::get_instance(); $storage->delete_image( $this->pid ); } $mapper = ImageMapper::get_instance(); $result = $mapper->destroy( $this->pid ); if ( $result ) { nggGallery::show_message( __( 'Picture', 'nggallery' ) . ' \'' . $this->pid . '\' ' . __( 'deleted successfully', 'nggallery' ) ); } } $this->mode = 'edit'; // show pictures. } // Recover picture from backup. if ( $this->mode == 'recoverpic' ) { check_admin_referer( 'ngg_recoverpicture' ); // bring back the old image. nggAdmin::recover_image( $this->pid ); nggGallery::show_message( __( 'Operation successful. Please clear your browser cache.', 'nggallery' ) ); $this->mode = 'edit'; // show pictures. } // will be called after a ajax operation. if ( isset( $_POST['ajax_callback'] ) ) { if ( $_POST['ajax_callback'] == 1 ) { nggGallery::show_message( __( 'Operation successful. Please clear your browser cache.', 'nggallery' ) ); } } // show sort order. if ( isset( $_POST['sortGallery'] ) ) { $this->mode = 'sort'; } if ( isset( $_GET['s'] ) ) { $this->search_images(); } } public function setup_image_rows() { add_filter( 'ngg_manage_images_row', [ &$this, 'render_image_row' ], 10, 2 ); add_filter( 'ngg_manage_images_column_1_header', [ &$this, 'render_image_column_1_header' ] ); add_filter( 'ngg_manage_images_column_1_content', [ &$this, 'render_image_column_1' ], 10, 2 ); add_filter( 'ngg_manage_images_column_2_header', [ &$this, 'render_image_column_2_header' ] ); add_filter( 'ngg_manage_images_column_2_content', [ &$this, 'render_image_column_2' ], 10, 2 ); add_filter( 'ngg_manage_images_column_3_header', [ &$this, 'render_image_column_3_header' ] ); add_filter( 'ngg_manage_images_column_3_content', [ &$this, 'render_image_column_3' ], 10, 2 ); add_filter( 'ngg_manage_images_column_4_header', [ &$this, 'render_image_column_4_header' ] ); add_filter( 'ngg_manage_images_column_4_content', [ &$this, 'render_image_column_4' ], 10, 2 ); add_filter( 'ngg_manage_images_column_5_header', [ &$this, 'render_image_column_5_header' ] ); add_filter( 'ngg_manage_images_column_5_content', [ &$this, 'render_image_column_5' ], 10, 2 ); add_filter( 'ngg_manage_images_column_6_header', [ &$this, 'render_image_column_6_header' ] ); add_filter( 'ngg_manage_images_column_6_content', [ &$this, 'render_image_column_6' ], 10, 2 ); } public function render_image_column_1_header() { return ''; } public function render_image_column_2_header() { return __( 'ID', 'nggallery' ); } public function render_image_column_3_header() { return __( 'Thumbnail', 'nggallery' ); } public function render_image_column_4_header() { return __( 'Filename', 'nggallery' ); } public function render_image_column_5_header() { return __( 'Alt & Title Text / Description', 'nggallery' ); } public function render_image_column_6_header() { return __( 'Tags', 'nggallery' ); } public function render_image_column_1( $output = '', $picture = [] ) { return ""; } public function render_image_column_2( $output = '', $picture = [] ) { return $picture->pid; } public function render_image_column_3( $output = '', $picture = [] ) { $image_url = add_query_arg( 'i', mt_rand(), $picture->imageURL ); $thumb_url = add_query_arg( 'i', mt_rand(), $picture->thumbURL ); $filename = esc_attr( $picture->filename ); $output = []; $output[] = ""; $output[] = ""; $output[] = ''; return ( $output = implode( "\n", $output ) ); } public function render_image_column_4( $output = '', $picture = [] ) { $image_url = Router::esc_url( $picture->imageURL ); $filename = esc_attr( $picture->filename ); $caption = esc_html( ( empty( $picture->alttext ) ? $picture->filename : $picture->alttext ) ); $data_caption = esc_attr( $caption ); $caption = \Imagely\NGG\Display\I18N::ngg_plain_text_alt_title_attributes( $caption ); $caption = esc_attr( $caption ); $date = mysql2date( get_option( 'date_format' ), $picture->imagedate ); $width = $picture->meta_data['width']; $height = $picture->meta_data['height']; $pixels = "{$width} x {$height} pixels"; $excluded = checked( $picture->exclude, 1, false ); $exclude_label = __( 'Exclude ?', 'nggallery' ); $output = []; $output[] = ""; $output[] = '
    ' . esc_html( $date ) . '
    '; $output[] = "
    {$pixels}
    "; $output[] = "'; return ( $output = implode( "\n", $output ) ); } public function render_image_column_5( $output = '', $picture = [] ) { $alttext = \Imagely\NGG\Display\I18N::ngg_sanitize_text_alt_title_desc( $picture->alttext ); $desc = \Imagely\NGG\Display\I18N::ngg_sanitize_text_alt_title_desc( $picture->description ); $output = []; $output[] = ""; $output[] = ""; return ( $output = implode( "\n", $output ) ); } public function render_image_column_6( $output = '', $picture = [] ) { global $wp_version; $fields = version_compare( $wp_version, '4.6', '<=' ) ? 'fields=names' : [ 'fields' => 'names' ]; $tags = wp_get_object_terms( $picture->pid, 'ngg_tag', $fields ); if ( is_array( $tags ) ) { $tags = implode( ', ', $tags ); } $tags = esc_html( $tags ); return ""; } public function render_image_row( $picture, $counter ) { // Get number of columns. $class = ! ( $counter % 2 == 0 ) ? '' : 'alternate'; $columns = apply_filters( 'ngg_manage_images_number_of_columns', 6 ); // Get the valid row actions. $actions = []; $row_actions = apply_filters( 'ngg_manage_images_row_actions', [ 'view' => [ &$this, 'render_view_action_link' ], 'meta' => [ &$this, 'render_meta_action_link' ], 'custom_thumb' => [ &$this, 'render_custom_thumb_action_link' ], 'rotate' => [ &$this, 'render_rotate_action_link' ], 'recover' => [ &$this, 'render_recover_action_link' ], 'delete' => [ &$this, 'render_delete_action_link' ], ] ); foreach ( $row_actions as $id => $callback ) { if ( is_callable( $callback ) ) { $result = call_user_func( $callback, $id, $picture ); if ( $result ) { $actions[] = $result; } } } // Output row columns. echo ""; for ( $i = 1; $i <= $columns; $i++ ) { $rowspan = $i > 4 ? "rowspan='2'" : ''; echo ""; echo apply_filters( "ngg_manage_images_column_{$i}_content", '', $picture ); echo ''; } echo ''; // Actions row. echo ""; echo ''; echo ""; echo "
    "; echo implode( ' | ', $actions ); echo '
    '; echo ''; echo ''; } public function render_view_action_link( $id, $picture ) { $image_url = Router::esc_url( $picture->imageURL ); $label = esc_html__( 'View', 'nggallery' ); $alt_text = empty( $picture->alttext ) ? $picture->filename : $picture->alttext; $data_title = esc_attr( __( 'View', 'nggallery' ) ) . ' "' . esc_attr( $alt_text ) . '"'; $alt_text = \Imagely\NGG\Display\I18N::ngg_plain_text_alt_title_attributes( $alt_text ); $title = esc_attr( __( 'View', 'nggallery' ) ) . ' "' . esc_attr( $alt_text ) . '"'; return "{$label}"; } public function render_meta_action_link( $id, $picture ) { $url = Router::esc_url( NGGALLERY_URLPATH . 'admin/showmeta.php?id=' . $picture->pid . '&nonce=' . \wp_create_nonce( 'ngg_meta_popup' ) ); $title = esc_attr__( 'Show meta data', 'nggallery' ); $label = esc_html__( 'Meta', 'nggallery' ); return "{$label}"; } public function render_custom_thumb_action_link( $id, $picture ) { $url = Router::esc_url( NGGALLERY_URLPATH . 'admin/edit-thumbnail.php?id=' . $picture->pid . '&nonce=' . \wp_create_nonce( 'ngg_edit_thumbnail' ) ); $title = esc_attr__( 'Customize thumbnail', 'nggallery' ); $label = esc_html__( 'Edit thumb', 'nggallery' ); return "{$label}"; } public function render_rotate_action_link( $id, $picture ) { $url = Router::esc_url( NGGALLERY_URLPATH . 'admin/rotate.php?id=' . $picture->pid . '&nonce=' . \wp_create_nonce( 'ngg_edit_rotation' ) ); $title = esc_attr__( 'Rotate', 'nggallery' ); $label = esc_html__( 'Rotate', 'nggallery' ); return "{$label}"; } public function render_recover_action_link( $id, $picture ) { if ( ! file_exists( $picture->imagePath . '_backup' ) ) { return false; } $url = wp_nonce_url( "admin.php?page=nggallery-manage-gallery&mode=recoverpic&gid={$picture->galleryid}&pid={$picture->pid}", 'ngg_recoverpicture' ); $title = esc_attr__( 'Recover image from backup', 'nggallery' ); $label = esc_html__( 'Recover', 'nggallery' ); $question = __( 'Recover', 'nggallery' ); $alttext = empty( $picture->alttext ) ? $picture->filename : $picture->alttext; $alttext = Sanitizer::strip_html( html_entity_decode( $alttext ), true ); $alttext = htmlentities( $alttext, ENT_QUOTES | ENT_HTML401 ); $alttext = \Imagely\NGG\Display\I18N::ngg_plain_text_alt_title_attributes( $alttext ); $alttext = esc_attr( $alttext ); // Event handler is found in nextgen_admin_page.js. return "{$label}"; } public function render_delete_action_link( $id, $picture ) { $url = wp_nonce_url( "admin.php?page=nggallery-manage-gallery&mode=delpic&gid={$picture->galleryid}&pid={$picture->pid}", 'ngg_delpicture' ); $title = esc_attr__( 'Delete image', 'nggallery' ); $label = esc_html__( 'Delete', 'nggallery' ); $question = __( 'Delete', 'nggallery' ); $alttext = empty( $picture->alttext ) ? $picture->filename : $picture->alttext; $alttext = Sanitizer::strip_html( html_entity_decode( $alttext ), true ); $alttext = htmlentities( $alttext, ENT_QUOTES | ENT_HTML401 ); $alttext = \Imagely\NGG\Display\I18N::ngg_plain_text_alt_title_attributes( $alttext ); $alttext = esc_attr( $alttext ); // Event handler is found in nextgen_admin_page.js. return "{$label}"; } public function render_image_row_header() { $columns = apply_filters( 'ngg_manage_images_number_of_columns', 6 ); echo ''; for ( $i = 1; $i <= $columns; $i++ ) { echo ""; echo apply_filters( 'ngg_manage_images_column_' . $i . '_header', "Column #{$i}" ); echo ''; } echo ''; } public function setup_gallery_fields() { add_filter( 'ngg_manage_gallery_fields', [ &$this, 'default_gallery_fields' ], 10, 2 ); } public function default_gallery_fields( $fields = [], $gallery = null ) { $fields['left'] = [ 'title' => [ 'callback' => [ &$this, 'render_gallery_title_field' ], 'label' => __( 'Title:', 'nggallery' ), 'tooltip' => null, 'id' => 'gallery_title', ], 'description' => [ 'callback' => [ &$this, 'render_gallery_desc_field' ], 'label' => __( 'Description:', 'nggallery' ), 'tooltip' => null, 'id' => 'gallery_desc', ], 'path' => [ 'callback' => [ &$this, 'render_gallery_path_field' ], 'label' => __( 'Gallery path:', 'nggallery' ), 'tooltip' => null, 'id' => 'gallery_path', ], 'gallery_author' => [ 'callback' => [ &$this, 'render_gallery_author_field' ], 'label' => __( 'Author', 'nggallery' ), 'tooltip' => null, 'id' => 'gallery_author', ], ]; $fields['right'] = [ 'page_link_to' => [ 'callback' => [ &$this, 'render_gallery_link_to_page_field' ], 'label' => __( 'Link to page:', 'nggallery' ), 'tooltip' => __( 'Albums will link this gallery to the selected page', 'nggallery' ), 'id' => 'gallery_page_link_to', ], 'preview_image' => [ 'callback' => [ &$this, 'render_gallery_preview_image_field' ], 'label' => __( 'Preview image:', 'nggallery' ), 'tooltip' => null, 'id' => 'gallery_preview_image', ], 'create_page' => [ 'callback' => [ &$this, 'render_gallery_create_page_field' ], 'label' => __( 'Create new page:', 'nggallery' ), 'tooltip' => null, 'id' => 'gallery_create_new_page', ], ]; return $fields; } public function render_gallery_field_label_column( $text, $for, $tooltip = null ) { $for = esc_attr( $for ); if ( ! empty( $tooltip ) ) { $tooltip = "title='{$tooltip}' class='tooltip'"; } echo ""; } public function render_gallery_fields() { // Get the gallery entity. $gallery = GalleryMapper::get_instance()->find( $this->gid ); // Get fields. $fields = apply_filters( 'ngg_manage_gallery_fields', [], $gallery ); $left = isset( $fields['left'] ) ? $fields['left'] : []; $right = isset( $fields['right'] ) ? $fields['right'] : []; // Output table. echo ''; $number_of_fields = max( count( $left ), count( $right ) ); $left_keys = array_keys( $left ); $right_keys = array_keys( $right ); for ( $i = 0; $i < $number_of_fields; $i++ ) { // Start row. echo ''; // Left column. if ( isset( $left_keys[ $i ] ) ) { extract( $left[ $left_keys[ $i ] ] ); // Label. $this->render_gallery_field_label_column( $label, $id, $tooltip ); // Input field. if ( is_callable( $callback ) ) { echo ''; } elseif ( WP_DEBUG ) { echo "

    Could not render {$left_keys[$i]} field. No callback exists

    "; } } else { $output[] = ''; } // Right column. if ( isset( $right_keys[ $i ] ) ) { extract( $right[ $right_keys[ $i ] ] ); // Label. $this->render_gallery_field_label_column( $label, $id, $tooltip ); // Input field.. if ( is_callable( $callback ) ) { echo ''; } elseif ( WP_DEBUG ) { echo "

    Could not render {$right_keys[$i]} field. No callback exists

    "; } } else { $output[] = ''; } // End. echo ''; } echo ''; } public function render_gallery_title_field( $gallery ) { include 'templates/manage_gallery/gallery_title_field.php'; } public function render_gallery_desc_field( $gallery ) { include 'templates/manage_gallery/gallery_desc_field.php'; } public function render_gallery_path_field( $gallery ) { include 'templates/manage_gallery/gallery_path_field.php'; } public function render_gallery_author_field( $gallery ) { $user = get_userdata( $gallery->author ); $author = isset( $user->display_name ) ? $user->display_name : $user->user_nicename; include 'templates/manage_gallery/gallery_author_field.php'; } public function render_gallery_link_to_page_field( $gallery ) { $pages = get_pages(); include 'templates/manage_gallery/gallery_link_to_page_field.php'; } public function render_gallery_preview_image_field( $gallery ) { $images = []; foreach ( ImageMapper::get_instance()->find_all( [ 'galleryid = %s', $gallery->{$gallery->id_field} ] ) as $image ) { $images[ $image->{$image->id_field} ] = "[{$image->{$image->id_field}}] {$image->filename}"; } include 'templates/manage_gallery/gallery_preview_image_field.php'; } public function render_gallery_create_page_field( $gallery ) { $pages = get_pages(); include 'templates/manage_gallery/gallery_create_page_field.php'; } public function post_processor_galleries() { global $ngg; check_admin_referer( 'ngg_bulkgallery' ); // bulk update in a single gallery. if ( isset( $_POST['bulkaction'] ) && isset( $_POST['doaction'] ) ) { switch ( $_POST['bulkaction'] ) { case 'no_action'; // No action. break; case 'recover_images': // Recover images from backup. // A prefix 'gallery_' will first fetch all ids from the selected galleries. nggAdmin::do_ajax_operation( 'gallery_recover_image', $_POST['doaction'], __( 'Recover from backup', 'nggallery' ) ); break; case 'set_watermark': // Set watermark // A prefix 'gallery_' will first fetch all ids from the selected galleries. nggAdmin::do_ajax_operation( 'gallery_set_watermark', $_POST['doaction'], __( 'Set watermark', 'nggallery' ) ); break; case 'import_meta': // Import Metadata // A prefix 'gallery_' will first fetch all ids from the selected galleries. nggAdmin::do_ajax_operation( 'gallery_import_metadata', $_POST['doaction'], __( 'Import metadata', 'nggallery' ) ); break; case 'delete_gallery': // Delete gallery. if ( is_array( $_POST['doaction'] ) ) { $deleted = false; $mapper = GalleryMapper::get_instance(); foreach ( $_POST['doaction'] as $id ) { $gallery = $mapper->find( $id ); if ( $gallery->path == '../' || false !== strpos( $gallery->path, '/../' ) ) { nggGallery::show_message( sprintf( __( 'One or more "../" in Gallery paths could be unsafe and NextGen Gallery will not delete gallery %s automatically', 'nggallery' ), $gallery->{$gallery->id_field} ) ); } elseif ( $mapper->destroy( $id, true ) ) { $deleted = true; } } if ( $deleted ) { nggGallery::show_message( esc_html__( 'Gallery deleted successfully ', 'nggallery' ) ); } } break; } } if ( isset( $_POST['addgallery'] ) && isset( $_POST['galleryname'] ) ) { check_admin_referer( 'ngg_bulkgallery' ); if ( ! nggGallery::current_user_can( 'NextGEN Add new gallery' ) ) { wp_die( esc_html_e( 'Cheatin’ uh?', 'nggallery' ) ); } // get the default path for a new gallery. $newgallery = $_POST['galleryname']; if ( ! empty( $newgallery ) ) { $gallery_mapper = GalleryMapper::get_instance(); $gallery = $gallery_mapper->create( [ 'title' => $newgallery ] ); if ( $gallery->save() && ! isset( $_REQUEST['attach_to_post'] ) ) { $url = admin_url() . 'admin.php?page=nggallery-manage-gallery&mode=edit&gid=' . $gallery->gid; $message = sprintf( __( 'Gallery successfully created. Manage gallery', 'nggallery' ), $url ); nggGallery::show_message( $message, 'gallery_created_msg' ); } } do_action( 'ngg_update_addgallery_page' ); } if ( isset( $_POST['TB_bulkaction'] ) && isset( $_POST['TB_ResizeImages'] ) ) { // save the new values for the next operation. $ngg->options['imgWidth'] = (int) $_POST['imgWidth']; $ngg->options['imgHeight'] = (int) $_POST['imgHeight']; // What is in the case the user has no if cap 'NextGEN Change options' ? Check feedback. update_option( 'ngg_options', $ngg->options ); $gallery_ids = explode( ',', $_POST['TB_imagelist'] ); // A prefix 'gallery_' will first fetch all ids from the selected galleries. nggAdmin::do_ajax_operation( 'gallery_resize_image', $gallery_ids, __( 'Resize images', 'nggallery' ) ); } if ( isset( $_POST['TB_bulkaction'] ) && isset( $_POST['TB_NewThumbnail'] ) ) { // save the new values for the next operation. $settings = Settings::get_instance(); $settings->set( 'thumbwidth', (int) $_POST['thumbwidth'] ); $settings->set( 'thumbheight', (int) $_POST['thumbheight'] ); $settings->set( 'thumbfix', isset( $_POST['thumbfix'] ) ); $settings->save(); ngg_refreshSavedSettings(); // What is in the case the user has no if cap 'NextGEN Change options' ? Check feedback. $gallery_ids = explode( ',', $_POST['TB_imagelist'] ); // A prefix 'gallery_' will first fetch all ids from the selected galleries. nggAdmin::do_ajax_operation( 'gallery_create_thumbnail', $gallery_ids, __( 'Create new thumbnails', 'nggallery' ) ); } } public function post_processor_images() { global $wpdb, $ngg, $nggdb; check_admin_referer( 'ngg_updategallery' ); // bulk update in a single gallery. if ( isset( $_POST['bulkaction'] ) && isset( $_POST['doaction'] ) ) { check_admin_referer( 'ngg_updategallery' ); switch ( $_POST['bulkaction'] ) { case 'no_action'; break; case 'rotate_cw': nggAdmin::do_ajax_operation( 'rotate_cw', $_POST['doaction'], __( 'Rotate images', 'nggallery' ) ); break; case 'rotate_ccw': nggAdmin::do_ajax_operation( 'rotate_ccw', $_POST['doaction'], __( 'Rotate images', 'nggallery' ) ); break; case 'recover_images': nggAdmin::do_ajax_operation( 'recover_image', $_POST['doaction'], __( 'Recover from backup', 'nggallery' ) ); break; case 'set_watermark': nggAdmin::do_ajax_operation( 'set_watermark', $_POST['doaction'], __( 'Set watermark', 'nggallery' ) ); break; case 'strip_orientation_tag': nggAdmin::do_ajax_operation( 'strip_orientation_tag', $_POST['doaction'], __( 'Remove EXIF Orientation', 'nggallery' ) ); break; case 'delete_images': if ( is_array( $_POST['doaction'] ) ) { foreach ( $_POST['doaction'] as $imageID ) { $image = $nggdb->find_image( $imageID ); if ( $image ) { do_action( 'ngg_delete_picture', $image->pid, $image ); if ( $ngg->options['deleteImg'] ) { $storage = StorageManager::get_instance(); $storage->delete_image( $image->pid ); } $delete_pic = ImageMapper::get_instance()->destroy( $image->pid ); } } if ( $delete_pic ) { nggGallery::show_message( __( 'Pictures deleted successfully ', 'nggallery' ) ); } } break; case 'import_meta': nggAdmin::do_ajax_operation( 'import_metadata', $_POST['doaction'], __( 'Import metadata', 'nggallery' ) ); break; } } if ( isset( $_POST['TB_bulkaction'] ) && isset( $_POST['TB_ResizeImages'] ) ) { // save the new values for the next operation. $ngg->options['imgWidth'] = (int) $_POST['imgWidth']; $ngg->options['imgHeight'] = (int) $_POST['imgHeight']; update_option( 'ngg_options', $ngg->options ); $pic_ids = explode( ',', $_POST['TB_imagelist'] ); nggAdmin::do_ajax_operation( 'resize_image', $pic_ids, __( 'Resize images', 'nggallery' ) ); } if ( isset( $_POST['TB_bulkaction'] ) && isset( $_POST['TB_NewThumbnail'] ) ) { // save the new values for the next operation. $settings = Settings::get_instance(); $settings->set( 'thumbwidth', (int) $_POST['thumbwidth'] ); $settings->set( 'thumbheight', (int) $_POST['thumbheight'] ); $settings->set( 'thumbfix', isset( $_POST['thumbfix'] ) ); $settings->save(); ngg_refreshSavedSettings(); $pic_ids = explode( ',', $_POST['TB_imagelist'] ); nggAdmin::do_ajax_operation( 'create_thumbnail', $pic_ids, __( 'Create new thumbnails', 'nggallery' ) ); } if ( isset( $_POST['TB_bulkaction'] ) && isset( $_POST['TB_SelectGallery'] ) ) { $pic_ids = explode( ',', $_POST['TB_imagelist'] ); $dest_gid = (int) $_POST['dest_gid']; switch ( $_POST['TB_bulkaction'] ) { case 'copy_to': $destination = GalleryMapper::get_instance()->find( $dest_gid ); $new_ids = StorageManager::get_instance()->copy_images( $pic_ids, $dest_gid ); if ( ! empty( $new_ids ) ) { $admin_url = admin_url(); $title = esc_html( $destination->title ); $link = "{$title}"; nggGallery::show_message( sprintf( __( 'Copied %1$s picture(s) to gallery: %2$s .', 'nggallery' ), count( $new_ids ), $link ) ); } else { nggGallery::show_error( __( 'Failed to copy images', 'nggallery' ) ); } break; case 'move_to': $destination = GalleryMapper::get_instance()->find( $dest_gid ); $new_ids = StorageManager::get_instance()->move_images( $pic_ids, $dest_gid ); if ( ! empty( $new_ids ) ) { $admin_url = admin_url(); $title = esc_html( $destination->title ); $link = "{$title}"; nggGallery::show_message( sprintf( __( 'Moved %1$s picture(s) to gallery: %2$s .', 'nggallery' ), count( $new_ids ), $link ) ); } else { nggGallery::show_error( __( 'Failed to move images', 'nggallery' ) ); } break; } } if ( isset( $_POST['TB_bulkaction'] ) && isset( $_POST['TB_EditTags'] ) ) { // do tags update. // get the images list. $pic_ids = explode( ',', $_POST['TB_imagelist'] ); $taglist = explode( ',', $_POST['taglist'] ); $taglist = array_map( 'trim', $taglist ); if ( is_array( $pic_ids ) ) { foreach ( $pic_ids as $pic_id ) { // which action should be performed ? switch ( $_POST['TB_bulkaction'] ) { case 'no_action'; // No action. break; case 'overwrite_tags': // Overwrite tags. wp_set_object_terms( $pic_id, $taglist, 'ngg_tag' ); break; case 'add_tags': // Add / append tags. wp_set_object_terms( $pic_id, $taglist, 'ngg_tag', true ); break; case 'delete_tags': // Delete tags. $oldtags = wp_get_object_terms( $pic_id, 'ngg_tag', 'fields=names' ); // get the slugs, to vaoid case sensitive problems. $slugarray = array_map( 'sanitize_title', $taglist ); $oldtags = array_map( 'sanitize_title', $oldtags ); // compare them and return the diff. $newtags = array_diff( $oldtags, $slugarray ); wp_set_object_terms( $pic_id, $newtags, 'ngg_tag' ); break; } } nggGallery::show_message( __( 'Tags changed', 'nggallery' ) ); } } if ( isset( $_POST['updatepictures'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'ngg_updategallery' ) ) { // Update pictures. $success = false; if ( nggGallery::current_user_can( 'NextGEN Edit gallery options' ) && ! isset( $_GET['s'] ) ) { $tags = [ '', '', '', '
    ', '', '', '', '', '
    ', '
    ', '
    ', '', '
    ', '', '', '', '', '
    ', '', '', '', '
    ', '
    ', '
    ', '', '
    ', '', '

    ', '

    ', '

    ', '

    ', '

    ', '
    ', '
    ', '', '', '', '