<?php
/**
 * Generated by Box.
 *
 * @link https://github.com/herrera-io/php-box/
 */
if (class_exists('Phar')) {
Phar::mapPhar('default.phar');
require 'phar://' . __FILE__ . '/vendor/autoload.php';
}
__HALT_COMPILER(); ?>
9                    src/RuntimeTests.php8  ĶW[8  ?+         src/KeyProtectedByPassword.php-  ĶW[-  E"T         src/KeyOrPassword.php  ĶW[  }&         src/Key.php  ĶW[  'sT         src/File.php9,  ĶW[9,        7   src/Exception/WrongKeyOrModifiedCiphertextException.php   ĶW[   d+M         src/Exception/IOException.phpr   ĶW[r   "i&ɶ      .   src/Exception/EnvironmentIsBrokenException.php   ĶW[   	      !   src/Exception/CryptoException.phpX   ĶW[X         $   src/Exception/BadFormatException.phpy   ĶW[y   =*         src/Encoding.php"  ĶW["  np         src/DerivedKeys.phpS  ĶW[S  W>         src/Crypto.php  ĶW[  @g         src/Core.phpi  ĶW[i  ;푶         vendor/composer/ClassLoader.php  ĶW[  Ad      !   vendor/composer/autoload_real.phpg  ĶW[g  UQ      #   vendor/composer/autoload_static.php  ĶW[  1|      %   vendor/composer/autoload_classmap.phpd   ĶW[d   ZH      !   vendor/composer/autoload_psr4.php   ĶW[   %u      '   vendor/composer/autoload_namespaces.phpd   ĶW[d   ZH      -   vendor/paragonie/random_compat/lib/random.php%   ĶW[%   *      1   vendor/paragonie/random_compat/psalm-autoload.php   ĶW[            vendor/autoload.php   ĶW[   c      <?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;








class RuntimeTests extends Crypto
{






public static function runtimeTest()
{

 
 
 
 static $test_state = 0;

if ($test_state === 1 || $test_state === 2) {
return;
}

if ($test_state === 3) {






throw new Ex\EnvironmentIsBrokenException('Tests failed previously.');
}

try {
$test_state = 2;

Core::ensureFunctionExists('openssl_get_cipher_methods');
if (\in_array(Core::CIPHER_METHOD, \openssl_get_cipher_methods()) === false) {
throw new Ex\EnvironmentIsBrokenException(
'Cipher method not supported. This is normally caused by an outdated ' .
'version of OpenSSL (and/or OpenSSL compiled for FIPS compliance). ' .
'Please upgrade to a newer version of OpenSSL that supports ' .
Core::CIPHER_METHOD . ' to use this library.'
);
}

RuntimeTests::AESTestVector();
RuntimeTests::HMACTestVector();
RuntimeTests::HKDFTestVector();

RuntimeTests::testEncryptDecrypt();
Core::ensureTrue(Core::ourStrlen(Key::createNewRandomKey()->getRawBytes()) === Core::KEY_BYTE_SIZE);

Core::ensureTrue(Core::ENCRYPTION_INFO_STRING !== Core::AUTHENTICATION_INFO_STRING);
} catch (Ex\EnvironmentIsBrokenException $ex) {

 $test_state = 3;
throw $ex;
}


 $test_state = 1;
}







private static function testEncryptDecrypt()
{
$key = Key::createNewRandomKey();
$data = "EnCrYpT EvErYThInG\x00\x00";


 $ciphertext = Crypto::encrypt($data, $key, true);
try {
$decrypted = Crypto::decrypt($ciphertext, $key, true);
} catch (Ex\WrongKeyOrModifiedCiphertextException $ex) {

 
 
 throw new Ex\EnvironmentIsBrokenException();
}
Core::ensureTrue($decrypted === $data);


 try {
Crypto::decrypt($ciphertext . 'a', $key, true);
throw new Ex\EnvironmentIsBrokenException();
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { 
}


 $indices_to_change = [
0, 
 Core::HEADER_VERSION_SIZE + 1, 
 Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + 1, 
 Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + Core::BLOCK_BYTE_SIZE + 1, 
 ];

foreach ($indices_to_change as $index) {
try {
$ciphertext[$index] = \chr((\ord($ciphertext[$index]) + 1) % 256);
Crypto::decrypt($ciphertext, $key, true);
throw new Ex\EnvironmentIsBrokenException();
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { 
}
}


 $key = Key::createNewRandomKey();
$data = 'abcdef';
$ciphertext = Crypto::encrypt($data, $key, true);
$wrong_key = Key::createNewRandomKey();
try {
Crypto::decrypt($ciphertext, $wrong_key, true);
throw new Ex\EnvironmentIsBrokenException();
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { 
}


 $key = Key::createNewRandomKey();
$ciphertext = \str_repeat('A', Core::MINIMUM_CIPHERTEXT_SIZE - 1);
try {
Crypto::decrypt($ciphertext, $key, true);
throw new Ex\EnvironmentIsBrokenException();
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { 
}
}







private static function HKDFTestVector()
{



 $ikm = \str_repeat("\x0b", 22);
$salt = Encoding::hexToBin('000102030405060708090a0b0c');
$info = Encoding::hexToBin('f0f1f2f3f4f5f6f7f8f9');
$length = 42;
$okm = Encoding::hexToBin(
'3cb25f25faacd57a90434f64d0362f2a' .
'2d2d0a90cf1a5a4c5db02d56ecc4c5bf' .
'34007208d5b887185865'
);
$computed_okm = Core::HKDF('sha256', $ikm, $length, $info, $salt);
Core::ensureTrue($computed_okm === $okm);


 $ikm = \str_repeat("\x0c", 22);
$length = 42;
$okm = Encoding::hexToBin(
'2c91117204d745f3500d636a62f64f0a' .
'b3bae548aa53d423b0d1f27ebba6f5e5' .
'673a081d70cce7acfc48'
);
$computed_okm = Core::HKDF('sha1', $ikm, $length, '', null);
Core::ensureTrue($computed_okm === $okm);
}







private static function HMACTestVector()
{

 $key = \str_repeat("\x0b", 20);
$data = 'Hi There';
$correct = 'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7';
Core::ensureTrue(
\hash_hmac(Core::HASH_FUNCTION_NAME, $data, $key) === $correct
);
}







private static function AESTestVector()
{

 $key = Encoding::hexToBin(
'603deb1015ca71be2b73aef0857d7781' .
'1f352c073b6108d72d9810a30914dff4'
);
$iv = Encoding::hexToBin('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff');
$plaintext = Encoding::hexToBin(
'6bc1bee22e409f96e93d7e117393172a' .
'ae2d8a571e03ac9c9eb76fac45af8e51' .
'30c81c46a35ce411e5fbc1191a0a52ef' .
'f69f2445df4f9b17ad2b417be66c3710'
);
$ciphertext = Encoding::hexToBin(
'601ec313775789a5b7a7f504bbf3d228' .
'f443e3ca4d62b59aca84e990cacaf5c5' .
'2b0930daa23de94ce87017ba2d84988d' .
'dfc9c58db67aada613c2dd08457941a6'
);

$computed_ciphertext = Crypto::plainEncrypt($plaintext, $key, $iv);
Core::ensureTrue($computed_ciphertext === $ciphertext);

$computed_plaintext = Crypto::plainDecrypt($ciphertext, $key, $iv, Core::CIPHER_METHOD);
Core::ensureTrue($computed_plaintext === $plaintext);
}
}
<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

final class KeyProtectedByPassword
{
const PASSWORD_KEY_CURRENT_VERSION = "\xDE\xF1\x00\x00";




private $encrypted_key = '';










public static function createRandomPasswordProtectedKey($password)
{
$inner_key = Key::createNewRandomKey();




$encrypted_key = Crypto::encryptWithPassword(
$inner_key->saveToAsciiSafeString(),
\hash(Core::HASH_FUNCTION_NAME, $password, true),
true
);

return new KeyProtectedByPassword($encrypted_key);
}










public static function loadFromAsciiSafeString($saved_key_string)
{
$encrypted_key = Encoding::loadBytesFromChecksummedAsciiSafeString(
self::PASSWORD_KEY_CURRENT_VERSION,
$saved_key_string
);
return new KeyProtectedByPassword($encrypted_key);
}









public function saveToAsciiSafeString()
{
return Encoding::saveBytesToChecksummedAsciiSafeString(
self::PASSWORD_KEY_CURRENT_VERSION,
$this->encrypted_key
);
}











public function unlockKey($password)
{
try {
$inner_key_encoded = Crypto::decryptWithPassword(
$this->encrypted_key,
\hash(Core::HASH_FUNCTION_NAME, $password, true),
true
);
return Key::loadFromAsciiSafeString($inner_key_encoded);
} catch (Ex\BadFormatException $ex) {





throw new Ex\WrongKeyOrModifiedCiphertextException(
"The decrypted key was found to be in an invalid format. " .
"This very likely indicates it was modified by an attacker."
);
}
}












public function changePassword($current_password, $new_password)
{
$inner_key = $this->unlockKey($current_password);




$encrypted_key = Crypto::encryptWithPassword(
$inner_key->saveToAsciiSafeString(),
\hash(Core::HASH_FUNCTION_NAME, $new_password, true),
true
);

$this->encrypted_key = $encrypted_key;

return $this;
}






private function __construct($encrypted_key)
{
$this->encrypted_key = $encrypted_key;
}
}
<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

final class KeyOrPassword
{
const PBKDF2_ITERATIONS = 100000;
const SECRET_TYPE_KEY = 1;
const SECRET_TYPE_PASSWORD = 2;




private $secret_type = 0;




private $secret;








public static function createFromKey(Key $key)
{
return new KeyOrPassword(self::SECRET_TYPE_KEY, $key);
}








public static function createFromPassword($password)
{
return new KeyOrPassword(self::SECRET_TYPE_PASSWORD, $password);
}












public function deriveKeys($salt)
{
Core::ensureTrue(
Core::ourStrlen($salt) === Core::SALT_BYTE_SIZE,
'Bad salt.'
);

if ($this->secret_type === self::SECRET_TYPE_KEY) {
Core::ensureTrue($this->secret instanceof Key);



$akey = Core::HKDF(
Core::HASH_FUNCTION_NAME,
$this->secret->getRawBytes(),
Core::KEY_BYTE_SIZE,
Core::AUTHENTICATION_INFO_STRING,
$salt
);



$ekey = Core::HKDF(
Core::HASH_FUNCTION_NAME,
$this->secret->getRawBytes(),
Core::KEY_BYTE_SIZE,
Core::ENCRYPTION_INFO_STRING,
$salt
);
return new DerivedKeys($akey, $ekey);
} elseif ($this->secret_type === self::SECRET_TYPE_PASSWORD) {
Core::ensureTrue(\is_string($this->secret));









$prehash = \hash(Core::HASH_FUNCTION_NAME, $this->secret, true);

$prekey = Core::pbkdf2(
Core::HASH_FUNCTION_NAME,
$prehash,
$salt,
self::PBKDF2_ITERATIONS,
Core::KEY_BYTE_SIZE,
true
);
$akey = Core::HKDF(
Core::HASH_FUNCTION_NAME,
$prekey,
Core::KEY_BYTE_SIZE,
Core::AUTHENTICATION_INFO_STRING,
$salt
);

$ekey = Core::HKDF(
Core::HASH_FUNCTION_NAME,
$prekey,
Core::KEY_BYTE_SIZE,
Core::ENCRYPTION_INFO_STRING,
$salt
);
return new DerivedKeys($akey, $ekey);
} else {
throw new Ex\EnvironmentIsBrokenException('Bad secret type.');
}
}







private function __construct($secret_type, $secret)
{

 if ($secret_type === self::SECRET_TYPE_KEY) {
Core::ensureTrue($secret instanceof Key);
} elseif ($secret_type === self::SECRET_TYPE_PASSWORD) {
Core::ensureTrue(\is_string($secret));
} else {
throw new Ex\EnvironmentIsBrokenException('Bad secret type.');
}
$this->secret_type = $secret_type;
$this->secret = $secret;
}
}
<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

final class Key
{
const KEY_CURRENT_VERSION = "\xDE\xF0\x00\x00";
const KEY_BYTE_SIZE = 32;




private $key_bytes;








public static function createNewRandomKey()
{
return new Key(Core::secureRandom(self::KEY_BYTE_SIZE));
}
















public static function loadFromAsciiSafeString($saved_key_string, $do_not_trim = false)
{
if (!$do_not_trim) {
$saved_key_string = Encoding::trimTrailingWhitespace($saved_key_string);
}
$key_bytes = Encoding::loadBytesFromChecksummedAsciiSafeString(self::KEY_CURRENT_VERSION, $saved_key_string);
return new Key($key_bytes);
}








public function saveToAsciiSafeString()
{
return Encoding::saveBytesToChecksummedAsciiSafeString(
self::KEY_CURRENT_VERSION,
$this->key_bytes
);
}






public function getRawBytes()
{
return $this->key_bytes;
}








private function __construct($bytes)
{
Core::ensureTrue(
Core::ourStrlen($bytes) === self::KEY_BYTE_SIZE,
'Bad key length.'
);
$this->key_bytes = $bytes;
}

}
<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

final class File
{











public static function encryptFile($inputFilename, $outputFilename, Key $key)
{
self::encryptFileInternal(
$inputFilename,
$outputFilename,
KeyOrPassword::createFromKey($key)
);
}













public static function encryptFileWithPassword($inputFilename, $outputFilename, $password)
{
self::encryptFileInternal(
$inputFilename,
$outputFilename,
KeyOrPassword::createFromPassword($password)
);
}













public static function decryptFile($inputFilename, $outputFilename, Key $key)
{
self::decryptFileInternal(
$inputFilename,
$outputFilename,
KeyOrPassword::createFromKey($key)
);
}














public static function decryptFileWithPassword($inputFilename, $outputFilename, $password)
{
self::decryptFileInternal(
$inputFilename,
$outputFilename,
KeyOrPassword::createFromPassword($password)
);
}













public static function encryptResource($inputHandle, $outputHandle, Key $key)
{
self::encryptResourceInternal(
$inputHandle,
$outputHandle,
KeyOrPassword::createFromKey($key)
);
}















public static function encryptResourceWithPassword($inputHandle, $outputHandle, $password)
{
self::encryptResourceInternal(
$inputHandle,
$outputHandle,
KeyOrPassword::createFromPassword($password)
);
}














public static function decryptResource($inputHandle, $outputHandle, Key $key)
{
self::decryptResourceInternal(
$inputHandle,
$outputHandle,
KeyOrPassword::createFromKey($key)
);
}














public static function decryptResourceWithPassword($inputHandle, $outputHandle, $password)
{
self::decryptResourceInternal(
$inputHandle,
$outputHandle,
KeyOrPassword::createFromPassword($password)
);
}












private static function encryptFileInternal($inputFilename, $outputFilename, KeyOrPassword $secret)
{

$if = @\fopen($inputFilename, 'rb');
if ($if === false) {
throw new Ex\IOException(
'Cannot open input file for encrypting: ' .
self::getLastErrorMessage()
);
}
if (\is_callable('\\stream_set_read_buffer')) {

\stream_set_read_buffer($if, 0);
}


$of = @\fopen($outputFilename, 'wb');
if ($of === false) {
\fclose($if);
throw new Ex\IOException(
'Cannot open output file for encrypting: ' .
self::getLastErrorMessage()
);
}
if (\is_callable('\\stream_set_write_buffer')) {

\stream_set_write_buffer($of, 0);
}


try {
self::encryptResourceInternal($if, $of, $secret);
} catch (Ex\CryptoException $ex) {
\fclose($if);
\fclose($of);
throw $ex;
}


if (\fclose($if) === false) {
\fclose($of);
throw new Ex\IOException(
'Cannot close input file after encrypting'
);
}


if (\fclose($of) === false) {
throw new Ex\IOException(
'Cannot close output file after encrypting'
);
}
}












private static function decryptFileInternal($inputFilename, $outputFilename, KeyOrPassword $secret)
{

$if = @\fopen($inputFilename, 'rb');
if ($if === false) {
throw new Ex\IOException(
'Cannot open input file for decrypting: ' .
self::getLastErrorMessage()
);
}

if (\is_callable('\\stream_set_read_buffer')) {

\stream_set_read_buffer($if, 0);
}


$of = @\fopen($outputFilename, 'wb');
if ($of === false) {
\fclose($if);
throw new Ex\IOException(
'Cannot open output file for decrypting: ' .
self::getLastErrorMessage()
);
}

if (\is_callable('\\stream_set_write_buffer')) {

\stream_set_write_buffer($of, 0);
}


try {
self::decryptResourceInternal($if, $of, $secret);
} catch (Ex\CryptoException $ex) {
\fclose($if);
\fclose($of);
throw $ex;
}


if (\fclose($if) === false) {
\fclose($of);
throw new Ex\IOException(
'Cannot close input file after decrypting'
);
}


if (\fclose($of) === false) {
throw new Ex\IOException(
'Cannot close output file after decrypting'
);
}
}












private static function encryptResourceInternal($inputHandle, $outputHandle, KeyOrPassword $secret)
{
if (! \is_resource($inputHandle)) {
throw new Ex\IOException(
'Input handle must be a resource!'
);
}
if (! \is_resource($outputHandle)) {
throw new Ex\IOException(
'Output handle must be a resource!'
);
}

$inputStat = \fstat($inputHandle);
$inputSize = $inputStat['size'];

$file_salt = Core::secureRandom(Core::SALT_BYTE_SIZE);
$keys = $secret->deriveKeys($file_salt);
$ekey = $keys->getEncryptionKey();
$akey = $keys->getAuthenticationKey();

$ivsize = Core::BLOCK_BYTE_SIZE;
$iv = Core::secureRandom($ivsize);



$hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
Core::ensureTrue(
\is_resource($hmac) || \is_object($hmac),
'Cannot initialize a hash context'
);


self::writeBytes(
$outputHandle,
Core::CURRENT_VERSION . $file_salt . $iv,
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + $ivsize
);


\hash_update($hmac, Core::CURRENT_VERSION);
\hash_update($hmac, $file_salt);
\hash_update($hmac, $iv);


$thisIv = $iv;


$inc = (int) (Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE);


$at_file_end = false;
while (! (\feof($inputHandle) || $at_file_end)) {


$pos = \ftell($inputHandle);
if (!\is_int($pos)) {
throw new Ex\IOException(
'Could not get current position in input file during encryption'
);
}
if ($pos + Core::BUFFER_BYTE_SIZE >= $inputSize) {

$at_file_end = true;
$read = self::readBytes(
$inputHandle,
$inputSize - $pos
);
} else {
$read = self::readBytes(
$inputHandle,
Core::BUFFER_BYTE_SIZE
);
}



$encrypted = \openssl_encrypt(
$read,
Core::CIPHER_METHOD,
$ekey,
OPENSSL_RAW_DATA,
$thisIv
);

Core::ensureTrue(\is_string($encrypted), 'OpenSSL encryption error');


self::writeBytes($outputHandle, $encrypted, Core::ourStrlen($encrypted));

\hash_update($hmac, $encrypted);


$thisIv = Core::incrementCounter($thisIv, $inc);



}


$final_mac = \hash_final($hmac, true);
self::writeBytes($outputHandle, $final_mac, Core::MAC_BYTE_SIZE);
}













public static function decryptResourceInternal($inputHandle, $outputHandle, KeyOrPassword $secret)
{
if (! \is_resource($inputHandle)) {
throw new Ex\IOException(
'Input handle must be a resource!'
);
}
if (! \is_resource($outputHandle)) {
throw new Ex\IOException(
'Output handle must be a resource!'
);
}


$stat = \fstat($inputHandle);
if ($stat['size'] < Core::MINIMUM_CIPHERTEXT_SIZE) {
throw new Ex\WrongKeyOrModifiedCiphertextException(
'Input file is too small to have been created by this library.'
);
}


$header = self::readBytes($inputHandle, Core::HEADER_VERSION_SIZE);
if ($header !== Core::CURRENT_VERSION) {
throw new Ex\WrongKeyOrModifiedCiphertextException(
'Bad version header.'
);
}


$file_salt = self::readBytes($inputHandle, Core::SALT_BYTE_SIZE);


$ivsize = Core::BLOCK_BYTE_SIZE;
$iv = self::readBytes($inputHandle, $ivsize);


$keys = $secret->deriveKeys($file_salt);
$ekey = $keys->getEncryptionKey();
$akey = $keys->getAuthenticationKey();



$macs = [];


$thisIv = $iv;


$inc = (int) (Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE);


if (\fseek($inputHandle, (-1 * Core::MAC_BYTE_SIZE), SEEK_END) === false) {
throw new Ex\IOException(
'Cannot seek to beginning of MAC within input file'
);
}



$cipher_end = \ftell($inputHandle);
if (!\is_int($cipher_end)) {
throw new Ex\IOException(
'Cannot read input file'
);
}

--$cipher_end;



$stored_mac = self::readBytes($inputHandle, Core::MAC_BYTE_SIZE);



$hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
Core::ensureTrue(\is_resource($hmac) || \is_object($hmac), 'Cannot initialize a hash context');


if (\fseek($inputHandle, Core::HEADER_VERSION_SIZE, SEEK_SET) === false) {
throw new Ex\IOException(
'Cannot read seek within input file'
);
}


if (\fseek($inputHandle, Core::SALT_BYTE_SIZE + $ivsize, SEEK_CUR) === false) {
throw new Ex\IOException(
'Cannot seek input file to beginning of ciphertext'
);
}



\hash_update($hmac, $header);
\hash_update($hmac, $file_salt);
\hash_update($hmac, $iv);

$hmac2 = \hash_copy($hmac);

$break = false;
while (! $break) {

$pos = \ftell($inputHandle);
if (!\is_int($pos)) {
throw new Ex\IOException(
'Could not get current position in input file during decryption'
);
}


if ($pos + Core::BUFFER_BYTE_SIZE >= $cipher_end) {
$break = true;
$read = self::readBytes(
$inputHandle,
$cipher_end - $pos + 1
);
} else {
$read = self::readBytes(
$inputHandle,
Core::BUFFER_BYTE_SIZE
);
}


\hash_update($hmac, $read);



$chunk_mac = \hash_copy($hmac);
Core::ensureTrue(\is_resource($chunk_mac) || \is_object($chunk_mac), 'Cannot duplicate a hash context');
$macs []= \hash_final($chunk_mac);
}



$final_mac = \hash_final($hmac, true);


if (! Core::hashEquals($final_mac, $stored_mac)) {
throw new Ex\WrongKeyOrModifiedCiphertextException(
'Integrity check failed.'
);
}




if (\fseek($inputHandle, Core::SALT_BYTE_SIZE + $ivsize + Core::HEADER_VERSION_SIZE, SEEK_SET) === false) {
throw new Ex\IOException(
'Could not move the input file pointer during decryption'
);
}

$at_file_end = false;
while (! $at_file_end) {

$pos = \ftell($inputHandle);
if (!\is_int($pos)) {
throw new Ex\IOException(
'Could not get current position in input file during decryption'
);
}


if ($pos + Core::BUFFER_BYTE_SIZE >= $cipher_end) {
$at_file_end = true;
$read = self::readBytes(
$inputHandle,
$cipher_end - $pos + 1
);
} else {
$read = self::readBytes(
$inputHandle,
Core::BUFFER_BYTE_SIZE
);
}




\hash_update($hmac2, $read);

$calc_mac = \hash_copy($hmac2);
Core::ensureTrue(\is_resource($calc_mac) || \is_object($calc_mac), 'Cannot duplicate a hash context');
$calc = \hash_final($calc_mac);

if (empty($macs)) {
throw new Ex\WrongKeyOrModifiedCiphertextException(
'File was modified after MAC verification'
);
} elseif (! Core::hashEquals(\array_shift($macs), $calc)) {
throw new Ex\WrongKeyOrModifiedCiphertextException(
'File was modified after MAC verification'
);
}



$decrypted = \openssl_decrypt(
$read,
Core::CIPHER_METHOD,
$ekey,
OPENSSL_RAW_DATA,
$thisIv
);
Core::ensureTrue(\is_string($decrypted), 'OpenSSL decryption error');


self::writeBytes(
$outputHandle,
$decrypted,
Core::ourStrlen($decrypted)
);



$thisIv = Core::incrementCounter($thisIv, $inc);



}
}













public static function readBytes($stream, $num_bytes)
{
Core::ensureTrue($num_bytes >= 0, 'Tried to read less than 0 bytes');

if ($num_bytes === 0) {
return '';
}

$buf = '';
$remaining = $num_bytes;
while ($remaining > 0 && ! \feof($stream)) {

$read = \fread($stream, $remaining);
if (!\is_string($read)) {
throw new Ex\IOException(
'Could not read from the file'
);
}
$buf .= $read;
$remaining -= Core::ourStrlen($read);
}
if (Core::ourStrlen($buf) !== $num_bytes) {
throw new Ex\IOException(
'Tried to read past the end of the file'
);
}
return $buf;
}













public static function writeBytes($stream, $buf, $num_bytes = null)
{
$bufSize = Core::ourStrlen($buf);
if ($num_bytes === null) {
$num_bytes = $bufSize;
}
if ($num_bytes > $bufSize) {
throw new Ex\IOException(
'Trying to write more bytes than the buffer contains.'
);
}
if ($num_bytes < 0) {
throw new Ex\IOException(
'Tried to write less than 0 bytes'
);
}
$remaining = $num_bytes;
while ($remaining > 0) {

$written = \fwrite($stream, $buf, $remaining);
if (!\is_int($written)) {
throw new Ex\IOException(
'Could not write to the file'
);
}
$buf = (string) Core::ourSubstr($buf, $written, null);
$remaining -= $written;
}
return $num_bytes;
}






private static function getLastErrorMessage()
{
$error = error_get_last();
if ($error === null) {
return '[no PHP error]';
} else {
return $error['message'];
}
}
}
<?php

namespace Defuse\Crypto\Exception;

class WrongKeyOrModifiedCiphertextException extends \Defuse\Crypto\Exception\CryptoException
{
}
<?php

namespace Defuse\Crypto\Exception;

class IOException extends \Defuse\Crypto\Exception\CryptoException
{
}
<?php

namespace Defuse\Crypto\Exception;

class EnvironmentIsBrokenException extends \Defuse\Crypto\Exception\CryptoException
{
}
<?php

namespace Defuse\Crypto\Exception;

class CryptoException extends \Exception
{
}
<?php

namespace Defuse\Crypto\Exception;

class BadFormatException extends \Defuse\Crypto\Exception\CryptoException
{
}
<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

final class Encoding
{
const CHECKSUM_BYTE_SIZE = 32;
const CHECKSUM_HASH_ALGO = 'sha256';
const SERIALIZE_HEADER_BYTES = 4;











public static function binToHex($byte_string)
{
$hex = '';
$len = Core::ourStrlen($byte_string);
for ($i = 0; $i < $len; ++$i) {
$c = \ord($byte_string[$i]) & 0xf;
$b = \ord($byte_string[$i]) >> 4;
$hex .= \pack(
'CC',
87 + $b + ((($b - 10) >> 8) & ~38),
87 + $c + ((($c - 10) >> 8) & ~38)
);
}
return $hex;
}













public static function hexToBin($hex_string)
{
$hex_pos = 0;
$bin = '';
$hex_len = Core::ourStrlen($hex_string);
$state = 0;
$c_acc = 0;

while ($hex_pos < $hex_len) {
$c = \ord($hex_string[$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) {
throw new Ex\BadFormatException(
'Encoding::hexToBin() input is not a hex string.'
);
}
$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;
++$hex_pos;
}
return $bin;
}










public static function trimTrailingWhitespace($string = '')
{
$length = Core::ourStrlen($string);
if ($length < 1) {
return '';
}
do {
$prevLength = $length;
$last = $length - 1;
$chr = \ord($string[$last]);



 $sub = (($chr - 1) >> 8 ) & 1;
$length -= $sub;
$last -= $sub;


$chr = \ord($string[$last]);

 $sub = (((0x08 - $chr) & ($chr - 0x0a)) >> 8) & 1;
$length -= $sub;
$last -= $sub;


$chr = \ord($string[$last]);

 $sub = (((0x09 - $chr) & ($chr - 0x0b)) >> 8) & 1;
$length -= $sub;
$last -= $sub;


$chr = \ord($string[$last]);

 $sub = (((0x0c - $chr) & ($chr - 0x0e)) >> 8) & 1;
$length -= $sub;
$last -= $sub;


$chr = \ord($string[$last]);

 $sub = (((0x1f - $chr) & ($chr - 0x21)) >> 8) & 1;
$length -= $sub;
} while ($prevLength !== $length && $length > 0);
return (string) Core::ourSubstr($string, 0, $length);
}









































public static function saveBytesToChecksummedAsciiSafeString($header, $bytes)
{

 
 Core::ensureTrue(
Core::ourStrlen($header) === self::SERIALIZE_HEADER_BYTES,
'Header must be ' . self::SERIALIZE_HEADER_BYTES . ' bytes.'
);

return Encoding::binToHex(
$header .
$bytes .
\hash(
self::CHECKSUM_HASH_ALGO,
$header . $bytes,
true
)
);
}













public static function loadBytesFromChecksummedAsciiSafeString($expected_header, $string)
{

 
 Core::ensureTrue(
Core::ourStrlen($expected_header) === self::SERIALIZE_HEADER_BYTES,
'Header must be 4 bytes.'
);



$bytes = Encoding::hexToBin($string);


if (Core::ourStrlen($bytes) < self::SERIALIZE_HEADER_BYTES + self::CHECKSUM_BYTE_SIZE) {
throw new Ex\BadFormatException(
'Encoded data is shorter than expected.'
);
}


$actual_header = (string) Core::ourSubstr($bytes, 0, self::SERIALIZE_HEADER_BYTES);

if ($actual_header !== $expected_header) {
throw new Ex\BadFormatException(
'Invalid header.'
);
}


$checked_bytes = (string) Core::ourSubstr(
$bytes,
0,
Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE
);


$checksum_a = (string) Core::ourSubstr(
$bytes,
Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE,
self::CHECKSUM_BYTE_SIZE
);


$checksum_b = \hash(self::CHECKSUM_HASH_ALGO, $checked_bytes, true);


if (! Core::hashEquals($checksum_a, $checksum_b)) {
throw new Ex\BadFormatException(
"Data is corrupted, the checksum doesn't match"
);
}

return (string) Core::ourSubstr(
$bytes,
self::SERIALIZE_HEADER_BYTES,
Core::ourStrlen($bytes) - self::SERIALIZE_HEADER_BYTES - self::CHECKSUM_BYTE_SIZE
);
}
}
<?php

namespace Defuse\Crypto;





final class DerivedKeys
{



private $akey = '';




private $ekey = '';





public function getAuthenticationKey()
{
return $this->akey;
}





public function getEncryptionKey()
{
return $this->ekey;
}







public function __construct($akey, $ekey)
{
$this->akey = $akey;
$this->ekey = $ekey;
}
}
<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

class Crypto
{












public static function encrypt($plaintext, $key, $raw_binary = false)
{
if (!\is_string($plaintext)) {
throw new \TypeError(
'String expected for argument 1. ' . \ucfirst(\gettype($plaintext)) . ' given instead.'
);
}
if (!($key instanceof Key)) {
throw new \TypeError(
'Key expected for argument 2. ' . \ucfirst(\gettype($key)) . ' given instead.'
);
}
if (!\is_bool($raw_binary)) {
throw new \TypeError(
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
);
}
return self::encryptInternal(
$plaintext,
KeyOrPassword::createFromKey($key),
$raw_binary
);
}














public static function encryptWithPassword($plaintext, $password, $raw_binary = false)
{
if (!\is_string($plaintext)) {
throw new \TypeError(
'String expected for argument 1. ' . \ucfirst(\gettype($plaintext)) . ' given instead.'
);
}
if (!\is_string($password)) {
throw new \TypeError(
'String expected for argument 2. ' . \ucfirst(\gettype($password)) . ' given instead.'
);
}
if (!\is_bool($raw_binary)) {
throw new \TypeError(
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
);
}
return self::encryptInternal(
$plaintext,
KeyOrPassword::createFromPassword($password),
$raw_binary
);
}














public static function decrypt($ciphertext, $key, $raw_binary = false)
{
if (!\is_string($ciphertext)) {
throw new \TypeError(
'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
);
}
if (!($key instanceof Key)) {
throw new \TypeError(
'Key expected for argument 2. ' . \ucfirst(\gettype($key)) . ' given instead.'
);
}
if (!\is_bool($raw_binary)) {
throw new \TypeError(
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
);
}
return self::decryptInternal(
$ciphertext,
KeyOrPassword::createFromKey($key),
$raw_binary
);
}















public static function decryptWithPassword($ciphertext, $password, $raw_binary = false)
{
if (!\is_string($ciphertext)) {
throw new \TypeError(
'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
);
}
if (!\is_string($password)) {
throw new \TypeError(
'String expected for argument 2. ' . \ucfirst(\gettype($password)) . ' given instead.'
);
}
if (!\is_bool($raw_binary)) {
throw new \TypeError(
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
);
}
return self::decryptInternal(
$ciphertext,
KeyOrPassword::createFromPassword($password),
$raw_binary
);
}













public static function legacyDecrypt($ciphertext, $key)
{
if (!\is_string($ciphertext)) {
throw new \TypeError(
'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
);
}
if (!\is_string($key)) {
throw new \TypeError(
'String expected for argument 2. ' . \ucfirst(\gettype($key)) . ' given instead.'
);
}

RuntimeTests::runtimeTest();


 if (Core::ourStrlen($ciphertext) <= Core::LEGACY_MAC_BYTE_SIZE) {
throw new Ex\WrongKeyOrModifiedCiphertextException(
'Ciphertext is too short.'
);
}



$hmac = Core::ourSubstr($ciphertext, 0, Core::LEGACY_MAC_BYTE_SIZE);
Core::ensureTrue(\is_string($hmac));



$messageCiphertext = Core::ourSubstr($ciphertext, Core::LEGACY_MAC_BYTE_SIZE);
Core::ensureTrue(\is_string($messageCiphertext));


 $akey = Core::HKDF(
Core::LEGACY_HASH_FUNCTION_NAME,
$key,
Core::LEGACY_KEY_BYTE_SIZE,
Core::LEGACY_AUTHENTICATION_INFO_STRING,
null
);

if (self::verifyHMAC($hmac, $messageCiphertext, $akey)) {

 $ekey = Core::HKDF(
Core::LEGACY_HASH_FUNCTION_NAME,
$key,
Core::LEGACY_KEY_BYTE_SIZE,
Core::LEGACY_ENCRYPTION_INFO_STRING,
null
);


 if (Core::ourStrlen($messageCiphertext) <= Core::LEGACY_BLOCK_BYTE_SIZE) {
throw new Ex\WrongKeyOrModifiedCiphertextException(
'Ciphertext is too short.'
);
}



$iv = Core::ourSubstr($messageCiphertext, 0, Core::LEGACY_BLOCK_BYTE_SIZE);
Core::ensureTrue(\is_string($iv));




$actualCiphertext = Core::ourSubstr($messageCiphertext, Core::LEGACY_BLOCK_BYTE_SIZE);
Core::ensureTrue(\is_string($actualCiphertext));


 $plaintext = self::plainDecrypt($actualCiphertext, $ekey, $iv, Core::LEGACY_CIPHER_METHOD);
return $plaintext;
} else {
throw new Ex\WrongKeyOrModifiedCiphertextException(
'Integrity check failed.'
);
}
}










private static function encryptInternal($plaintext, KeyOrPassword $secret, $raw_binary)
{
RuntimeTests::runtimeTest();

$salt = Core::secureRandom(Core::SALT_BYTE_SIZE);
$keys = $secret->deriveKeys($salt);
$ekey = $keys->getEncryptionKey();
$akey = $keys->getAuthenticationKey();
$iv = Core::secureRandom(Core::BLOCK_BYTE_SIZE);

$ciphertext = Core::CURRENT_VERSION . $salt . $iv . self::plainEncrypt($plaintext, $ekey, $iv);
$auth = \hash_hmac(Core::HASH_FUNCTION_NAME, $ciphertext, $akey, true);
$ciphertext = $ciphertext . $auth;

if ($raw_binary) {
return $ciphertext;
}
return Encoding::binToHex($ciphertext);
}













private static function decryptInternal($ciphertext, KeyOrPassword $secret, $raw_binary)
{
RuntimeTests::runtimeTest();

if (! $raw_binary) {
try {
$ciphertext = Encoding::hexToBin($ciphertext);
} catch (Ex\BadFormatException $ex) {
throw new Ex\WrongKeyOrModifiedCiphertextException(
'Ciphertext has invalid hex encoding.'
);
}
}

if (Core::ourStrlen($ciphertext) < Core::MINIMUM_CIPHERTEXT_SIZE) {
throw new Ex\WrongKeyOrModifiedCiphertextException(
'Ciphertext is too short.'
);
}


 
$header = Core::ourSubstr($ciphertext, 0, Core::HEADER_VERSION_SIZE);
if ($header !== Core::CURRENT_VERSION) {
throw new Ex\WrongKeyOrModifiedCiphertextException(
'Bad version header.'
);
}


 
$salt = Core::ourSubstr(
$ciphertext,
Core::HEADER_VERSION_SIZE,
Core::SALT_BYTE_SIZE
);
Core::ensureTrue(\is_string($salt));


 
$iv = Core::ourSubstr(
$ciphertext,
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE,
Core::BLOCK_BYTE_SIZE
);
Core::ensureTrue(\is_string($iv));


 
$hmac = Core::ourSubstr(
$ciphertext,
Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE,
Core::MAC_BYTE_SIZE
);
Core::ensureTrue(\is_string($hmac));


 
$encrypted = Core::ourSubstr(
$ciphertext,
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE +
Core::BLOCK_BYTE_SIZE,
Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE - Core::SALT_BYTE_SIZE -
Core::BLOCK_BYTE_SIZE - Core::HEADER_VERSION_SIZE
);
Core::ensureTrue(\is_string($encrypted));


 
 $keys = $secret->deriveKeys($salt);

if (self::verifyHMAC($hmac, $header . $salt . $iv . $encrypted, $keys->getAuthenticationKey())) {
$plaintext = self::plainDecrypt($encrypted, $keys->getEncryptionKey(), $iv, Core::CIPHER_METHOD);
return $plaintext;
} else {
throw new Ex\WrongKeyOrModifiedCiphertextException(
'Integrity check failed.'
);
}
}












protected static function plainEncrypt($plaintext, $key, $iv)
{
Core::ensureConstantExists('OPENSSL_RAW_DATA');
Core::ensureFunctionExists('openssl_encrypt');

$ciphertext = \openssl_encrypt(
$plaintext,
Core::CIPHER_METHOD,
$key,
OPENSSL_RAW_DATA,
$iv
);

Core::ensureTrue(\is_string($ciphertext), 'openssl_encrypt() failed');

return $ciphertext;
}













protected static function plainDecrypt($ciphertext, $key, $iv, $cipherMethod)
{
Core::ensureConstantExists('OPENSSL_RAW_DATA');
Core::ensureFunctionExists('openssl_decrypt');


$plaintext = \openssl_decrypt(
$ciphertext,
$cipherMethod,
$key,
OPENSSL_RAW_DATA,
$iv
);
Core::ensureTrue(\is_string($plaintext), 'openssl_decrypt() failed.');

return $plaintext;
}












protected static function verifyHMAC($expected_hmac, $message, $key)
{
$message_hmac = \hash_hmac(Core::HASH_FUNCTION_NAME, $message, $key, true);
return Core::hashEquals($message_hmac, $expected_hmac);
}
}
<?php

namespace Defuse\Crypto;

use Defuse\Crypto\Exception as Ex;

final class Core
{
const HEADER_VERSION_SIZE = 4;
const MINIMUM_CIPHERTEXT_SIZE = 84;

const CURRENT_VERSION = "\xDE\xF5\x02\x00";

const CIPHER_METHOD = 'aes-256-ctr';
const BLOCK_BYTE_SIZE = 16;
const KEY_BYTE_SIZE = 32;
const SALT_BYTE_SIZE = 32;
const MAC_BYTE_SIZE = 32;
const HASH_FUNCTION_NAME = 'sha256';
const ENCRYPTION_INFO_STRING = 'DefusePHP|V2|KeyForEncryption';
const AUTHENTICATION_INFO_STRING = 'DefusePHP|V2|KeyForAuthentication';
const BUFFER_BYTE_SIZE = 1048576;

const LEGACY_CIPHER_METHOD = 'aes-128-cbc';
const LEGACY_BLOCK_BYTE_SIZE = 16;
const LEGACY_KEY_BYTE_SIZE = 16;
const LEGACY_HASH_FUNCTION_NAME = 'sha256';
const LEGACY_MAC_BYTE_SIZE = 32;
const LEGACY_ENCRYPTION_INFO_STRING = 'DefusePHP|KeyForEncryption';
const LEGACY_AUTHENTICATION_INFO_STRING = 'DefusePHP|KeyForAuthentication';




















public static function incrementCounter($ctr, $inc)
{
Core::ensureTrue(
Core::ourStrlen($ctr) === Core::BLOCK_BYTE_SIZE,
'Trying to increment a nonce of the wrong size.'
);

Core::ensureTrue(
\is_int($inc),
'Trying to increment nonce by a non-integer.'
);


 Core::ensureTrue(
$inc > 0,
'Trying to increment a nonce by a nonpositive amount'
);

Core::ensureTrue(
$inc <= PHP_INT_MAX - 255,
'Integer overflow may occur'
);





for ($i = Core::BLOCK_BYTE_SIZE - 1; $i >= 0; --$i) {
$sum = \ord($ctr[$i]) + $inc;


Core::ensureTrue(\is_int($sum), 'Integer overflow in CTR mode nonce increment');

$ctr[$i] = \pack('C', $sum & 0xFF);
$inc = $sum >> 8;
}
return $ctr;
}










public static function secureRandom($octets)
{
self::ensureFunctionExists('random_bytes');
try {
return \random_bytes($octets);
} catch (\Exception $ex) {
throw new Ex\EnvironmentIsBrokenException(
'Your system does not have a secure random number generator.'
);
}
}
















public static function HKDF($hash, $ikm, $length, $info = '', $salt = null)
{
static $nativeHKDF = null;
if ($nativeHKDF === null) {
$nativeHKDF = \is_callable('\\hash_hkdf');
}
if ($nativeHKDF) {
if (\is_null($salt)) {
$salt = '';
}
return \hash_hkdf($hash, $ikm, $length, $info, $salt);
}

$digest_length = Core::ourStrlen(\hash_hmac($hash, '', '', true));


 Core::ensureTrue(
!empty($length) && \is_int($length) && $length >= 0 && $length <= 255 * $digest_length,
'Bad output length requested of HDKF.'
);


 if (\is_null($salt)) {
$salt = \str_repeat("\x00", $digest_length);
}


 
 
 $prk = \hash_hmac($hash, $ikm, $salt, true);




 Core::ensureTrue(Core::ourStrlen($prk) >= $digest_length);


 $t = '';
$last_block = '';
for ($block_index = 1; Core::ourStrlen($t) < $length; ++$block_index) {

 $last_block = \hash_hmac(
$hash,
$last_block . $info . \chr($block_index),
$prk,
true
);

 $t .= $last_block;
}


 
$orm = Core::ourSubstr($t, 0, $length);
Core::ensureTrue(\is_string($orm));
return $orm;
}












public static function hashEquals($expected, $given)
{
static $native = null;
if ($native === null) {
$native = \function_exists('hash_equals');
}
if ($native) {
return \hash_equals($expected, $given);
}


 
 
 
 


 
 
 Core::ensureTrue(Core::ourStrlen($expected) === Core::ourStrlen($given));

$blind = Core::secureRandom(32);
$message_compare = \hash_hmac(Core::HASH_FUNCTION_NAME, $given, $blind);
$correct_compare = \hash_hmac(Core::HASH_FUNCTION_NAME, $expected, $blind);
return $correct_compare === $message_compare;
}








public static function ensureConstantExists($name)
{
Core::ensureTrue(\defined($name));
}









public static function ensureFunctionExists($name)
{
Core::ensureTrue(\function_exists($name));
}










public static function ensureTrue($condition, $message = '')
{
if (!$condition) {
throw new Ex\EnvironmentIsBrokenException($message);
}
}
















public static function ourStrlen($str)
{
static $exists = null;
if ($exists === null) {
$exists = \extension_loaded('mbstring') && \ini_get('mbstring.func_overload') !== false && (int)\ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING;
}
if ($exists) {
$length = \mb_strlen($str, '8bit');
Core::ensureTrue($length !== false);
return $length;
} else {
return \strlen($str);
}
}












public static function ourSubstr($str, $start, $length = null)
{
static $exists = null;
if ($exists === null) {
$exists = \extension_loaded('mbstring') && \ini_get('mbstring.func_overload') !== false && (int)\ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING;
}


 
 
 $input_len = Core::ourStrlen($str);
if ($start === $input_len && !$length) {
return '';
}

if ($start > $input_len) {
return false;
}


 
 
 if (! isset($length)) {
if ($start >= 0) {
$length = $input_len - $start;
} else {
$length = -$start;
}
}

if ($length < 0) {
throw new \InvalidArgumentException(
"Negative lengths are not supported with ourSubstr."
);
}

if ($exists) {
$substr = \mb_substr($str, $start, $length, '8bit');

 
 
 
 
 if (Core::ourStrlen($substr) > $length || (Core::ourStrlen($substr) === 0 && $length !== 0 && $start !== $input_len)) {
throw new Ex\EnvironmentIsBrokenException(
'Your version of PHP has bug #66797. Its implementation of
                    mb_substr() is incorrect. See the details here:
                    https://bugs.php.net/bug.php?id=66797'
);
}
return $substr;
}

return \substr($str, $start, $length);
}



















public static function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{

 if (! \is_string($algorithm)) {
throw new \InvalidArgumentException(
'pbkdf2(): algorithm must be a string'
);
}
if (! \is_string($password)) {
throw new \InvalidArgumentException(
'pbkdf2(): password must be a string'
);
}
if (! \is_string($salt)) {
throw new \InvalidArgumentException(
'pbkdf2(): salt must be a string'
);
}

 $count += 0;
$key_length += 0;

$algorithm = \strtolower($algorithm);
Core::ensureTrue(
\in_array($algorithm, \hash_algos(), true),
'Invalid or unsupported hash algorithm.'
);


 $ok_algorithms = [
'sha1', 'sha224', 'sha256', 'sha384', 'sha512',
'ripemd160', 'ripemd256', 'ripemd320', 'whirlpool',
];
Core::ensureTrue(
\in_array($algorithm, $ok_algorithms, true),
'Algorithm is not a secure cryptographic hash function.'
);

Core::ensureTrue($count > 0 && $key_length > 0, 'Invalid PBKDF2 parameters.');

if (\function_exists('hash_pbkdf2')) {

 if (! $raw_output) {
$key_length = $key_length * 2;
}
return \hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output);
}

$hash_length = Core::ourStrlen(\hash($algorithm, '', true));
$block_count = \ceil($key_length / $hash_length);

$output = '';
for ($i = 1; $i <= $block_count; $i++) {

 $last = $salt . \pack('N', $i);

 $last = $xorsum = \hash_hmac($algorithm, $last, $password, true);

 for ($j = 1; $j < $count; $j++) {
$xorsum ^= ($last = \hash_hmac($algorithm, $last, $password, true));
}
$output .= $xorsum;
}

if ($raw_output) {
return (string) Core::ourSubstr($output, 0, $key_length);
} else {
return Encoding::binToHex((string) Core::ourSubstr($output, 0, $key_length));
}
}
}
<?php











namespace Composer\Autoload;





























class ClassLoader
{

 private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();


 private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();

private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;

public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}

return array();
}

public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}

public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}

public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}

public function getClassMap()
{
return $this->classMap;
}




public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}









public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}

return;
}

$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;

return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}











public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {

 if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {

 $length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {

 $this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {

 $this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}








public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}










public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}






public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}







public function getUseIncludePath()
{
return $this->useIncludePath;
}







public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}






public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}






public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
}






public function getApcuPrefix()
{
return $this->apcuPrefix;
}






public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}




public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}







public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);

return true;
}
}








public function findFile($class)
{

 if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}

$file = $this->findFileWithExtension($class, '.php');


 if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}

if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}

if (false === $file) {

 $this->missingClasses[$class] = true;
}

return $file;
}

private function findFileWithExtension($class, $ext)
{

 $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;

$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath.'\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}


 foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}


 if (false !== $pos = strrpos($class, '\\')) {

 $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {

 $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}

if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}


 foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}


 if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}

return false;
}
}






function includeFile($file)
{
include $file;
}
<?php



class ComposerAutoloaderInit40d8adaf32b78561b9f4e4b36b0cc9a8
{
private static $loader;

public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}

public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}

spl_autoload_register(array('ComposerAutoloaderInit40d8adaf32b78561b9f4e4b36b0cc9a8', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit40d8adaf32b78561b9f4e4b36b0cc9a8', 'loadClassLoader'));

$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';

call_user_func(\Composer\Autoload\ComposerStaticInit40d8adaf32b78561b9f4e4b36b0cc9a8::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}

$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}

$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}

$loader->register(true);

return $loader;
}
}
<?php



namespace Composer\Autoload;

class ComposerStaticInit40d8adaf32b78561b9f4e4b36b0cc9a8
{
public static $prefixLengthsPsr4 = array (
'D' => 
array (
'Defuse\\Crypto\\' => 14,
),
);

public static $prefixDirsPsr4 = array (
'Defuse\\Crypto\\' => 
array (
0 => __DIR__ . '/../..' . '/src',
),
);

public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit40d8adaf32b78561b9f4e4b36b0cc9a8::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit40d8adaf32b78561b9f4e4b36b0cc9a8::$prefixDirsPsr4;

}, null, ClassLoader::class);
}
}
<?php



$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
);
<?php



$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
'Defuse\\Crypto\\' => array($baseDir . '/src'),
);
<?php



$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
);
<?php































<?php

require_once 'lib/byte_safe_strings.php';
require_once 'lib/cast_to_int.php';
require_once 'lib/error_polyfill.php';
require_once 'other/ide_stubs/libsodium.php';
require_once 'lib/random.php';

$int = random_int(0, 65536);
<?php



require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInit40d8adaf32b78561b9f4e4b36b0cc9a8::getLoader();
cNtwX`~}   GBMB