I want to decrypt an encrypted response using mcrypt_decrypt but this doesn't work, so I'm using this snippet of code for test and the response should be "This is a test":
// Encryption Algorithm
// the $shared_key and $init_vector are not real
$cipher_alg = MCRYPT_RIJNDAEL_128;
$shared_key = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
$key = pack("H*", $shared_key);
$init_vector = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
$iv = pack("H*", $init_vector);
echo mcrypt_decrypt($cipher_alg, $key, utf8_encode(mcrypt_encrypt(
$cipher_alg, $key, utf8_encode('This is a test'), MCRYPT_MODE_CBC, $iv)), MCRYPT_MODE_CBC, $iv);
And the response is:
æ †,?7÷q†Ý³‚¢gTô1ò‚ù’Ü”®mÀ{ëQS
What I'm doing wrong?
You are utf8 encoding the encrypted stuff. That way it is modified and can not be decrypted anymore.
echo mcrypt_decrypt($cipher_alg, $key, mcrypt_encrypt(
$cipher_alg, $key, 'This is a test'), MCRYPT_MODE_CBC, $iv), MCRYPT_MODE_CBC, $iv);
Related
I used following codes to encrypt and decrypt the strings in php. I recently upgraded my server and now i can see that the codes i use is depreciated. Encryption code is hardcoded on my app so i need to decrypt on the server. Please provide the alternative to both encrypt and decrypt
Code for encryption.
function encrypt($data = '', $key = 'chiperbase65enus')
{
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, 'chiperbase65enus');
return base64_encode($encrypted);
}
And for decryption is below. I dont actually need encryption anymore but decryption is the must.
function decrypt($data = '', $key = 'chiperbase65enus')
{
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($data), MCRYPT_MODE_CBC,'chiperbase65enus');
return rtrim($decrypted, "\0");
}
$decrypted = openssl_decrypt(base64_decode($encrypted_string), "AES-128-CBC", "chiperbase65enus",OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, "chiperbase65enus");
I found the solution...
I'm having problem with decrypting
I have
$key="Gwu078980";
$cipher="aes-128-gcm";
$iv=md5($cipher);
$text="yaw0";
$tag="";
echo $encrypted=openssl_encrypt($text, $cipher, $key, 0, $iv, $tag);
echo $de_ciphertext=openssl_decrypt($encrypted, $cipher, $key, 0, $iv, $tag);
Output
ELRmWQ==
yaw0
So the raw text is yaw0 and the encrypted is ELRmWQ== and the decrypted is yaw0 so perfect.
But when I manually copy the encrypted text and use it as
$encrypted ="ELRmWQ==";
And I run the decryption
the decryption returns null.
Thanks in advance for anyone to help me out.
Your openssl_encrypt message modifies $tag by reference since you're using aes-128-gcm.
That parameter is required for openssl_decrypt aswell (when using AEAD - Authenticated Encryption and Decryption) and is probably an empty string in your case when you omit the openssl_encrypt call.
See Example 1 in the docs:
The comment about storing $cipher, $iv, and $tag is the important part:
<?php
//$key should have been previously generated in a cryptographically safe way, like openssl_random_pseudo_bytes
$plaintext = "message to be encrypted";
$cipher = "aes-128-gcm";
if (in_array($cipher, openssl_get_cipher_methods()))
{
$ivlen = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options=0, $iv, $tag);
//store $cipher, $iv, and $tag for decryption later
$original_plaintext = openssl_decrypt($ciphertext, $cipher, $key, $options=0, $iv, $tag);
echo $original_plaintext."\n";
}
?>
As you guys probably know, the extension mcrypt will be deprecated on php 7.1.
I use to maintain a "legacy" application that I want to migrate eventually to this version so I ran the tests and verified that I can't get 100% of coverage anymore, since there's a piece of code that use the following code:
$key = 'sA*(DH';
// initialization vector
$iv = md5(md5($key));
$output = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, $iv));
I tried to port this piece of code to openssl_encrypt using this code
$key = md5('sA*(DH');
$iv = md5($key);
echo base64_encode(openssl_encrypt($data, "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv));
But I have 2 problems with this:
The IV lenght should be 16 chars (and md5 gives me 32), so I get a PHP Warning
The output it's not the same (even if I truncate to 16 chars)
Anyone had similar problems (or know how to fix it?)
BTW: I'm using the dev master version of PHP (supposed to be 7.1.0 alpha 3).
Yet another tested solution taking and returning ANSI text to replace Mcrypt function with the openssl_encrypt() and openssl_decrypt():
//Return encrypted string
public function stringEncrypt ($plainText, $cryptKey = '7R7zX2Urc7qvjhkr') {
$cipher = 'aes-128-cbc';
if (in_array($cipher, openssl_get_cipher_methods()))
{
$ivlen = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt(
$plainText, $cipher, $cryptKey, $options=OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, $cryptKey, $as_binary=true);
$encodedText = base64_encode( $iv.$hmac.$ciphertext_raw );
}
return $encodedText;
}
//Return decrypted string
public function stringDecrypt ($encodedText, $cryptKey = '7R7zX2Urc7qvjhkr') {
$c = base64_decode($encodedText);
$cipher = 'aes-128-cbc';
if (in_array($cipher, openssl_get_cipher_methods()))
{
$ivlen = openssl_cipher_iv_length($cipher);
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$ivlenSha2len = $ivlen+$sha2len;
$ciphertext_raw = substr($c, $ivlen+$sha2len);
$plainText = openssl_decrypt(
$ciphertext_raw, $cipher, $cryptKey, $options=OPENSSL_RAW_DATA, $iv);
}
return $plainText;
}
More read in openssl documentation
You should really get out of the habit of using md5 for anything.
$iv = openssl_random_pseudo_bytes(16);
$key = substr(hash('sha256', 'sA*(DH'), 0, 32)
mcrypt_encrypt and openssl_encrypt will not output the same crypttext given the same plaintext and key.
also, mcrypt is deprecated in PHP 7.1, not removed...so you can update to 7.1 without changing from mcrypt to openssl ... but it is a good idea to remove mcrypt in general.
There are 2 problems :
MCrypt uses zero padding while Openssl uses by default PKCS#7
Openssl needs the input string to be of proper length (multiple of block length)
To solve this problems :
add OPENSSL_ZERO_PADDING flag to openssl_encrypt/openssl_decrypt
if input string length is not multiple of block length then append to the input string zero chars "\0" [aka chr(0)];
That being said this should solve the problem:
// key/iv in ASCII binary data, $str base64
function decrypt_stuff($key, $str, $iv) {
// $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($str), MCRYPT_MODE_CBC, $iv);
$plaintext_dec = openssl_decrypt(base64_decode($str), "aes-256-cbc", $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
return $plaintext_dec;
}
// key/iv in ascii binary data, $str ascii
function encrypt_stuff($key, $str, $iv) {
// $ciphertext = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_CBC, $iv));
if (($l = (strlen($str) & 15)) > 0) { $str .= str_repeat(chr(0), 16 - $l); }
$ciphertext = base64_encode(openssl_encrypt($str, "aes-256-cbc", $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv));
return $ciphertext;
}
I'm trying to encrypt and decrypt a token with the AES 128 bit CBC encryption in PHP.
If I try to encrypt and decrypt a token, the result is not the original token.
Here is my code:
$decrKey = "123456789abcdefg";
$decrIV = "xyz123456789abcd";
function encryptAES($data,$key,$iv)
{
$decr= mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, base64_encode($data), MCRYPT_MODE_CBC, $iv);
return $decr;
}
function decryptAES($data,$key,$iv)
{
$decr= mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($data), MCRYPT_MODE_CBC, $iv);
return $decr;
}
$token = "abcdefghijk";
echo $token;
$tokenEncrypt = encryptAES($token,$decrKey,$decrIV);
echo "encrypt: ".$tokenEncrypt ;
$tokenDecrypt = decryptAES($tokenEncrypt,$decrKey,$decrIV);
echo "decrypt: ".$tokenDecrypt ;
What do i miss?
You should base 64 encode the result of the encryption method (called the ciphertext), and decode it again before decryption. You are currently base 64 encoding the plain text in the encryption function instead of the ciphertext. Encoding the plain text is not necessary. It would be however a good idea to use a well defined character-encoding for the plain text.
$encr = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv));
return $encr
I am encrypting and decrypting a string using:
$key = 'my key';
$data = 'my string';
$ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM);
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv);
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CBC, $iv);
$data = trim($decrypted, chr(0));
http://codepad.viper-7.com/1JgCRs
Is it safe to just trim off the padding added by the encryption algorithm, or is it necessary to store the length of the data before encrypting?
You are trimming the value after you decrypt so you won't run into ay issues with the current code.
If you try to re-encrypt the different, trimmed data, you will get a different encrypted value.
Padding is added on the right normally, so consider rtrim():
$data = rtrim($decrypted, chr(0));
However this is still not yet perfectly safe because in PHP strings can contain NUL-bytes. If for some reason the plain did had NUL-bytes at the end, the rtrim will remove the padding and those previous NUL-bytes.