Optimize file reading - mcrypt

I wrote a couple functions to encrypt and decrypt data passed to it, as follows:


function aes_crypt($plaintext, $key) {
	$td = mcrypt_module_open('rijndael-256', '', 'ofb', '');
	$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);
	mcrypt_generic_init($td, $key, $iv);
	
	$ciphertext = mcrypt_generic($td, $plaintext);
	mcrypt_generic_deinit($td);
	mcrypt_module_close($td);
	
	return $ciphertext;
}

function aes_decrypt($ciphertext, $key) {
	$td = mcrypt_module_open('rijndael-256', '', 'ofb', '');
	$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);
	mcrypt_generic_init($td, $key, $iv);
	
	$plaintext = mdecrypt_generic($td, $ciphertext);
	mcrypt_generic_deinit($td);
	mcrypt_module_close($td);
	
	return $plaintext;
}

$data = file_get_contents($file1);
file_put_contents($file2, aes_crypt($data, $key));

Is there a way to optimize this so that I don’t have to read an entire file into memory ($data = file_get_contents(‘/foo/bar’):wink: at one time? As far as I know, the cipher allows for operation with a minimal amount of memory usage, and I need this to be able to handle files >100MiB.

Thanks!

You could use fgets() or fiileread() to put the contents into sized strings instead of 1 big one.

I don’t think that produces the same result. Say I have a 1KiB file and the cipher’s block length is 256 bits. That means a 1024 B file should be split into 32 blocks of 32 B each. Correct me if I’m wrong, but any block cipher mode other than ECB would treat 32 blocks of 32 bytes differently than one block of 1024 B.

I would think mcrypt would be flexible enough to deal with the data in a way to avoid reading huge amounts of data in.

Maybe you could compress the original file with gzip and then encrypt that?

Hmmm, I’ve since found out that using the block cipher modes CFB or OFB is much slower than CBC. (Note that ECB is far less secure and should not be used.)

According to my benchmarks, using AES-256 with a 14.9MiB file…

Encrypt with CBC: 1.9 seconds
Encrypt with CFB/OFB: 45 seconds
Just read and write the file: 0.2 seconds

If I can deal with a 15 meg file in about 2 seconds, then efficiency is a non-issue for about any file.

Thanks for the info. I would never have guessed that there would be that much of a difference. Something for me toi remember if I ever need to encrypt larger files.

Also, I read the wikipedia article, and though it doesn’t mention it directly, I was able to determine that while CFB and OFB are a little more secure than CBC, they are in no way 20+ times more secure. AES/Rijndael-256 is secure enough atm. :wink: