I'm working with a CodeIgniter application to encrypt uploaded files then decrypt them when downloaded so they can be stored safely (alongside other security measures). This is all working fine, apart from docx (and other Microsoft Office 2007+) files. When these are downloaded they are successfully decrypted but Office detects them as corrupt. These can be repaired, so they're not totally corrupted, but something has changed in the file from the original version which is making Office see them as corrupt. As I mentioned, this doesn't seem to be happening to any other file types (that I have noticed). The docx files are also slightly different in size (only a matter of bytes), whereas other types are not.
To encrypt, I upload the file, read the contents into a string with file_get_contents(), then run the string through CodeIgniter's encode() in the encrypt library then save the file back to disk, deleting the original:
function mcrypt_encode($data, $key)
{
$init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());
$init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
return $this->_add_cipher_noise($init_vect.mcrypt_encrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), $key);
}
and to decode:
function mcrypt_decode($data, $key)
{
$data = $this-&开发者_高级运维gt;_remove_cipher_noise($data, $key);
$init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());
if ($init_size > strlen($data))
{
return FALSE;
}
$init_vect = substr($data, 0, $init_size);
$data = substr($data, $init_size);
return rtrim(mcrypt_decrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), "\0");
}
Then run the decoded string through CodeIgniter's force_download()
The default cipher is MCRYPT_RIJNDAEL_256 and mode is MCRYPT_MODE_CBC. Mcrypt is enabled on my server along with MCRYPT_RIJNDAEL_256.
If anyone could point me in the right direction as to why this might be happening it would be greatly appreciated.
Many thanks
This is a known bug with file_get_contents
and binary data. http://bugs.php.net/bug.php?id=42661
base64_encode()
the file_get_contents()
of file, then encrypt.
base64_decode()
the decrypted file_get_contents()
of encrypted file before downloading.
I was doing almost the same thing and got here from google.
I solved it now. The problem is not in the file_get_contents()
, the problem is the encode function in codeigniter. The function removes certain special characters thus removing data from the file. It's interesting how Microsoft office was able to repair it back.
精彩评论