PHP lacks a build-in function to encrypt and decrypt large files. openssl_encrypt can be used to encrypt strings, but loading a huge file into memory is a bad idea.
This example uses the symmetric AES-256-CBC algorithm to encrypt smaller chunks of a large file and writes them into another file. |
<?php define('FILE_ENCRYPTION_BLOCKS', 10000); /** * Encrypt the passed file and saves the result in a new file with ".enc" as suffix. * * @param string $source Path to file that should be encrypted * @param string $key The key used for the encryption * @param string $dest File name where the encryped file should be written to. * @return string|false Returns the file name that has been created or FALSE if an error occured */ function encryptFile($source, $key, $dest) { $key = substr(sha1($key, true), 0, 16); $iv = openssl_random_pseudo_bytes(16); $error = false; if ($fpOut = fopen($dest, 'w')) { // Put the initialzation vector to the beginning of the file fwrite($fpOut, $iv); if ($fpIn = fopen($source, 'rb')) { while (!feof($fpIn)) { $plaintext = fread($fpIn, 16 * FILE_ENCRYPTION_BLOCKS); $ciphertext = openssl_encrypt($plaintext, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv); // Use the first 16 bytes of the ciphertext as the next initialization vector $iv = substr($ciphertext, 0, 16); fwrite($fpOut, $ciphertext); } fclose($fpIn); } else { $error = true; } fclose($fpOut); } else { $error = true; } return $error ? null : $dest; } /** * Dencrypt the passed file and saves the result in a new file, removing the * last 4 characters from file name. * * @param string $source Path to file that should be decrypted * @param string $key The key used for the decryption (must be the same as for encryption) * @param string $dest File name where the decryped file should be written to. * @return string|false Returns the file name that has been created or FALSE if an error occured */ function decryptFile($source, $key, $dest) { $key = substr(sha1($key, true), 0, 16); $error = false; if ($fpOut = fopen($dest, 'w')) { if ($fpIn = fopen($source, 'rb')) { // Get the initialzation vector from the beginning of the file $iv = fread($fpIn, 16); while (!feof($fpIn)) { $ciphertext = fread($fpIn, 16 * (FILE_ENCRYPTION_BLOCKS + 1)); // we have to read one block more for decrypting than for encrypting $plaintext = openssl_decrypt($ciphertext, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv); // Use the first 16 bytes of the ciphertext as the next initialization vector $iv = substr($ciphertext, 0, 16); fwrite($fpOut, $plaintext); } fclose($fpIn); } else { $error = true; } fclose($fpOut); } else { $error = true; } return $error ? null : $dest; } $key = 'my secret key'; $fileName = __DIR__ . '/testfile.txt'; file_put_contents($fileName, 'File would be encrypted...'); $result = encryptFile($fileName, $key, $fileName . '.enc'); if ($result) { echo "FILE ENCRYPTED TO " . $result; $result = decryptFile($result, $key, $fileName . '.dec'); if ($result) { echo "<BR>FILE DECRYPTED TO " . $result; } } ?> |
Showing posts with label AES-256-CBC. Show all posts
Showing posts with label AES-256-CBC. Show all posts
Sunday, February 16, 2020
PHP - Encryption and Decryption of Large Files with OpenSSL
Subscribe to:
Posts (Atom)