mcrypt_encrypt to openssl_encrypt ecb des - php

i have to replace deprecated function mcrypt_encrypt using openssl_encrypt.
My old mcrypt function use 'des' cipher and 'ecb' mode.
I tried all cipher options (openssl_get_cipher_methods) and i cant find same result. Help please
$key = '04647132';
$message = hex2bin('046471324B3680');
$mcrypt = base64_encode(mcrypt_encrypt('des', $key, $message, 'ecb'));
foreach (openssl_get_cipher_methods(true) as $cipher) {
$openSsl = base64_encode(#openssl_encrypt($message, $cipher, $key, OPENSSL_RAW_DATA));
if ($openSsl == $mcrypt) {
echo 'FOUND - ' . $cipher . ' = ' . $openSsl;
exit;
}
}

This is because of the different data padding - PKCS#5 for MCrypt and PKCS#7 for OpenSSL.
You can pre-pad $message yourself (either standard would work, but PKCS#7 is better) and use the OPENSSL_ZERO_PADDING flag together with OPENSSL_RAW_DATA. That also means you have to manually strip the padding after decryption - this is the case with all block cipher modes.
But this is the least of your problems ...
Nobody should be using using ECB, or DES today; you should move away from both as soon as possible. It's understandable if you maintain a legacy system, but you don't have to encrypt new data that way.
When you eventually move to another mode, don't ignore the IV requirement - the reason why ECB is bad is exactly because it doesn't utilize an IV.
Also, I know this is just sample code, but $key in your example isn't a proper key ... use random_bytes() to generate one.
All of this, and more issues that you don't even know about, could be resolved if you simply used a popular, well-vetted cryptography library - it would do all the work for you in one easy step.
Please do seriously consider this - even professional cryptographers prefer third-party libraries instead of writing their own code, and there's good reasons for that.

Related

What is the most secure mcrpyt_encrypt algorithm?

I am trying to come up with a secure algorithm to encrypt and decrypt specific strings in my project I am working on. I am using the mcrypt_encrypt with the MCRYPT_RIJNDAEL_256 block cipher variation.
I have tested many and found this one to seem quite secure.
I am making the encrypt and decrypt into functions so I can call upon them for multiple instances in the future of my project. So far this is what I have come up with. My question here is if there is any way to make this more secure, harder to decrypt or if there are any newer formulas/methods that are known to be better.
function encrypt($privatekey, $stringe)
{
$var = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $privatekey, $stringe,
MCRYPT_MODE_CBC, $privatekey);
return base64_encode($var);
}
function decrypt($privatekey, $stringd)
{
$stringd = str_replace("~", "+", $stringd);
$var = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $privatekey,
base64_decode($stringd), MCRYPT_MODE_CBC, $privatekey);
$var = rtrim($var, "\0\4");
return $var;
}
I have tested many and found this one to seem quite secure.
What tests did you conduct, exactly?
Rijndael256 is a 256-bit block variant of Rijndael (for which the 128-bit block size variant is known as AES). However, when implemented in pure software (like mcrypt is implemented), it's vulnerable to cache-timing attacks.
What is the most secure mcrpyt_encrypt algorithm?
Mcrypt's implementations are not secure. That's why it was deprecated in PHP 7.1, and removed in PHP 7.2.
See this answer for safe-to-use example code backed by libsodium. For PHP 7.1 and below, you want to install the Sodium extension from PECL or install sodium_compat.

equivalent of mcrypt_encrypt in PhpSecLib

I have an old piece of code that's written using mcrypt extension and I have to change it to phpseclib. But my code doesn't generate the same output as mcrypt function:
Old code:
$encryptedText =mcrypt_encrypt(
MCRYPT_RIJNDAEL_256,
$myKey,
$data ,
MCRYPT_MODE_CBC,
$myIV
);
My new code:
$aes = new \phpseclib\Crypt\AES(\phpseclib\Crypt\AES::MODE_CBC);
$aes->setKey($myKey);
$aes->setIV($myIV);
$aes->disablePadding();
$seclib = $aes->encrypt( $data );
but $encryptedText and $seclib are not the same.
You're equating Rijndael with AES, a common misconception.
AES is only a subset of it - Rijndael-128, with the difference between AES variations being only the key size:
AES-128 is Rijndael-128 with a 128-bit key.
AES-256 is again Rijndael-128, but with a 256-bit key.
The suffix number in Rijndael variations on the other hand, refers to both key size and block size, so of course you cannot get Rijndael-256 by doing AES, as you need a 256-bit block size.
There's a page on the phpseclib docs, which generates sample code after you input the basic variables (cipher, mode, key size, bit size). It outputs the following for Rijndael, CBC, 256, 256:
<?php
include('Crypt/Rijndael.php');
include('Crypt/Random.php');
$cipher = new Crypt_Rijndael(); // could use CRYPT_RIJNDAEL_MODE_CBC
$cipher->setBlockLength(256);
// keys are null-padded to the closest valid size
// longer than the longest key and it's truncated
//$cipher->setKeyLength(256);
$cipher->setKey('abcdefghijklmnopqrstuvwxyz123456');
// the IV defaults to all-NULLs if not explicitly defined
$cipher->setIV(crypt_random_string($cipher->getBlockLength() >> 3));
$size = 10 * 1024;
$plaintext = str_repeat('a', $size);
echo $cipher->decrypt($cipher->encrypt($plaintext));
I am not sure if the library actually supports this cipher without mcrypt availablity, but it should.
I assume you are doing this because mcrypt is being dropped from PHP, and I strongly suggest that you change your strategy.
Even if the above works, it would be quite slow when using a userland PHP implementation of the algorithm (something which is noted in the phpseclib docs), but more importantly - you'll have no other alternatives if this library stops working, is no longer maintained, etc. Non-AES variations of Rijndael are not ubiquitous, and there are more modern algorithms available today anyway (hint: libsodium being added to PHP 7.2).
If I were you, I'd change the algorithm entirely. Of course, that would mean re-encrypting all of the data, but you'll have to do that eventually and now is really the best time to do it.

About RC4 Decryption PHP (mcrypt)

I'm looking for anything about RC4 Decryption with decode the input using: Hexa
Lucky for me, I found
PHP's mcrypt_encrypt.
I want to decrypt many cipher files with the same key.
But, I had a problem with:
$iv_size = mcrypt_get_iv_size(MCRYPT_ARCFOUR, MCRYPT_MODE_STREAM);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
print (mcrypt_decrypt(MCRYPT_ARCFOUR, $key, $text, MCRYPT_MODE_STREAM, $iv));
(And UTF-8 Vietnamese)
The result of echo $iv_size is 0.
Please help me, I don't know how I can fix it?
Key : Lyr1cjust4nct (key file .txt)
Mode: STREAM
Decode the input using: Hexa
Ciphertext: cipher.txt (Hexa)
http://pastebin.com/bmYcmU0J
RC4 doesn't support IVs. You instead need to use a unique key for each message.
RC4 has two big weaknesses that apply to your situation:
Using related keys is not secure. So you can't just concatenate a fixed key with a variable/unique IV. You'd need to use some kind of hashing scheme.
The beginning of the output is very biased, which leaks information about the ciphertext. So you need to throw away the beginning of the key-stream. I think throwing away 1024 bytes should take care of the biggest biases.
RC4 doesn't include any integrity protection (MAC). So if an attacker manipulates the ciphertext, you'll run into problems.
=> Don't use RC4. Use AES in an authenticated mode such as GCM or by combining AES with a MAC using the encrypt-then-MAC principle.
I strongly recommend using a high level library written by experts, since people get encryption wrong very often, even when using standard primitives like AES.

How to encrypt plaintext with AES-256 CBC in PHP using OpenSSL?

I am trying to encrypt sensitive user data like personal messages in my php powered website before entering into the database. I have researched a bit on the internet and I have found the few important things to remember:
Never use mcrypt, it's abandonware.
AES is based on the Rijndael algorithm and has been unbroken till now.
AES has also been recommended by NSA and used in US Government data encryption, but since the NSA is recommending it, there's a chance they might sneak upon my user data easily.
Blowfish has been unbroken as well, but slow and less popular.
So, I decided I will give it a try first with AES-256 cbc. But I am still not sure if I should not consider Blowfish a better option. So any recommendations are welcome.
And my primary concern is, how to encrypt the data in php? I don't find a good manual about this in the php documentation. What is the correct way to implement it?
Any help is heavily appreciated.
AES-256 (OpenSSL Implementation)
You're in Luck.
The openssl extension has some pretty easy to use methods for AES-256. The steps you need to take are basically...
Generate a 256-bit encryption key (This needs storing somewhere)
$encryption_key = openssl_random_pseudo_bytes(32);
Generate an "initialization vector" (This too needs storing for decryption but we can append it to the encrypted data)
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
encrypt data using openssl_encrypt()
openssl_encrypt($data, 'aes-256-cbc', $encryptionKey, $options, $initializationVector)
the $options can be set to 0 for default options or changed to OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
append the initialisation vector to the encrypted data
$encrypted = $encrypted . ':' . $iv;
retrieve the encrypted data and the initialization vector.
explode(':' , $encrypted);
decrypt data using openssl_decrypt()
openssl_decrypt($encryptedData, 'aes-256-cbc', $encryptionKey, $options, $initializationVector)
Enabling openssl
openssl_functions() won't be available by default, you can enable this extension in your php.ini file by uncommenting the line. ;extension=php_openssl.dll by removing the leading ;
PHP - Fiddle.
http://phpfiddle.org/lite/code/9epi-j5v2

Can I replicate the exact behaviour of PHP's AES encryption in ruby?

I'm in the process of rebuilding a PHP web app in Ruby on Rails, and would dearly love to avoid forcing all existing users to reset their encrypted passwords. The PHP site uses mcrypt_encrypt with AES-256-ECB, and I can't for the life of me get the same cipher text using ruby's OpenSSL. I can't decrypt them either (which is good in principle) since what's actually stored in the user DB is an MD5 hash of the AES cipher text.
I've read these previous, closely related questions and the very helpful answers:
How to make Ruby AES-256-CBC and PHP MCRYPT_RIJNDAEL_128 play well together
Part II: How to make Ruby AES-256-CBC and PHP MCRYPT_RIJNDAEL_128 play well together
including the pages referenced there, and if I understand correctly, the PHP and ruby implementations use different padding methods. Since I have to live with how things work on the PHP side, is there any way to force the same padding method on ruby/OpenSSL somehow? I'm using ruby 1.9.2-p180.
Here's the sample code in PHP:
$salt = "12345678901234567890123456789012";
$plain = "password";
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$cipher = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $plain, MCRYPT_MODE_ECB, $iv);
echo md5($cipher);
Output: 6337137fd88148250fd135a43dbeb84a
and in ruby:
require 'openssl'
salt = "12345678901234567890123456789012"
plain = "password";
c = OpenSSL::Cipher.new("AES-256-ECB")
c.encrypt
c.key = salt
cipher = c.update(plain)
cipher << c.final
puts Digest::MD5.hexdigest(cipher)
Output: 18dee36145c07ab83452aefe2590c391
Actually not in general an openssl solution but maybe it is ok for you to have a working example.
require 'mcrypt'
require 'openssl'
plaintext = 'password'
puts plaintext
key = '12345678901234567890123456789012'
enc = Mcrypt.new(:rijndael_256, :ecb, key, nil, :zeros)
encrypted = enc.encrypt(plaintext)
puts Digest::MD5.hexdigest(encrypted)
I used an additional gem(ruby-mcrypt). Seems to be an issue with openssl. Actually the issue seems to be that Openssl does not support zero padding and uses either no-padding or default-openssl-padding. Due to the fact that you use zero padding in php you must use zero padding also in ruby.
Output on my machine for the php script:
[~/test] ➔ php5 t.php
6337137fd88148250fd135a43dbeb84a
and for the ruby script:
[~/test] ➔ ruby t2.rb
password
6337137fd88148250fd135a43dbeb84a
and my ruby version:
[~/test] ➔ ruby -version
ruby 1.9.2p0 (2010-08-18 revision 29036) [i686-linux]
Hope this helps.
if key size is not standard on php side, you need to fill the key with zeros to next valid key size, in order to make ruby side works like this:
php_encrypted = string_encoded_with_php_mcrypt
key = "longerthan16butnot24".to_a.pack('a24')
enc = Mcrypt.new(:rijndael_256, :ecb, key, nil, :zeros)
enc.decrypt(php_encrypted)
In this case next valid key length is 24.
For :rijndael_256 valid key lengths are: 16, 24, 32
You can get more info on algorithms:
Mcrypt.algorithm_info(:rijndael_256
if you can use other encrypt methods, you can try TEA Block Encryption. I have adopted the method across Ruby, JS, ActionScript. It should work with PHP as well. github repo is here

Categories