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; } } ?> |
Sunday, February 16, 2020
PHP - Encryption and Decryption of Large Files with OpenSSL
Subscribe to:
Post Comments (Atom)
I really thank you for the valuable info on this great subject and look forward to more great posts. Thanks a lot for enjoying this beauty article with me. I am appreciating it very much! Looking forward to another great article. Good luck to the author! All the best!
ReplyDeletePhp projects with source code
Online examination system in php
Student management system in php
Php projects for students
Free source code for academic
Academic projects provider in nashik
Academic project free download
ReplyDeleteNice Blog , This is what I exactly Looking for , Keep sharing more blog .
Offshore Yii Framework Development in India
Hi, would you expect the encryption file using your method above to be exactly the same as loading the entire data in one go into openssl_encrypt with the same options, key, iv etc? (the only difference obviously being the memory when using a large file)
ReplyDelete