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

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

Related

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.

PHP encryption not working on server

I'm trying to store encrypted cookies in a PHP app and have implemented 2 different encryption libraries in attempts to get this to work.
Both implementations, when deployed to the server, are generating fatal exceptions when calling my encryption function. On my local dev env, however, both encryption implementations are working successfully.
My open_ssl implementation code (works on localhost, does not work on remote server):
set_encrypted_cookie("foo","my_cookie_name");
function set_encrypted_cookie($msg,$name){
$key = '0123456qwerty'; // Key is stored externally but defined locally for debugging
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encryptedStr = openssl_encrypt($msg, 'aes-256-cbc', $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
setcookie($name,$encryptedStr,0,'/');
}
Any thoughts on why the server might be not allowing the openssl_encrypt() func to execute?
openssl_encrypt() returns raw binary, you should base64_encode() before storing in a cookie.
Before you do that, a couple of things you can do to improve your cryptography protocol:
Use MCRYPT_DEV_URANDOM, not MCRYPT_RAND.
Store your IV with your ciphertext (before base64_encode()ing it), so you can use the same IV when decrypting.
Encrypt then MAC.
The last link has two functions, setLessUnsafeCookie() and getLessUnsafeCookie(), that you can use as a drop-in on PHP 5.6.x.
There are still two more things to do to make it safe to use:
Use HKDF to split the key into an encryption key and a decryption key.
Use PKCS7 padding on the plaintext.
(If you want to go for maximum security, you can use libsodium instead of openssl.) Also, don't use mcrypt.

PHP: Most secure (decryptable) encryption method?

In PHP, which (decryptable) encryption algorithm is most secure one?
I mean MD5 can't be decrypted back right?
I've found full working class with mcrypt (then encoded with base64 again) which can encrypt and decrypt back.
Sample mcrypt (Encrypt):
function encrypt($value) {
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, $this->key, $text, MCRYPT_MODE_ECB, $iv);
return trim($this->safe_b64encode($crypttext));
}
Then encode again with base64:
function safe_b64encode($string) {
$data = base64_encode($string);
$data = str_replace(array('+','/','='),array('-','_',''),$data);
return $data;
}
(Sorry for the code just with the encrypt, without decrypt. I just giving sample.)
But I just want to know if there other more secure algorithm then using mcrypt.
You probably want MCRYPT_RIJNDAEL_256. Rijndael with blocksizes of 128, 192 and 256 bit is a generalization of AES which only supports a blocksize of 128 bit.
See: http://us.php.net/manual/en/mcrypt.ciphers.php and http://us.php.net/manual/en/book.mcrypt.php
Just to clarify: MD and SHA algorithms are HASH algorithms: they calculate a check sum of given data so you can later verify that it hasn't been altered. Think of it like this:
Your data is 592652. You want a checksum to know this hasnt been altered so, you do something like:
5+9+2+6+5+2=29
2+9=11
1+1=2
Now, when you want to check your data, you can put it through same calculation and see if you get the same result:
2
However there is no way to take that 2 and get back your original data: 592652.
Of course real calculations hash algoriths are different, this example is just a demonstration of the general idea. This is not encryption.
As for encryption, AES family of algorithms is probably most secure these days, I'd go AES-512. As others noted RIJNDAEL should be preferred. (AES and Rijndael are used exchangably, theyre almost the same thing: Rijndael is the name of the algorithm while AES is the name of the encryption standard that adops Rijndael as its method).
Base64 is not an encryption algorithm.
On PHP you can use the mcrypt extension to securely encrypt and decrypt data.
Blowfish is one of the most secure (and the default in mcrypt) algorithms supported by PHP.
See the full list of supported algorithms here.
Given that the question changed, this would be the new answer:
mcrypt is not an encryption algorithm. It's a library that provides an interface to different encryption algorithms to encrypt arbitrary data.
In a PHP context this is more or less the only decent thing you have to encrypt data.

Encrypt / Decrypt with Private key

I would like to implement some security in some of the Flash/PHP applications that I have.
I have some Flash apps that communicate with PHP files, and the PHP is sending the data as get string ( e.g.: name=John&sname=Doe&age=24&balance=12.4 ). Instead of all these variables, I would like it to send a single variable ( e.g.: flashvar=jr9afgaw9-fg90agfawf7gw ) that would contain those values, so then Flash would decrypt the string and get the real and useful vars.
I want to encrypt this using a private key and use the same private key to decrypt this inside Flash. If someone would want to decode the message PHP sends, he would have to decompile the flash file and find the private key I'm using in Flash to decode the message and then decode it.
The reason I posted here is because I want to use an encryption algorithm that allows only the use of a private key for encryption/decryption.
I'm new in the cryptography field and I'd like some suggestions for this.
Thank you!
A "shared private key" is refered to as a symmetric key. The standard symmetric algorithm in use today is AES. I have no idea if php, or flash, have the capability of using AES (Google does), but if they do, you could hard code an AES key in your code and use it to encrypt and decrypt data. However, hard coding a key is very bad cryptography and is little more than obfuscation.
Another thing to keep in mind is the cipher mode you are using. Cipher Block Chaining (CBC) requires the use of an initialization vector (sort of like a salt for a hash), so two of the same values encrypted with the same key, but different IV, will result in differen cipher text. ECB does not need an initialization vector, but is less secure. For your needs I would go with ECB so you dont have to worry about an IV.
Google is a very good way of finding information, you should use it.
After a quick search, I saw that ActionScript 3 has support for encryption throught ASCrypt3 library. According to the website, AES Rijndael is supported.
Rijndael is also supported in PHP using the mcrypt extension. Here's a pretty good example taken from the manual:
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "This is a very secret key";
$text = "Meet me at 11 o'clock behind the monument.";
echo strlen($text) . "\n";
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv);
echo strlen($crypttext) . "\n";
If You want to encrypt data I would go with the ASCrypt3o library.
It works very well and supports multiple types of encryption.
You can see a demo of it here click on the secret key tab.

Cryptography libraries conflict (MCrypt, libgcrypt)

I'm trying to perform encryption and decryption (Rijndael 256, ecb mode) in two different components:
1. PHP - Server Side (using mcrypt)
2. C + + - Client Side (using gcrypt)
I ran into a problem when the client side could not decrypt correctly the encrypted data (made by the server side)
so... i checked the:
1. initial vector - same same (32 length)
2. the key - again the same key on both sides..
so i wrote some code in C++ that will encrypt the data (with the same parameters like in the php)
and i found out that the encrypted data contains different bytes (maybe encoding issue??)
I'll be more than glad to get some help
PHP - MCrypt
// Encrypt Function
function mc_encrypt($encrypt, $mc_key) {
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$iv = "static_init_vector_static_init_v";
echo "IV-Size: " . $iv_size . "\n";
echo "IV: " . $iv . "\n";
$passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $mc_key, $encrypt, MCRYPT_MODE_ECB, $iv);
print_hex($passcrypt);
return $encode;
}
mc_encrypt("Some text which should be encrypted...","keykeykeykeykeykeykeykeykeykeyke");
I'll post the C++ code in a comment
Thanks,
Johnny Depp
OK. I'll make my comment an answer:
An Initialization Vector (IV) isn't used in ECB mode. If it is provided different implementations might work differently.
If you want to be sure the implementations will work correctly then use an IV of 0 (zero). Even though you provide the IV, both implementations SHOULD ignore it but one can never be sure about that. Not providing an IV in ECB mode should work aswell but again, it all depends on the implementations.
According to the PHP documentation MCrypt will ignore it. GCrypt I'm not sure about.
mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB) should actually return 0 since you specify ECB mode.
Edit:
Do not call mcrypt_get_iv_size or mcrypt_create_iv.
Instead call mcrypt_encrypt without an IV. According to the PHP documentation all bytes in the IV will be set to '\0'.
Same goes for the C++ code. No need to set any IV at all. The libgcrypt code is complex but from glancing at the source of version 1.4.5 then in ECB mode it seems the IV isn't used at all.
If the resulting ciphertext still differs then the problem is something else.
A couple of possibilities comes to mind:
Encoding - Is the same encoding used in both the server and the client?
Endianness - What type of systems are the server and the client? Big- vs Little-endian?

Categories