Replace Mcrypt with OpenSSL - is that possible - php

currently we have a mcrypt implentation on our systems to crypt some Ids in our PHP application.
But Mcrypt is deprecated now and I have to replace it.
Unfortunately, I cannot convert all of the saved information.
Decryption would be enough.
These are the two functions that I use:
self::$key = '123456';
public static function encrypt($plaintext)
{
$td = mcrypt_module_open('cast-256', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, self::$key, $iv);
$encrypted_data = mcrypt_generic($td, $plaintext);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$encoded_64 = base64_encode($encrypted_data);
return trim($encoded_64);
}
and
public static function decrypt($crypttext)
{
$decoded_64 = base64_decode($crypttext);
$td = mcrypt_module_open('cast-256', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, self::$key, $iv);
$decrypted_data = mdecrypt_generic($td, $decoded_64);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return trim($decrypted_data);
}

Eh? PHP has OpenSSL support ... https://www.php.net/manual/en/book.openssl.php
"So, certainly yes." You can use mcrypt to decrypt all of your existing information and then encrypt it using OpenSSL or some other cipher algorithm of your choosing.
Now, I'd bear in mind that OpenSSL is very much designed around the notion of "public and private keys." So, if you go that route, you should try to take advantage of that. There are actually a great many cipher algorithms that can be used in modern PHP ... https://www.php.net/manual/en/function.crypt.php

Related

Why can't I decrypt an mcrypt encrypted text with opnssl using blowfisch an PHP 7.x

Why can't I decrypt an mcrypt encrypted text with openssl
I have encrypted information in the database and in apps on mobile devices.
So far, these have been encrypted and decrypted on a server with PHP 7.0 and mcrypt.
- The deprecated message is already displayed there.
There will be no mcrypt in the next PHP versions. So I tried to do that with openssl.
Although I also use blowfish with mode CFB at openssl, it doesn't work.
What am I doing wrong?
#
# mcrypt on Server with PHP 7.0
/**
* encrypt with Blowfish and mcrypt
*/
function mcrypt_encrypt($plaintext, $key)
{
$td = mcrypt_module_open(MCRYPT_BLOWFISH, '', MCRYPT_MODE_CFB, '');
$ivsize = mcrypt_enc_get_iv_size($td);
$iv = mcrypt_create_iv($ivsize, MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$crypttext = mcrypt_generic($td, $plaintext);
mcrypt_generic_deinit($td);
return $iv . $crypttext;
}
/**
* decrypt with Blowfish and mcrypt
*/
function mcrypt_decrypt($crypttext, $key)
{
$td = mcrypt_module_open(MCRYPT_BLOWFISH, '', MCRYPT_MODE_CFB, '');
$ivsize = mcrypt_enc_get_iv_size($td);
$iv = substr($crypttext, 0, $ivsize);
$crypttext = substr($crypttext, $ivsize);
mcrypt_generic_init($td, $key, $iv);
$plaintext = mdecrypt_generic($td, $crypttext);
mcrypt_generic_deinit($td);
return $plaintext;
}
This works on PHP 7.0:
$plaintext = 'Hello World';
$mcrypt_crypttext = mcrypt_encrypt($plaintext,'secret');
$mcrypt_plaintext = mcrypt_decrypt($mcrypt_crypttext,'secret');
# $plaintext == $mcrypt_plaintext;
The new funktions with OpenSSL:
#
# openssl on Server with PHP 7.2
/**
* encrypt with Blowfish and openssl
*/
function openssl_encrypt($plaintext, $key)
{
$ivlen = openssl_cipher_iv_length('bf-cfb');
$iv = openssl_random_pseudo_bytes($ivlen);
$crypttext = openssl_encrypt($plaintext, 'bf-cfb', $key, OPENSSL_RAW_DATA, $iv);
return $iv . $crypttext;
}
/**
* decrypt with Blowfish and openssl
*/
function openssl_decrypt($crypttext, $key)
{
$ivlen = openssl_cipher_iv_length('bf-cfb');
$iv = substr($data, 0, $ivlen);
$crypttext = substr($data, $ivlen);
$plaintext = openssl_decrypt($crypttext, 'bf-cfb', $key, OPENSSL_RAW_DATA, $iv);
return $plaintext;
}
This works also:
$openssl_crypttext = openssl_encrypt($plaintext,'secret');
$openssl_plaintext = openssl_decrypt($openssl_crypttext,'secret');
# $plaintext == $openssl_plaintext;
But this goes wrong - decrypting the mcrypt encrypted text:
$openssl_plaintext = openssl_decrypt($mcrypt_crypttext,'secret');
# $plaintext != $openssl_plaintext
Is there a way to decrypt mcrypted data with PHP7.2?

Preparing for removal of Mcrypt in PHP 7.2

So as time moves on mcrypt will go in PHP 7.2.
Of course there is an alternative: openssl.
I find it difficult to switch from mcrypt to openssl, using AES 256 CBC and preserving IVs. I am sort of new to cryptography, so I don't really know everything, but I understand the basics.
Let's say I have the following code
function encrypt($masterPassword, $data)
{
$keySize = mcrypt_get_key_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM);
$key = mb_substr(hash('SHA256', $masterPassword), 0, $keySize);
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv);
return base64_encode($iv . $encrypted);
}
function decrypt($masterPassword, $base64)
{
$keySize = mcrypt_get_key_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$key = mb_substr(hash('SHA256', $masterPassword), 0, $keySize);
$data = base64_decode($base64);
$iv = substr($data, 0, $ivSize);
$encrypted = substr($data, $ivSize, strlen($data));
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CBC, $iv);
return trim($decrypted);
}
How can I "convert" this code to use openssl insted of mcrypt?
You can't convert it, because Rijndael-256 is not AES-256, and the OpenSSL extension doesn't ship with Rijndael-256 support.
AES-256 is Rijndael-128 with a 256-bit (32-byte) key.
Unfortunately, you'll have to re-encrypt all of your data.
Edit: Also, the scheme you're currently using has some problems:
It lacks authentication (HMACs are the easiest way to do it in PHP)
It lacks proper padding (mcrypt pads with zero bytes; you need something like PKCS#5 padding instead), which is required for block mode encryption to be safe.
It's not byte-safe (you're using mb_substr())
The good news is that OpenSSL will do PKCS#5 padding for you automatically, but you should go even further and use a solid encryption library like defuse/php-encryption.

AES Cookie Data randomly not decryptable

I'm having a problem when writing and parsing some DATA out of stored cookies.
Here are my crypt and decrypt functions (which I have found in another topic here).
function decrypt($crypttext){
$crypttext = base64_decode($crypttext);
$plaintext = '';
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, '');
$ivsize = mcrypt_enc_get_iv_size($td);
$iv = substr($crypttext, 0, $ivsize);
$crypttext = substr($crypttext, $ivsize);
if ($iv)
{
mcrypt_generic_init($td, CRYPTKEY, $iv);
$plaintext = mdecrypt_generic($td, $crypttext);
}
return trim($plaintext);
}
function encrypt($plaintext){
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, CRYPTKEY, $iv);
$crypttext = mcrypt_generic($td, $plaintext);
mcrypt_generic_deinit($td);
return base64_encode($iv.$crypttext);
}
My usage is fairly simple:
//read, split if neccesarry, check if already in it, if not-> add, crypt, write
if(isset($_COOKIE['DATA'])){
$data = decrypt($_COOKIE['DATA']);
$search = explode('#',$data);
if(!in_array($lnk, $search)){
$data.= "#".$lnk; // $lnk = additional data
$err = setrawcookie("DATA", encrypt($data));
}
$err = true;
}
In most tries, it doesn't work adding a $lnk. The decryption of the cookie after I've wrote it, is wrong. undefined junk. (so something doesn't work well).
I haven't been able to find any errors in the code at all. My best guess is that the problem is caused by :
$ivsize = mcrypt_enc_get_iv_size($td);
$iv = substr($crypttext, 0, $ivsize);
Specifically, that $ciphertext is smaller than $ivsize?
Any other ideas?
// to prevent questions about it:
the data which i store, are just php uniqueID()'s separeted by '#'. so maybe in future there will be 10 IDs stored (encrypted) in the cookie...i didin't know the max size of a cookie and the factor AES blow this up, but i thought a cookie should get it.
(if there is a easier synchronus way to encrypt (this should not be high security, but mostly safe) please feel free to tell me.
Try using bin2hex instead of base64_encode(). I previously answered a similar question on SO.

Encrypt message in PHP, decrypt in JavaScript

I want to encrypt a message by php but at client side, I want javascript to decrypt it. I had tried Blowfish(using mcrypt ), but I discovered that php echoing non-alpha-numberic character and Javascript display alpha-numeric. I am using ajax so that the page will not reload.
I had tested codes from http://aam.ugpl.de/?q=node/1060 and http://www.php-einfach.de/blowfish_en.php#ausgabe.
Any help is appreciated.
Edit: I use Diffie-Hellman to calculate secret key with random generated number a and b. Below is the resulted from php code
class Encryption
{
const CYPHER = 'blowfish';
const MODE = 'cbc';
const KEY = '26854571066639171754759502724211797107457520821';
public function encrypt($plaintext)
{
$td = mcrypt_module_open(self::CYPHER, '', self::MODE, '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, self::KEY, $iv);
$crypttext = mcrypt_generic($td, $plaintext);
mcrypt_generic_deinit($td);
return $iv.$crypttext;
}
public function decrypt($crypttext)
{
$plaintext = '';
$td = mcrypt_module_open(self::CYPHER, '', self::MODE, '');
$ivsize = mcrypt_enc_get_iv_size($td);
$iv = substr($crypttext, 0, $ivsize);
$crypttext = substr($crypttext, $ivsize);
if ($iv)
{
mcrypt_generic_init($td, self::KEY, $iv);
$plaintext = mdecrypt_generic($td, $crypttext);
}
return $plaintext;
}
}
$encrypted_string = Encryption::encrypt('this is a test');
$decrypted_string = Encryption::decrypt($encrypted_string);
echo "encrypted: $encrypted_string<br>";
echo "decrypted: $decrypted_string<br>";
encrypted: µ˜?r_¿ÖŸŒúw‰1‹Žn!úaH
decrypted: this is a test
This javascript AES crypto library from a few stanford students is the best I've seen:
http://crypto.stanford.edu/sjcl/
But note their caveat:
We believe that SJCL provides the best security which is practically available in Javascript. (Unfortunately, this is not as great as in desktop applications because it is not feasible to completely protect against code injection, malicious servers and side-channel attacks.)
UPDATE:
In PHP, use base64_encode() after encrypting and base64_decode() before decrypting. This way it will be rendered with characters safe for transmission. In the browser, use atob() and btoa().

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

Categories