public function remainingBytes() : int { return PHP_INT_MAX & $this->stat['size'] - $this->pos; }
/** * Stream decryption - Do not call directly * * @param ReadOnlyFile $input * @param MutableFile $output * @param Key $encKey * @param string $nonce * @param resource $mac (hash context) * @param Config $config * @throws FileAlert\AccessDenied */ private static final function streamDecrypt(ReadOnlyFile $input, MutableFile $output, KeyInterface $encKey, $nonce, $mac, Config $config, array &$chunk_macs) { if (!$encKey instanceof EncryptionKey) { throw new \ParagonIE\Halite\Alerts\InvalidKey('Argument 3: Expected an instance of EncryptionKey'); } $start = $input->getPos(); $cipher_end = $input->getSize() - $config->MAC_SIZE; // Begin the streaming decryption $input->reset($start); while ($input->remainingBytes() > $config->MAC_SIZE) { if ($input->getPos() + $config->BUFFER > $cipher_end) { $read = $input->readBytes($cipher_end - $input->getPos()); } else { $read = $input->readBytes($config->BUFFER); } \hash_update($mac, $read); $calcMAC = \hash_copy($mac); if ($calcMAC === false) { throw new CryptoException\CannotPerformOperation('An unknown error has occurred'); } $calc = \hash_final($calcMAC, true); if (empty($chunk_macs)) { throw new CryptoException\InvalidMessage('Invalid message authentication code'); } else { $chkmac = \array_shift($chunk_macs); if (!\hash_equals($chkmac, $calc)) { throw new CryptoException\InvalidMessage('Invalid message authentication code'); } } $decrypted = \Sodium\crypto_stream_xor($read, $nonce, $encKey->get()); $output->writeBytes($decrypted); \Sodium\increment($nonce); } \Sodium\memzero($nonce); return true; }