I am trying to come up with a way to have PHP encrypt a file. I used to just use a PHP system call to run a script that encoded the file:
#!/bin/sh
/usr/bin/openssl aes-256-cbc -a -salt -k $1 -in $2
Argument 1 was the password to use and argument 2 is the data. I then use a second script on a computer to de-crypt the file.
#!/bin/sh
/usr/bin/openssl aes-256-cbc -a -d -salt -k $1 -in $2
This method of encrypting will not work on a production host as the PHP system call is disabled. I also would prefer not the change the decode function if at all possible.
Is there a way to replicate the above encrypt function using only PHP?
Take a look at mcyrpt_encrypt():
string mcrypt_encrypt ( string $cipher , string $key , string $data ,
string $mode [, string $iv ] )
Set $cipher to MCRYPT_RIJNDAEL_128 (AES-128), and $mode to MCRYPT_MODE_CBC.
Then use base64_encode() to generate a base-64 encoded output (ie: what the -a option
does).
openssl derives the key and IV as follows:
Key = MD5(Password + Salt)
IV = MD5(Key + Password + Salt)
Where Salt is a 8 byte salt. With this in mind, I created simple encrypt() and decrypt() routines:
function ssl_encrypt($pass, $data) {
$salt = substr(md5(mt_rand(), true), 8);
$key = md5($pass . $salt, true);
$iv = md5($key . $pass . $salt, true);
$ct = mcrypt_encrypt (MCRYPT_RIJNDAEL_128, $key, $data,
MCRYPT_MODE_CBC, $iv);
return base64_encode('Salted__' . $salt . $ct);
}
function ssl_decrypt($pass, $data) {
$data = base64_decode($data);
$salt = substr($data, 8, 8);
$ct = substr($data, 16);
$key = md5($pass . $salt, true);
$iv = md5($key . $pass . $salt, true);
$pt = mcrypt_decrypt (MCRYPT_RIJNDAEL_128, $key, $ct,
MCRYPT_MODE_CBC, $iv);
return $pt;
}
The parameter $data takes the string to be encrypted. If you want to encrypt a file, you'll have to get it via file_get_contents() or similar and then give that to the function.
Usage:
echo ssl_encrypt('super secret key', 'Hello World');
Generates something like (will change every time because of the random salt):
U2FsdGVkX18uygnq8bZYi6f62FzaeAnyB90U6v+Pyrk=
As stated above in the comments padding is necessary to make this work. The function below will make a file that can be decrypted on the command line like this:
openssl enc -d -aes-256-cbc -a -salt -in test.txt
The test.txt file is created from the output of the ssl_encrypt function below.
function ssl_encrypt($pass, $data)
{
// Set a random salt
$salt = substr(md5(mt_rand(), true), 8);
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$pad = $block - (strlen($data) % $block);
$data = $data . str_repeat(chr($pad), $pad);
// Setup encryption parameters
$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);
$total_len = $key_len + $iv_len;
$salted = '';
$dx = '';
// Salt the key and iv
while (strlen($salted) < $total_len)
{
$dx = md5($dx.$pass.$salt, true);
$salted .= $dx;
}
$key = substr($salted,0,$key_len);
$iv = substr($salted,$key_len,$iv_len);
mcrypt_generic_init($td, $key, $iv);
$encrypted_data = mcrypt_generic($td, $data);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return chunk_split(base64_encode('Salted__' . $salt . $encrypted_data),32,"\r\n");
}
Example Usage:
$plainText = "Secret Message";
$password = "SecretPassword";
$test = ssl_encrypt($password, $plainText);
$file = fopen('test.txt', 'wb');
// Write the Base64 encrypted output to a file.
fwrite($file, $test);
fclose($file);
// Show the output on the screen
echo $test;
References: http://juan.boxfi.com/2010/03/16/write-openssl-files-in-php/
Perhaps PHP's OpenSSL library?
Related
I have a PHP page that loops through a CSV file and encrypts the 'email' column using the following function:
function my_encrypt($data, $key)
{
// Remove the base64 encoding from our key
$encryption_key = base64_decode($key);
// Generate an initialization vector
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
// Encrypt the data using AES 256 encryption in CBC mode using our encryption key and initialization vector.
$encrypted = openssl_encrypt($data, 'aes-256-cbc', $encryption_key, 0, $iv);
// The $iv is just as important as the key for decrypting, so save it with our encrypted data using a unique separator (::)
return base64_encode($encrypted . '::' . $iv);
}
In another part of the app, I decrypt the returned value using:
function my_decrypt($data, $key)
{
// Remove the base64 encoding from our key
$encryption_key = base64_decode($key);
// To decrypt, split the encrypted data from our IV - our unique separator used was "::"
list($encrypted_data, $iv) = explode('::', base64_decode($data), 2);
return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
}
This all works smoothly for the most part, but every now and then, the decrypted value comes back with a few weird characters in it.
For example: rsmi3�6CTΣ%mecompany.com was returned instead of rsmith#somecompany.com.
I'm not sure if it's the input or the output that is bad, but I'm guessing it has something to do with the uploaded CSV file... encoding issue? What do those characters mean and under what conditions are they produced?
UPDATE
Here's the code I'm using to add the encrypted value to the CSV:
$file = fopen(get_stylesheet_directory() . "/emma_members.csv", "r"); //Open the old file for reading
$newFile = fopen(get_stylesheet_directory() . "/emma_members_new.csv", "w"); //Create a new file for writing
if (!$file) error_log('ERROR opening file');
if (!$newFile) error_log('ERROR creating file');
$columns = ['email', 'member_id', 'member_since', 'plaintext_preferred', 'bounce_count', 'status_name', 'last_modified_at', 'city', 'first_name', 'last_name', 'request-demo', 'job-function', 'title', 'country', 'current-ams', 'opt-in', 'address-2', 'unique-identifier', 'state', 'postal_code', 'web-address', 'address', 'phone-number', 'company', 'area-of-specialization', 'work-phone'];
while (($data = fgetcsv($file)) !== FALSE) {
$row = array_combine($columns, $data);
$email = "{$row['email']}";
$uid = my_encrypt($email, ENCRYPT_KEY_1);
$row['unique-identifier'] = $uid;
$ret = fputcsv($newFile, array_values($row));
}
UPDATE 2
So after much testing with thousands of emails, it seems the my_encrypt function returns some bad values, depending on the input of course. It didn't happen with EVERY email address, but even 1 is too many for my use case.
I even tried getting rid of the :: between the data and the iv, but that didn't work either (although it's possible I did it wrong).
Anyway, I ended up using the following function in its place, and all is well:
function encrypt_decrypt($action, $string) {
$output = false;
$encrypt_method = "AES-256-CBC";
$secret_key = PHRASE_1;
$secret_iv = PHRASE_2;
// hash
$key = hash('sha256', $secret_key);
// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', $secret_iv), 0, 16);
if ( $action == 'encrypt' ) {
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
} else if( $action == 'decrypt' ) {
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
}
return $output;
}
I tested your encrypt and decrypt functions and they are working as expected, so the reason for the behaviour seems to be a different file encoding on your device.
Especially when reading a CSV-file sometimes a (windows) device changes the encoding and you get some curious characters like those you have shown. My recommendation is to read the files with another encoding as the default one (ISO...).
I setup a live example that "proves" the correctness on a simple string en- and decryption: https://paiza.io/projects/e/Y-1gy9Y3b-VAlXAMG4odng
The result is simple:
plaintext: rsmith#somecompany.com
ciphertext: Y0RrMWRwR1pWeGtGbFdic3dIVmFzVmp4VUFYemJGdUhzMStRSll6akIwWT06Orf+twLGopVa4083RckEw44=
decryptedtext: rsmith#somecompany.com
Here is the code:
<?php
function my_encrypt($data, $key)
{
// Remove the base64 encoding from our key
$encryption_key = base64_decode($key);
// Generate an initialization vector
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
// Encrypt the data using AES 256 encryption in CBC mode using our encryption key and initialization vector.
$encrypted = openssl_encrypt($data, 'aes-256-cbc', $encryption_key, 0, $iv);
// The $iv is just as important as the key for decrypting, so save it with our encrypted data using a unique separator (::)
return base64_encode($encrypted . '::' . $iv);
}
function my_decrypt($data, $key)
{
// Remove the base64 encoding from our key
$encryption_key = base64_decode($key);
// To decrypt, split the encrypted data from our IV - our unique separator used was "::"
list($encrypted_data, $iv) = explode('::', base64_decode($data), 2);
return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
}
$plaintext = 'rsmith#somecompany.com';
echo 'plaintext: ' . $plaintext . PHP_EOL;
$encryptionKey = base64_encode(32);
$ciphertext = my_encrypt($plaintext, $encryptionKey);
echo 'ciphertext: ' . $ciphertext . PHP_EOL;
$decryptedtext = my_decrypt($ciphertext, $encryptionKey);
echo 'decryptedtext: ' . $decryptedtext . PHP_EOL;
?>
I want to encrypt data in livecode using mergAESEncryptWithKey pData,pKey,pIV,[pMode],[pKeySize],[pPadding]. The encrypted data is then posted to php. PhP decrypts the data using the same function, does something with the data and then encrypts the results and posts them to livecode. Livecode then decrypts the data from php
My PHP Code looks like this (This works perfect)
function encrypt($plaintext, $salt) {
$method = "AES-256-CBC";
$key = hash('sha256', $salt, true);
$iv = openssl_random_pseudo_bytes(32);
$ciphertext = openssl_encrypt($plaintext, $method, $key, $iv);
$hash = hash_hmac('sha256', $ciphertext . $iv, $key, true);
return $iv . $hash . $ciphertext;
}
function decrypt($ivHashCiphertext, $salt) {
$method = "AES-256-CBC";
$iv = substr($ivHashCiphertext, 0, 32);
$hash = substr($ivHashCiphertext, 32, 48);
$ciphertext = substr($ivHashCiphertext, 64);
$key = hash('sha256', $salt, true);
//if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true), $hash)) return null;
return openssl_decrypt($ciphertext, $method, $key, $iv);
}
echo $encrypted."</br>";
echo "----------------------------The message is:<br/>";
echo decrypt($encrypted, 'hashsalt');
For most of you who just don't know but still want to post good for nothing comments, I figured it out. #Sammitch and #Mark asking a question don't mean someone is stupid.
/*
* Encrypt or decrypt data using
* AES-256-CBC
*/
function encrypt_decrypt($mode,$data,$key,$salt){
//define the cipher method
$ciphering = "AES-256-CBC";
// Use OpenSSl Encryption method. This works on PHP 7.2 and above
$iv_length = openssl_cipher_iv_length($ciphering);
$options = 0;
if($mode=="encrypt"){
// Use openssl_encrypt() function to encrypt the data
$Data = openssl_encrypt($data, $ciphering, $key, $options, $salt);
}else{
// Use openssl_decrypt() function to decrypt the data
$Data = openssl_decrypt($data, $ciphering, $key,$options, $salt);
}
return $Data;
}
Oooh and this is for livecode
//encrypt
encrypt tString using "aes-256-cbc" with key theKey and IV saltHash at 256 bit
//decrypt
decrypt base64Decode(varEnc) using "aes-256-cbc" with key theKey and IV saltHash at 256 bit
The command "openssl passwd -1" uses MD5 based BSD password algorithm 1 to compute a string hash.
Example:
openssl passwd -1
$1$./j/us.N$P2tq6IkO0Zu2d3uqkEHpv.
How do I implement exactly the same functionality in PHP? I'd like it to be a native PHP function, rather than something return by exec/shell_exec.
Example code
<?php
define('KEY', 'scret key');
function encrypt($value)
{
$iv = openssl_random_pseudo_bytes(16);
$encrypt = openssl_encrypt($value, 'AES-128-CBC', KEY, 0, $iv);
return base64_encode($encrypt . ':::' . $iv);
}
function decrypt($data)
{
$data = base64_decode($data);
list($data, $iv) = explode(':::', $data);
return openssl_decrypt($data, 'AES-128-CBC', KEY, 0, $iv);
}
$enc = encrypt('password');
echo decrypt($enc);
I know that a constant IV key is wrong and a random key must be generated. I, however need this as I have been assigned to do this. I have searched all over the net on how to deal with this but failed. My code is below, and any advice will be greatly apprecieted.
Here's the whole code together with the functions
define('ENCRYPTION_KEY', 'ITU2NjNhI0tOc2FmZExOTQ=='); //Encryption KEY
// Encrypt Function
function mc_encrypt($encrypt, $key)
{
//Do Not Put ENCRYPTION_KEY here
$encrypt = serialize($encrypt);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
//$iv = ('AAAAAAAAAAAAAAAAAAAAAA==');
$key = pack('H*', $key);
$mac = hash_hmac('sha256', $encrypt, substr(bin2hex($key), -32));
$passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $encrypt.$mac, MCRYPT_MODE_CBC, $iv);
$encoded = base64_encode($passcrypt).'|'.base64_encode($iv);
return $encoded; //return base64_encode($encoded).':'.$iv;
}
// Decrypt Function
function mc_decrypt($decrypt, $key)
{
$decrypt = explode('|', $decrypt);
$decoded = base64_decode($decrypt[0]);
$iv = base64_decode($decrypt[1]);
if(strlen($iv) !== mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC))
{
return false;
}
$key = pack('H*', $key);
$decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded, MCRYPT_MODE_CBC, $iv));
$mac = substr($decrypted, -64);
$decrypted = substr($decrypted, 0, -64);
$calcmac = hash_hmac('sha256', $decrypted, substr(bin2hex($key), -32));
if($calcmac !== $mac)
{
return false;
}
$decrypted = unserialize($decrypted);
return $decrypted;
}
echo '<h1>Sample Encryption</h1>';
$data = 'Patrick';
$encrypted_data = mc_encrypt($data, ENCRYPTION_KEY);
echo '<h2>Example #1: String Data</h2>';
echo 'Data to be Encrypted: ' . $data . '<br/>';
echo 'Encrypted Data: ' . $encrypted_data . '<br/>';
echo 'Decrypted Data: ' . mc_decrypt($encrypted_data, ENCRYPTION_KEY) . '</br>';
If i use that I get the error
Warning: pack(): Type H: illegal hex digit I in C:\xampp\htdocs\sample1\test.php on line 24
and when I use the
$iv = ('AAAAAAAAAAAAAAAAAAAAAA==');
Instead of this
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
while they have both
define('ENCRYPTION_KEY', 'd0a7e7997b6d5fcd55f4b5c32611b87cd923e88837b63bf2941ef819dc8ca282'); //Encryption KEY
this is the error
Warning: mcrypt_encrypt(): The IV parameter must be as long as the blocksize in C:\xampp\htdocs\sample1\test.php on line 26
This is working and tested code on PHP 5.3.18. Demonstration at Viper-7
1) It uses the required base64 encoded 'AAAAAAAAAAAAAAAAAAAAAA==', as the IV ('salt'), which when converted back to a string is 16 bytes of binary zeroes. As we need 32 bytes i just concatenate it with itself to make the required length.
2) There are two supplied keys:
1) base64 encoded: 'ITU2NjNhI0tOc2FmZExOTQ==', which is a 'typical' high quality password string that is 16 bytes long. This needs to converted to a hex string for the encryption functions.
2) The hexadecimal literal: 'd0a7e7997b'...
Please note: The supplied keys, as hex strings, are not equal to each other!
This does not affect the routines, just be aware that the same key must be used to encrypt / decrypt.
The routines:
// Encrypt Function - $key must be a Hexadecimal String
function mc_encrypt($encrypt, $key) {
//Do Not Put ENCRYPTION_KEY here
$encrypt = serialize($encrypt);
// $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
$iv = base64_decode(ENCRYPTION_IV); // convert back to binary string
$actualIV = $iv . $iv; // As it is 16 bytes of binary characters just double it
$key = pack('H*', $key); // convert key back to binary string
$mac = hash_hmac('sha256', $encrypt, substr(bin2hex($key), -32));
$passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $encrypt.$mac, MCRYPT_MODE_CBC, $actualIV);
$encoded = base64_encode($passcrypt).'|'.base64_encode($iv);
return $encoded;
}
Note that '$actualIV' is just a 'trick' to get the 32 bytes required. However, it will work if different 16 byte IV's are used.
Caveats: It is important that different (random) IV's are used when encrypting otherwise identical messages encrypt to the same ciphertext when the same key is used. To use 16 byte IV's in the routine i would be tempted to generate a random IV and just use the first 16 bytes of it concatenated to itself as is used currently.
i.e. replace this code:
$iv = base64_decode(ENCRYPTION_IV); // convert back to binary string
with:
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
$iv = substr($iv, 0, 16);
CBC mode and 'Padding Oracle Attacks'
It looks as though this is not an issue if you use PHP exclusively. There may be issues decrypting on different systems. This link explains the issues: Cryptography/DES-PHP-Block-Padding-in-mcrypt.html
// Decrypt Function - - $key must be a Hexadecimal String
function mc_decrypt($decrypt, $key) {
$decrypt = explode('|', $decrypt);
$decoded = base64_decode($decrypt[0]);
$iv = base64_decode($decrypt[1]);
$actualIV = $iv . $iv; // make it long enough and match the original IV used.
if(strlen($actualIV) !== mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC)){ return false; }
$key = pack('H*', $key);
$decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded, MCRYPT_MODE_CBC, $actualIV));
$mac = substr($decrypted, -64);
$decrypted = substr($decrypted, 0, -64);
$calcmac = hash_hmac('sha256', $decrypted, substr(bin2hex($key), -32));
if($calcmac!==$mac) { return false; }
$decrypted = unserialize($decrypted);
return $decrypted;
}
Note that '$iv' is concatenated with itself to get the 32 bytes required.
Defined keys:
define('ENCRYPTION_B64KEY', 'ITU2NjNhI0tOc2FmZExOTQ=='); //Encryption KEY
define('ENCRYPTION_IV', 'AAAAAAAAAAAAAAAAAAAAAA==');
define('ENCRYPTION_HEXKEY', 'd0a7e7997b6d5fcd55f4b5c32611b87cd923e88837b63bf2941ef819dc8ca282'); //Encryption KEY
Examples using both supplied keys:
echo '<h1>Sample Encryption</h1>';
$data = 'Patrick';
echo '<h2>Example #1: Using base64 encoded key (ENCRYPTION_B64KEY)</h2>';
$b64HexKey = bin2hex(base64_decode(ENCRYPTION_B64KEY));
$encrypted_data = mc_encrypt($data, $b64HexKey);
echo 'Data to be Encrypted: ' . $data . '<br/>';
echo 'Encrypted Data: ' . $encrypted_data . '<br/>';
echo 'Decrypted Data: ' . mc_decrypt($encrypted_data, $b64HexKey) . '</br>';
echo '<h2>Example #2 using Hexadecimal Key (ENCRYPTION_HEXKEY)</h2>';
$hexKey = ENCRYPTION_HEXKEY;
$encrypted_data = mc_encrypt($data, $hexKey);
echo 'Data to be Encrypted: ' . $data . '<br/>';
echo 'Encrypted Data: ' . $encrypted_data . '<br/>';
echo 'Decrypted Data: ' . mc_decrypt($encrypted_data, $hexKey) . '</br>';
Output from the above:
Sample Encryption
Example #1: Using base64 encoded key (ENCRYPTION_B64KEY)
Data to be Encrypted: Patrick
Encrypted Data: /7qKjoPnNiGveTHo0NnkXfSLFIHE72De1q85QWI/d16j4BzLaqIR7jpap0J2wCdHYgK+IS4Zf1OpZorK9iGnPErkh+owjkoEo/dejHxUaVxOS03+Uqti8i13aGeB6wAU|AAAAAAAAAAAAAAAAAAAAAA==
Decrypted Data: Patrick
Example #2 using Hexadecimal Key (ENCRYPTION_HEXKEY)
Data to be Encrypted: Patrick
Encrypted Data: iAyCpfnOHUeHKHT+BIra2TZbRlLJfXKAO5pRGbmKvLyTOlzr9L6IBRI8ZuDsGVdZym26Qd89hKZxnVPbBSsOktCaztF9akZA8iPa3r0jvgISFldRDdHx8CZyd+GfR9BV|AAAAAAAAAAAAAAAAAAAAAA==
Decrypted Data: Patrick
Trying to achieve encrypting and decryption using following strategy, but ending up with random characters mostly.
class Crypt {
public static function encrypt($string, $account) {
// create a random initialization vector to use with CBC encoding
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = pack('H*', $account . $account);
$output = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_CBC, $iv);
$output = $iv . $output;
$output = base64_encode($output);
$output = urlencode($output);
return $output;
}
public static function decrypt($token, $account) {
$ciphertext_dec = base64_decode($token);
// retrieves the IV, iv_size should be created using mcrypt_get_iv_size()
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv_dec = substr($ciphertext_dec, 0, $iv_size);
// retrieves the cipher text (everything except the $iv_size in the front)
$ciphertext_dec = substr($ciphertext_dec, $iv_size);
$key = pack('H*', $account . $account);
$token = urldecode($token);
$output = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);
$output = rtrim($output, "");
return $output;
}
}
Can't get exact values back, sometimes it decrypts but I see some garbage values, but mostly just random characters.
$a = \Crypt::encrypt("MyPassword", "1974246e");
echo \Crypt::decrypt($a, "1974246e");
Edits after the discussion
class Crypt {
public static function encrypt($data, $passphrase) {
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); //create a random initialization vector to use with CBC encoding
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = pack('H*', $passphrase . $passphrase);
return base64_encode($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv));
}
public static function decrypt($data, $passphrase) {
$data = base64_decode($data);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); //retrieves the IV, iv_size should be created using mcrypt_get_iv_size()
$iv = substr($data, 0, $iv_size);
$data = substr($data, $iv_size); //retrieves the cipher text (everything except the $iv_size in the front)
$key = pack('H*', $passphrase . $passphrase);
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv), chr(0));
}
}
Usage:
$pass = "MyPassword*&^*&^(*&^(";
$token = \Crypt::encrypt($pass, "1974246e8e8a479bb0233495e8a3ed12");
$answer = \Crypt::decrypt($token, "1974246e8e8a479bb0233495e8a3ed12");
echo $answer == $pass ? "yes" : "no";
Don't urlencode. Unnecessary.
trim for NULL bytes, not empty strings: rtrim($str, chr(0)); (Instead, you might want to save the source string length in the encrypted result too, so you won't rtrim() too much.)
Why pack('H*', $account) for $key? Also unnecessary.
Rijndael 128 uses 16 byte keys (128 bits), so make sure your key is at least that long:
$key = $account . $account
will do, but it obviously imperfect. (mcrypt will do something like that if it's too short.) If every account had its own passphrase, that would be good. (Even more so in combination with an app secret, but details.)
rtrim() with chr(0) is fine, very probably, because your source string won't have trailing NUL bytes.
I usually use these en/decrypt functions, or alike, but these have a static secret/key, so yours is better.
To send an encrypted token to the client:
$enc_token = Crypt::encrypt($token, $key);
// $enc_token might contain `/` and `+` and `=`
$url = 'page.php?token=' . urlencode($enc_token);