Defuse\Crypto\File::encryptResourceInternal PHP Method

encryptResourceInternal() private static method

Encrypts a resource with either a key or a password.
private static encryptResourceInternal ( resource $inputHandle, resource $outputHandle, KeyOrPassword $secret )
$inputHandle resource
$outputHandle resource
$secret KeyOrPassword
    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);
        /* Initialize a streaming HMAC state. */
        $hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
        if ($hmac === false) {
            throw new Ex\EnvironmentIsBrokenException('Cannot initialize a hash context');
        }
        /* Write the header, salt, and IV. */
        self::writeBytes($outputHandle, Core::CURRENT_VERSION . $file_salt . $iv, Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + $ivsize);
        /* Add the header, salt, and IV to the HMAC. */
        \hash_update($hmac, Core::CURRENT_VERSION);
        \hash_update($hmac, $file_salt);
        \hash_update($hmac, $iv);
        /* $thisIv will be incremented after each call to the encryption. */
        $thisIv = $iv;
        /* How many blocks do we encrypt at a time? We increment by this value. */
        $inc = Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE;
        /* Loop until we reach the end of the input file. */
        $at_file_end = false;
        while (!(\feof($inputHandle) || $at_file_end)) {
            /* Find out if we can read a full buffer, or only a partial one. */
            $pos = \ftell($inputHandle);
            if ($pos === false) {
                throw new Ex\IOException('Could not get current position in input file during encryption');
            }
            if ($pos + Core::BUFFER_BYTE_SIZE >= $inputSize) {
                /* We're at the end of the file, so we need to break out of the loop. */
                $at_file_end = true;
                $read = self::readBytes($inputHandle, $inputSize - $pos);
            } else {
                $read = self::readBytes($inputHandle, Core::BUFFER_BYTE_SIZE);
            }
            /* Encrypt this buffer. */
            $encrypted = \openssl_encrypt($read, Core::CIPHER_METHOD, $ekey, OPENSSL_RAW_DATA, $thisIv);
            if ($encrypted === false) {
                throw new Ex\EnvironmentIsBrokenException('OpenSSL encryption error');
            }
            /* Write this buffer's ciphertext. */
            self::writeBytes($outputHandle, $encrypted, Core::ourStrlen($encrypted));
            /* Add this buffer's ciphertext to the HMAC. */
            \hash_update($hmac, $encrypted);
            /* Increment the counter by the number of blocks in a buffer. */
            $thisIv = Core::incrementCounter($thisIv, $inc);
            /* WARNING: Usually, unless the file is a multiple of the buffer
             * size, $thisIv will contain an incorrect value here on the last
             * iteration of this loop. */
        }
        /* Get the HMAC and append it to the ciphertext. */
        $final_mac = \hash_final($hmac, true);
        self::writeBytes($outputHandle, $final_mac, Core::MAC_BYTE_SIZE);
    }