Thoughts of just about anything
Read OpenSSL files in PHP
I finally got PHP to open encrypted files created with OpenSSL. I use openssl in the command line to encrypt files with AES cipher 128 block size and 256 key length with salt. For example to encrypt myfile.txt I would use something like this:
openssl enc -e -aes-256-cbc -salt -in myfile.txt -out myfile.txt.crypt
If on the other hand you want to decrypt the file you would use something like this
openssl enc -d -aes-256-cbc -salt -in myfile.txt.crypt -out myfile.txt
I thought about using encrypted files on a web server since I currently share the space with other people. This way I can keep some files confidential. One way was to call openssl through a shell command but it turns out that it is not installed on the webserver.
So I checked the PHP manual and it does have support for encryption/decryption (that is if you compiled with mcrypt module). So that’s what I was set on using. The problem arose when I read the documentation and saw that there was no function to open a file created with openssl directly. Further more the decryption looked kinda complicated since all I had was a password for the file and the functions need a KEY and IV.
But I finally figured it out. So here it is:
First to get the KEY and IV from them file you need the original password and the salt used. The password is of course kept secret but the salt is stored in the file created by openssl. We take the password append it to the salt hash it a couple times with MD5 and we get the KEY and IV. Once we have the KEY and IV we can use the PHP functions to decrypt the file.So here’s the details:First load the encrypted file contents to a string:
$stream = file_get_contents($filename);
Then get the salt.
$salt = substr($stream, 8, 8);
The salt is eight characters long and stored after the constant “Salted__” in the file stream. Thus we look at location eight and save off eight characters.Next we get rid of the salt in the stream since it is not part of the encrypted file.
$stream = substr($stream, 16)
Then we create the cipher resource used to decrypt the file, and we also get the size of the key and the size of the IV (we could hard-code constants but we want to be explicit). Note that AES cipher is the same as RIJNDAEL. You might also be asking why we used -aes-256-cbc but we are using MCRYPT_RIJNDAEL_128 here (well I did ask my self). Turns out 256 is the key size, while 128 is the block size so this combination works.
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); $key_len = mcrypt_enc_get_key_size($td); $iv_len = mcrypt_enc_get_iv_size($td);
then we generate the key and IV with the password and salt.
list($key, $iv) = salted_key_and_iv($key_len, $iv_len, $password, $salt);
salted_key_and_iv is a simple function that does the password and salt hashing and it looks like this:
function salted_key_and_iv($key_len, $iv_len, $pass, $salt) {
$desired_len = $key_len + $iv_len;
$data = "";
$dx = "";
while ( strlen($data) < $desired_len ) {
$dx = md5($dx . $pass . $salt, true);
$data .= $dx;
}
return array(substr($data,0,$key_len), substr($data,$key_len,$iv_len));
}
Lastly we init the cipher, decrypt the data, denit the cypher and close it.
mcrypt_generic_init($td, $key, $iv); $plaintext = mdecrypt_generic($td, $stream); mcrypt_generic_deinit($td); mcrypt_module_close($td);
And that’s it $plaintext has the decrypted data. Simple enough, but it took me a while to figure out how to do this. Hope it helps someone.
Update: If you are looking for a way to write files check this other post: Write OpenSSL Files in PHP
| Print article | This entry was posted by Juan Frias on April 18, 2007 at 11:10 pm, and is filed under PHP. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |
about 6 months ago
Hi,
I tried procedure explained here. Unfortunately, It doesn’t work. I get binary garbage. Do you have any idea why?
Thank you
Predrag Manojlovic
about 6 months ago
Please forgive me,
I finally found bug in my procedure.
Your instructions are great.
Thank you
about 5 months ago
Works perfect !! But … i need the other way around.. So create a encrypted file with php and decrypt with openssl. Can you please give me an example of this ?
I would appreciate it very much