PHP7: mcrypt_cbc not work - php

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

Related

Is mcrypt_encrypt() function not working in PHP 7.2?

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

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

Using defined security variables inside a function

I found out that I should not use global variables like global $auth_key for sensitive data's (Correct me if that's not true.) so I wanted to use defined variables for storing security keys.
Inside config.php salt keys are defined.
define('AUTH_KEY','::~K~UC*[tlu4Eq/]Lm|h');
define('SECURE_AUTH_KEY', 'QsTMvbV+tuU{K26!]J2');
In encryption.php contains the encryption functions where AUTH_KEY and SECURE_AUTH_KEY will be used inside.
function encrypt_text($value) {
if(!$value) return false;
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, **AUTH_KEY_HERE**, $value, MCRYPT_MODE_ECB, **SECURE_AUTH_KEY_HERE**);
return trim(base64_encode($crypttext));
}
function decrypt_text($value) {
if(!$value) return false;
$crypttext = base64_decode($value);
$decrypttext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, **AUTH_KEY_HERE**, $crypttext, MCRYPT_MODE_ECB, **SECURE_AUTH_KEY_HERE**);
return trim($decrypttext);
}
Is there a way to do that? or any other solutions you can recommend? Please note that these keys are real important for encryption of sensitive informations.
Also, a another question, what is the maximum length of keys to be used on mcrypt?
Thank you and looking forward for reply of yours.
as a rule: the logner the key, the stonger the encryption. Secondly, don't use ECB unless your data is very short, you ought to use CBC or something stronger. Third: use a salt or initialization vector. Lastly read this: https://www.owasp.org/index.php/Cryptographic_Storage_Cheat_Sheet
Using a constant is just like using a variable except there is no dollar sign.
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, AUTH_KEY, $value, MCRYPT_MODE_ECB, SECURE_AUTH);
There is nothing inherently more secure in this approach over using the global key word. Though this approach is preferred. By using a constant you are saying this is a static value I will use across the application. Having to use global on the other hand is often just a result of bad design or laziness. It leads to code that is hard to follow, abusing what scoping tries to accomplish.
Key length is dependent on the encryption algorithm used. RTM.
Yes you can use the define variable like you are doing, see the example
define('AUTH_KEY','::~K~UC*[tlu4Eq/]Lm|h');
function abc()
{
echo AUTH_KEY;
}
abc(); // ::~K~UC*[tlu4Eq/]Lm|h
http://codepad.viper-7.com/tUAg6D
Although choosing constants would be preferable over plain variables, this kind of information is better stored inside a configuration file rather than your code.
Also, for better reuse and avoid having those global values lying around it would be a better idea to encapsulate the functionality:
class MyCrypto
{
private $key;
private $cipher;
private $mode;
public function __construct($key, $cipher, $mode = "cbc")
{
$this->key = $key;
$this->cipher = $cipher;
$this->mode = $mode;
}
public function generate_salt()
{
return mcrypt_create_iv(
mcrypt_get_iv_size($this->cipher, $this->mode),
MCRYPT_DEV_URANDOM
);
}
public function encrypt($data) { ... }
public function decrypt($data) { ... }
}
I've added a salt generator function to be used for every encryption operation;
Lastly, I would recommend using CBC mode - MCRYPT_MODE_CBC.
Update (27/09/17):
Since mcrypt_encrypt is DEPRECATED as of PHP 7.1.0. Ive added a simple encrypt/decrypt using openssl.
function encrypt($string, $key = 'PrivateKey', $secret = 'SecretKey', $method = 'AES-256-CBC') {
// hash
$key = hash('sha256', $key);
// create iv - encrypt method AES-256-CBC expects 16 bytes
$iv = substr(hash('sha256', $secret), 0, 16);
// encrypt
$output = openssl_encrypt($string, $method, $key, 0, $iv);
// encode
return base64_encode($output);
}
function decrypt($string, $key = 'PrivateKey', $secret = 'SecretKey', $method = 'AES-256-CBC') {
// hash
$key = hash('sha256', $key);
// create iv - encrypt method AES-256-CBC expects 16 bytes
$iv = substr(hash('sha256', $secret), 0, 16);
// decode
$string = base64_decode($string);
// decrypt
return openssl_decrypt($string, $method, $key, 0, $iv);
}
$str = 'Encrypt this text';
echo "Plain: " .$str. "\n";
// encrypt
$encrypted_str = encrypt($str);
echo "Encrypted: " .$encrypted_str. "\n";
// decrypt
$decrypted_str = decrypt($encrypted_str);
echo "Decrypted: " .$decrypted_str. "\n";
In your example, you are using the same initialization vector **SECURE_AUTH_KEY_HERE** when you can allow PHP to create the iv for you this way you only need 1 SECURE_KEY defined.
<?php
define('SECURE_KEY',md5('your secret key'));
/**
* Encrypt a value
*/
function encrypt($str){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
return mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SECURE_KEY, $str, MCRYPT_MODE_ECB, $iv);
}
/**
* Decrypt a value
*/
function decrypt($str){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, SECURE_KEY, $str, MCRYPT_MODE_ECB, $iv));
}
//32
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
//Create an initialization vector (IV) from a random source
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
echo decrypt(encrypt('Encrypt me'));
?>

proper PHP mcrypt encryption methods?

Ok, I have tried to create my own encryption/decryption methods using PHP mcrypt, and when I posted them a while back some called them "trash". They were mentioning things about "Initialization Vectors" and such. Basically, how can I make these cryptography methods better:
function encrypt($key, $data){
$encrypted_data = mcrypt_cbc(MCRYPT_RIJNDAEL_192, $key, $data, MCRYPT_ENCRYPT);
return base64_encode($encrypted_data);
}
function decrypt($key, $encryptedData){
$dec = base64_decode($encryptedData);
$decrypt = mcrypt_cbc(MCRYPT_RIJNDAEL_192, $key, $dec, MCRYPT_DECRYPT);
return trim($decrypt);
}
I want these to work the best they can except I am a duck in a brand new world when it comes to mcrypt, any suggestions are welcome, thanks!
Here is a snippet of the mcrypt functions I use. They use mcrypt_generic and mdecrypt_generic, which should be used according to the PHP manual.
function encrypt($key, $data){
$b = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$enc = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($enc), MCRYPT_DEV_URANDOM);
mcrypt_generic_init($enc, md5($key), $iv);
// PKCS7 Padding from: https://gist.github.com/1077723
$dataPad = $b-(strlen($data)%$b);
$data .= str_repeat(chr($dataPad), $dataPad);
$encrypted_data = mcrypt_generic($enc, $data);
mcrypt_generic_deinit($enc);
mcrypt_module_close($enc);
return array(
'data' => base64_encode($encrypted_data),
'iv' => base64_encode($iv)
);
}
function decrypt($key, $iv, $encryptedData){
$iv = base64_decode($iv);
$enc = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, '');
mcrypt_generic_init($enc, md5($key), $iv);
$encryptedData = base64_decode($encryptedData);
$data = mdecrypt_generic($enc, $encryptedData);
mcrypt_generic_deinit($enc);
mcrypt_module_close($enc);
// PKCS7 Padding from: https://gist.github.com/1077723
$dataPad = ord($data[strlen($data)-1]);
return substr($data, 0, -$dataPad);
}
I don't know much about mcrypt either, so I just kinda hacked these together. I md5 the key so it's always 32 characters (the max key length), and I randomly calculate an "Initialization Vector".
Using PKCS7 Padding is better because you can have strings that end in white space (as trim would remove that), also the encryption is more efficient when the string is a certain length.
I'm using AES 256 (MCRYPT_RIJNDAEL_256) here, but AES 192 (MCRYPT_RIJNDAEL_192) would work too.
Demo: http://ideone.com/WA5Tk
You can create an iv with mcrypt_create_iv(), using the appropriate size for your encryption mode.
$size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_192, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($size, MCRYPT_DEV_RANDOM);
Then pass it to mcrypt_cbc() as the optional 5th parameter. The only changes I've made here to your original functions are to pass in $iv:
function encrypt($key, $data, $iv){
$encrypted_data = mcrypt_cbc(MCRYPT_RIJNDAEL_192, $key, $data, MCRYPT_ENCRYPT, $iv);
return base64_encode($encrypted_data);
}
function decrypt($key, $encryptedData, $iv){
$dec = base64_decode($encryptedData);
$decrypt = mcrypt_cbc(MCRYPT_RIJNDAEL_192, $key, $dec, MCRYPT_DECRYPT, $iv);
return trim($decrypt);
}

mcrypt_decrypt return strange code

I tried to encrypt an array then decrypt it back to string by calling a function, it's seem return the correct value if I does all encrypt and decrypt at once time in the function, however, if I return the encrypt value, then call the function again to decrypt it will return me some strange code.
Example 1:
public main()
{
$dataArray = array("one"=>1, "two"=>2, "three"=>3);
$a = $this->encryptDecryptInfo(json_encode($dataArray),$this->key);
var_dump($a);
}
public function encryptDecryptInfo($text,$key)
{
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256,
$text= base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CFB, $iv));
return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($text), MCRYPT_MODE_CFB, $iv);
}
This will return me the correct value which is string(27) "{"one":1,"two":2,"three":3}"
Example 2:
public main()
{
$dataArray = array("one"=>1, "two"=>2, "three"=>3);
$a = $this->encryptDecryptInfo(json_encode($dataArray),$this->key,"encrypt");
$b = $this->encryptDecryptInfo($a,$this->key,"decrypt");
var_dump($b);
}
public function encryptDecryptInfo($text,$key,$type)
{
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB), MCRYPT_RAND);
if($type == "encrypt")
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CFB, $iv));
else return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($text), MCRYPT_MODE_CFB, $iv);
}
However if I do my code in this way, it will return me strange value which is like this string(27) "�ÔérôŸY éXgíœÈÐN*é౜CµÖ" .
Deos anyone know why this is happen? Both encrypt and decrypt coding are the same for example 1 and example 2, but why it will return strange code in example instead? Any way to fix this issue?
I think this is encoding issue look for UTF here - http://php.net/manual/en/function.base64-encode.php in the comments there is a UTF8 safe encoding function.
By passing the parameters left and right you are changing the encoding and you loose it in the translation. Welcome to PHP :)
You must use the same IV for decryption. Just save it along with encrypted data, for example:
if($type == "encrypt") {
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB), MCRYPT_RAND);
return base64_encode($iv . '##' .
mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CFB, $iv));
} else {
list($iv, $data) = explode('##', base64_decode($text));
return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CFB, $iv);
}
I had a similar issue. In the database I originally set it up for 16 characters. When I changed to encrypting, I forgot to change that number so the entire encrypted value was not stored. Once I corrected this it returned normal characters :)

Categories