Is mcrypt_encrypt() function not working in PHP 7.2? - php

I have encryption code as below & it was working in PHP version 5.6. But it is not working in PHP version 7.2.
**
Warning : Use of undefined constant MCRYPT_RIJNDAEL_128 - assumed
'MCRYPT_RIJNDAEL_128' (this will throw an Error in a future version of
PHP)
**
Any alternative of this?
$serviceid="2951";
$secretkey = "fQ5FHy0qzM6ljp97";
function pkcs5_pad ($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
function encrypt($plaintext, $key) {
$plaintext = pkcs5_pad($plaintext, 16);
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_ECB);
$ciphertext_base64 = base64_encode($ciphertext);
$ciphertext_base64;
}
$data = $serviceid;
$auth= encrypt($data ,$secretkey);
Value of encryption is AGchNk2xOnHHxhgYv02XJw==
I tried with below code in PHP 7.2
function encrypt($plaintext, $key)
{
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-128-cbc'));
$encrypted = openssl_encrypt($plaintext, 'aes-128-cbc', $key, 0, $iv);
return base64_encode($encrypted . '::' . $iv);
}
but output keeps changing

As you can see into documentation mcrypt_encrypt is REMOVED from PHP 7.2.0
Here an SO question for best alternative

I have found solution of my query. Please check below
function encrypt($plaintext,$key)
{
return base64_encode(openssl_encrypt($plaintext, 'aes-128-ecb', $key, OPENSSL_RAW_DATA));
}

Related

How to replace mcrypt with openssl?

I am currently upgrading an existing PHP application from PHP 5.4 to PHP 8.1. I have managed to restore all functionality except for encryption and decryption of data. My application communicates with a third party server, so just running an old PHP version to decrypt using mcrypt and reencrypt using openssl is not possible. I have seen a lot of similar threads, was however unable to find a solution to my issue.
This is the old set of functions (using mcrypt):
static function encrypt($key, $plain, $salt = null)
{
if (is_null($salt))
{
$salt = QuickBooks_Encryption::salt();
}
$plain = serialize(array( $plain, $salt ));
$crypt = mcrypt_module_open('rijndael-256', '', 'ofb', '');
if (false !== stripos(PHP_OS, 'win') and
version_compare(PHP_VERSION, '5.3.0') == -1)
{
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($crypt), MCRYPT_RAND);
}
else
{
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($crypt), MCRYPT_DEV_URANDOM);
}
$ks = mcrypt_enc_get_key_size($crypt);
$key = substr(md5($key), 0, $ks);
mcrypt_generic_init($crypt, $key, $iv);
$encrypted = base64_encode($iv . mcrypt_generic($crypt, $plain));
mcrypt_generic_deinit($crypt);
mcrypt_module_close($crypt);
return $encrypted;
}
static function decrypt($key, $encrypted)
{
$crypt = mcrypt_module_open('rijndael-256', '', 'ofb', '');
$iv_size = mcrypt_enc_get_iv_size($crypt);
$ks = mcrypt_enc_get_key_size($crypt);
$key = substr(md5($key), 0, $ks);
//print('before base64 [' . $encrypted . ']' . '<br />');
$encrypted = base64_decode($encrypted);
//print('given key was: ' . $key);
//print('iv size: ' . $iv_size);
//print('decrypting [' . $encrypted . ']' . '<br />');
mcrypt_generic_init($crypt, $key, substr($encrypted, 0, $iv_size));
$decrypted = trim(mdecrypt_generic($crypt, substr($encrypted, $iv_size)));
mcrypt_generic_deinit($crypt);
mcrypt_module_close($crypt);
//print('decrypted: [[**(' . $salt . ')');
//print_r($decrypted);
//print('**]]');
$tmp = unserialize($decrypted);
$decrypted = current($tmp);
return $decrypted;
}
And this is my best approximation using openssl:
static function new_encrypt($key, $plain, $salt = null)
{
if (is_null($salt))
{
$salt = QuickBooks_Encryption::salt();
}
$plain = serialize(array( $plain, $salt ));
$method = "AES-256-OFB";
$iv_len = openssl_cipher_iv_length($method);
$iv = openssl_random_pseudo_bytes($iv_len);
$key = substr(md5($key), 0, 32);
$encrypted = openssl_encrypt($plain, $method, $key, OPENSSL_RAW_DATA, $iv);
return base64_encode($iv . $encrypted);
}
static function new_decrypt($key, $encrypted)
{
$iv_size = openssl_cipher_iv_length('aes-256-ofb');
$key = substr(md5($key), 0, 32);
$encrypted = base64_decode($encrypted);
$iv = substr($encrypted, 0, $iv_size);
$encrypted = substr($encrypted, $iv_size);
$decrypted = openssl_decrypt($encrypted, 'aes-256-ofb', $key, OPENSSL_RAW_DATA, $iv);
$tmp = unserialize($decrypted);
$decrypted = current($tmp);
return $decrypted;
}
Both function sets can encrypt and decrypt data; however they are not compatible with each other.
What am I missing here?
First and foremost: Rijndael is not AES.
While AES is descended from/closely related to Rjindael, and may even have certain compatible implementations under very strict interpretations, more often than not they are not compatible at all. The implementations of Rijndael in mcrypt and AES OpenSSL are not compatible. [note: not a cryptographer, some amount of this paragraph might be BS aside from the words 'not compatible']
That said, you can use a library like phpseclib/mcrypt_compat to shim Rijndael and other functionality back into PHP8 and above.
However, since this library code will be running in userspace rather than a compiled extension the performance will likely be noticeably worse. My suggestion would be to use mcrypt_compat to migrate older encryption versions to something OpenSSL-compatible, or at least more current and broadly used/implemented, like AES.

openssl_cipher_iv_length error on php 7.4

how to fix openssl_cipher_iv_length error on php 7.4 its working normally on php 7.2?
$key = pack('H*','5e4888f3b85db60b53303483581c2b42112788e5e1b2d18c45cf70b867ca0721');
$method = 'aes-256-ecb';
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($method));
$encrypted = openssl_encrypt($data, $method, $key, OPENSSL_RAW_DATA, $iv);
$encrypted = strtoupper(implode(null, unpack('H*', $encrypted)));
return $encrypted;
in PHP 7.4 i get this error Fatal error: Uncaught Error: Length must be greater than 0
In Php 7.2 Everything is work
We need add a condition in order to find out if $ivSize is greater than zero. If $ivSize will be return zero $iv will stay empty.
Here is fixed code for PHP 7.4 and newer.
$key = pack('H*','5e4888f3b85db60b53303483581c2b42112788e5e1b2d18c45cf70b867ca0721');
$method = 'aes-256-ecb';
$ivSize = openssl_cipher_iv_length($method);
$iv = '';
if ($ivSize > 0) {
$iv = openssl_random_pseudo_bytes($ivSize);
}
$encrypted = openssl_encrypt($data, $method, $key, OPENSSL_RAW_DATA, $iv);
$encrypted = strtoupper(implode(null, unpack('H*', $encrypted)));
return $encrypted;

PHP7: mcrypt_cbc not work

please help to solve the problem.
how to make it work for on php 7 ?
function decr($string) {
$key="";
$iv = mcrypt_create_iv(mcrypt_get_block_size (MCRYPT_CAST_32, MCRYPT_MODE_CFB), MCRYPT_DEV_RANDOM);
$string = base64_decode(trim($string));
$dec = mcrypt_cbc (MCRYPT_TripleDES, $key, $string, MCRYPT_DECRYPT, $iv);
return $dec;
}
I had recently this problem in an app, i did not use mcrypt_encrypt() as suggested because of :
Warning
This function has been DEPRECATED as of PHP 7.1.0. Relying on this function is highly discouraged.
I did it using openssl (php-openssl) this way :
function _encrypt($data){
$initialVector = openssl_random_pseudo_bytes(16, $secure);
$secretKey = '<SECRET_KEY>'; // string : 16 length
return openssl_encrypt($data, "aes-128-cbc", $secretKey, OPENSSL_RAW_DATA, $initialVector);
}
function _decrypt($data){
$initialVector = openssl_random_pseudo_bytes(16, $secure);
$secretKey = '<SECRET_KEY>'; // string : 16 length
return openssl_decrypt($data, "aes-128-cbc", $secretKey, OPENSSL_RAW_DATA, $initialVector);
}
Note : initial vector/secret key generated this way is just for example

Replacing mcrypt_encrypt using MCRYPT_RIJNDAEL_256 with openssl_encrypt

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;
}

PHP code to encrypt using 3DES algorithm using CBC mode and a secretkey and IV spec key

i am try to encrypt following data using the 3des(CBC) using a secretkey and IV spec key in php but i am not getting the same output which i get on this online tool (http://symmetric-ciphers.online-domain-tools.com/)
//input
$data = "Id=120278;timestamp=2009-02-05 08:28:39.195";
$key = "80127ECD5E40BB25DB14354A3795880DF2B459BB08E1EE6D";
$iv = "331BA9C5A7446C98";
//output from online tool. I should get the same result in my php code
$result = "1C80CBCE1713128176499C7A3DFB8779156B31B8DEF2F667A7100F1C3AEFABACB24283CFDF 5D312D A0074897138684BC";
following the PHP code i tried
$string = "Id=120278;timestamp=2009-02-05 08:28:39.195";
$iv = "331BA9C5A7446C98";
$passphrase = "80127ECD5E40BB25DB14354A3795880DF2B459BB08E1EE6D";
$encryptedString = encryptString($string, $passphrase, $iv);
function encryptString($unencryptedText, $passphrase, $iv) {
$enc = mcrypt_encrypt(MCRYPT_3DES, $passphrase, $unencryptedText, MCRYPT_MODE_CBC, $iv);
return base64_encode($enc);
}
Try this:
function encrypt3DES($key,$iv,$text_enc){
$block = mcrypt_get_block_size('tripledes', 'cbc');
$pad = $block - (strlen($text_enc) % $block);
$text_enc .= str_repeat(chr($pad), $pad);
$text_enc = mcrypt_encrypt(MCRYPT_3DES, $key, $text_enc, MCRYPT_MODE_CBC, $iv);
$text_enc = base64_encode ($text_enc);
return $text_enc;
}

Categories