I have an application that was build on CakePHP 1.2, and stored some encrypted data. I am rebuilding the application and need to decrypt the data in the new app to update the encryption on it. The ciphers and methods used to encrypt the data in CakePHP 1.2 are not available in PHP 7.1+. Does anyone know of a way that I can decrypt the data in a PHP 7.1+ environment so that it can be encrypted with newer technologies?
Current method that encrypts/decrypts data
function _cryptData(&$data, $direction) {
$ivSize = mcrypt_get_iv_size(MCRYPT_TRIPLEDES, MCRYPT_MODE_CBC);
switch ($direction) {
case 'encrypt':
$iv = mcrypt_create_iv($ivSize, MCRYPT_RAND);
$data = base64_encode($iv) . '|' . base64_encode(mcrypt_encrypt(MCRYPT_TRIPLEDES, Configure::read('CakeMix.cryptKey'), $data, MCRYPT_MODE_CBC, $iv));
break;
case 'decrypt':
list($iv, $encoded) = explode('|', $data);
$data = mcrypt_decrypt(MCRYPT_TRIPLEDES, Configure::read('CakeMix.cryptKey'), base64_decode($encoded), MCRYPT_MODE_CBC, base64_decode($iv));
break;
}
}
The shown code in your question seems to be custom, ie non-CakePHP core code, so this seem more just PHP related.
Mcrypt is deprecated, but still available in PHP 7.1, it has only been removed as of PHP 7.2. Mcrypt can also still be used with PHP 7.2+, you'd just have to install it manually, as it's been moved to PECL, see for example Issue in installing php7.2-mcrypt. You could also use a polyfill like phpseclib/mcrypt_compat. So you should be able to continue using Mcrypt for decryption, and port the data to whatever encryption you like.
Furthermore it should generally also be possible to decrypt the data using OpenSSL, though there seem to be pitfalls around null padding, see for example Decrypt mcrypt with openssl. Here's a basic example:
$data = openssl_decrypt(
base64_decode($encoded),
'des-ede3-cbc',
Configure::read('CakeMix.cryptKey'),
OPENSSL_RAW_DATA | OPENSSL_NO_PADDING,
base64_decode($iv)
);
There's quite a lot of topics on replacing Mcrypt with OpenSSL, which you may want to have a look at for further options.
Related
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.
As php has stopped support for Mcrypt from 7.2 and onwards. I do not know enough to convert Mcrypt to Openssl.
I was wondering if someone could provide the OpenSSL equivalent for this? For the record, I am not looking to support Mcrypt so I have to decrypt my mcrypt encrypted strings(passwords) via openSSL.
To Encode via mcrypt->
static function encode($value= NULL, $key= NULL){
if(!$value){
return false;
}
$text = $value;
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv);
return trim(self::safe_b64encode($crypttext));
}
private function safe_b64encode($string= NULL) {
$data = base64_encode($string);
$data = str_replace(array('+','/','='),array('-','_',''),$data);
return $data;
}
Updated
Unfortunately it looks like there is not a way your going to be able to do what you want. Had you used the MCRYPT_RIJNDAEL_128 mode with a 256 byte key there may have been hope.
AES-256 and MCRYPT_RIJNDAEL_256 encryption are not the same thing, even though AES is basically Rijndael. It all has to do with the block size. What you want to do just is not compatible.
Your options are this:
Use a version of PHP that still has the MCRYPT libraries available and decrypt the passwords to a file and then encrypt them with your new encryption method.
A PECL option looks available that would allow you to install a pseudo version of MCRYPT with your latest version of PHP.
For just encrypting and decrypting your passwords OpenSSL should be fine, but
OpenSSL has limitation especially when you want to encrypt large amounts of data. It requires you to write additional code to break apart your data into smaller chunks before you encrypt and then put it back together after you decrypt.
I highly recommend that you skip OpenSSL and learn the LibSodium library which is now supported on the latest PHP versions.
http://php.net/manual/en/book.sodium.php
Here is a good page to read to get you started.
https://paragonie.com/blog/2015/05/using-encryption-and-authentication-correctly
Some more Libsodium resources.
https://github.com/paragonie/pecl-libsodium-doc/blob/v1/chapters/01-quick-start.md
Good Luck~
You have so many choices when it comes to encrypting data, so that's why you should implement it yourself. I recommend you the library diffuse/php-encryption, see this link for a detailed tutorial.
I currently have a PHP application that uses data-at-rest encryption to store sensitive information onto a database that I can later decrypt for use in my application.
Here is the current code I'm using. I kno...i kno...it's not very secure at all but it works fine for what I using it for. I'm not storing credit card numbers, social security number, or anything like that. Mainly just names and addresses.
define('CRYPTO_KEY', 'some-key');
function decrypt($val){
$val = urlencode($val);
$data = base64_decode(urldecode($val));
$iv = substr($data, 0, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC));
$val = rtrim(
mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
hash('sha256', CRYPTO_KEY, true),
substr($data, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)),
MCRYPT_MODE_CBC,
$iv
),
"\0"
);
return $val;
}
function enc($val){
$iv = mcrypt_create_iv(
mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC),
MCRYPT_DEV_URANDOM
);
$val = urlencode(base64_encode(
$iv .
mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
hash('sha256', CRYPTO_KEY, true),
$selection,
MCRYPT_MODE_CBC,
$iv
)
));
return $val;
}
The problem I'm running into is that I just upgraded from PHP 5.5 to PHP 7.1. Now in PHP 7.1 my encrypt/decrypt function throws a ton of warnings out stating that the following function are deprecated:
mcrypt_get_iv_size()
mcrypt_create_iv()
mcrypt_encrypt()
mcrypt_decrypt()
I was doing some research and found that the new recommendations are to use libraries like libsodium or OpenSSL found HERE
I looked into both but the documentation is way too technical for me to understand. I can't even figure out how to install libsodium, let alone use it.
My question is, does anyone have a decent encrypt/decrypt function that is compatible with PHP 7.1 or higher they'd be willing to share?
Better yet, would anyone be willing to provide instructions on how to use libsodium or OpenSSL for data encryption/decryption?
FYI - I'm currently using a shared hosting platform with cPanle. I have composer installed and understand how to install packages through it. I have never used PECL or PEAR
This is a bit of an old question, but I figured I'd answer anyway.
As of PHP 7.2, Libsodium is enabled as a core module. There's nothing else you need to install, it will "just work" moving forward.
For PHP 7.1, I'd recommend the Pecl extension for Libsodium. You can install it just like you would any other Pecl extension:
pecl install libsodium
In any case, I'd highly recommend using the sodium_compat library as a wrapper around Libsodium. It's compatible with PHP all the way back to 5.2 and even ships with a PHP-native implementation of Libsodium if the Pecl module is missing.
Note: The PHP-native implementation is significantly slower than the compiled extension, but if you're having trouble upgrading to 7.2 or installing the Pecl module it will at least get you started.
As for your existing code, consider the following as an upgrade to use sodium_compat:
define('CRYPTO_KEY', 'some-key');
function decrypt($val){
$key = base64_decode(CRYPTO_KEY);
$data = base64_decode(urldecode($val));
$nonce = substr($data, 0, ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES);
$ciphertext = substr($data, ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES);
$plaintext = ParagonIE_Sodium_Compat::crypto_secretbox_open($ciphertext, $nonce, $key);
if ($plaintext === false) {
throw new Exception("Bad ciphertext");
}
return $plaintext;
}
function enc($val){
$key = base64_decode(CRYPTO_KEY);
$nonce = random_bytes(ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES);
$ciphertext = ParagonIE_Sodium_Compat::crypto_secretbox($val, $nonce, $key);
return urlencode(base64_encode($nonce . $ciphertext));
}
The additional ParagonIE_Sodium_Compat:: namespacing is if you're using sodium_compat. If you're able to just upgrade to PHP 7.2 you could dump that and use the native methods and constants directly. They're all named pretty similarly, so I won't belabor it here.
Note: As mentioned by others in the comments, storing your secret key hard-coded alongside the code that does the crypto is not a good idea. I copied it here to illustrate how your code would change to use Libsodium, not as an endorsement of the way CRYPTO_KEY is defined.
Here is a way to encrypt Php 7 with Open SSL. This is a sure fire way to encrypt and decrypt your data. The only thing to keep in mind is that when searching your database for certain parameters you will need to decrypt before the search starts. First you start out with a key. Then there is an encrypt function as well as a decrypt function.
Key you can change to whatever you want. Store it on your server or another server.
$key = 'qkwjdiw239&&jdafweihbrhnan&^%$ggdnawhd4njshjwuuO';
Next is the encrypt php function.
function encryptthis($data, $key) {
$encryption_key = base64_decode($key);
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
$encrypted = openssl_encrypt($data, 'aes-256-cbc', $encryption_key, 0,
$iv);
return base64_encode($encrypted . '::' . $iv);
}
Then to decrypt use this function.
function decryptthis($data, $key) {
$encryption_key = base64_decode($key);
list($encrypted_data, $iv) = array_pad(explode('::', base64_decode($data),
2),2,null);
return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0,
$iv);
}
To see code for a working example with a form please see this webpage. https://a1websitepro.com/data-encryption-php-mysql-methods-implementation-open-ssl-encrypt/
I have to store some information (Text) in an MySQL Column (MediumBLOB). It works but I am not sure if this way is secure enough.
Please don't wonder that the encryption key is randomized. It works as designed :)
$encryptionKeyRandom = str_random(12);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
$encrypted_string = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $encryptionKeyRandom, $input['item'], MCRYPT_MODE_ECB, $iv);
$input['item'] = bin2hex($encrypted_string);
// Save to DB
Suggestions for better security/encryption are welcome.
mcrypt is outdated and hasn't been touched in quite a few years.
I'm not saying that it isn't useable, just that there are faster alternatives available cause quite frankly, mcrypt is slow.
openssl is a better alternative and works much like mcrypt, but the best library is in my opinion sodium. However sodium is not yet available in php 7 and maybe bringing it to 7.1. but should be for other versions.
https://www.virendrachandak.com/techtalk/encryption-using-php-openssl/ helped me migrating from mcrypt to openssl, take a look.
Problem
I need to encrypt data in Javascript and decrypt it in PHP. Mcrypt seems the way to go on the PHP side, and AES seems thoroughly good enough, but I'm having trouble finding a javascript decryption algorithm that matches it. Any suggestions? I'm open to replacing any of the assumptions (mcrypt, aes, ECB, etc) if it'll help get a compatible js encryption/decryption library.
Code
The PHP looks pretty much like this:
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encrypted = mcrypt_encrypt( MCRYPT_RIJNDAEL_256, $key, $plaintext,
MCRYPT_MODE_ECB,$iv );
Rationale
Not that it matters, but the point here is to encrypt some credentials to an external system so that we can pass it around our server without our analytics and logging servers picking it up in the clear. It'll eventually be decrypted in the PHP just before it's sent to the external system.
I ended up using the SlowAES library, which has parallel implementations in PHP and JS:
http://kevinkuchta.com/_site/2011/08/matching-php-and-js-encryption/