13

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:

  1. Never use mcrypt, it's abandonware.

  2. AES is based on the Rijndael algorithm and has been unbroken till now.

  3. 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.

  4. 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.

jww
  • 97,681
  • 90
  • 411
  • 885
DASH
  • 181
  • 1
  • 2
  • 10

1 Answers1

33

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...

  1. Generate a 256-bit encryption key (This needs storing somewhere)
    • $encryption_key = openssl_random_pseudo_bytes(32);
  2. 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'));
  3. 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
  4. append the initialisation vector to the encrypted data
    • $encrypted = $encrypted . ':' . $iv;
  5. retrieve the encrypted data and the initialization vector.
    • explode(':' , $encrypted);
  6. 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

Maksym Moskvychev
  • 1,471
  • 8
  • 11
Luke
  • 3,481
  • 6
  • 39
  • 63
  • I have read somewhere that I should convert it into hex before proceeding, which part should I convert? And can you please give me an example of the key and IV? – DASH Jan 19 '16 at 08:41
  • added examples of the `key` and `iv` generation. Not sure about hex conversion I've always worked from the above. Opps fixed a typo too. – Luke Jan 19 '16 at 08:43
  • Okay, thanks for that! Will it be safe to store the encrypted data straight to the database and when the receiver has to view it I will just let them have the keys and iv? – DASH Jan 19 '16 at 08:46
  • 1
    Implementation is entirely up to you. In my opinion it would be better to authenticate the user in PHP code when they request the data. Maybe with a login system for example. Then authenticated suers can be shown the unencrypted data. I wouldn't ever recommend publishing the keys. – Luke Jan 19 '16 at 08:51
  • 1
    Another thing, should I leave the options to 0? And Yes, I have done that. I have a login system using bcrypt to validate the passwords. I need to know if it is safe to store sensitive data like personal messages in my database? Will it slow down my performance? And will blowfish be a viable substitute for this? – DASH Jan 19 '16 at 08:56
  • Provided you encrypt the data, it is OK to store it in the database. The performance hit is negligble. It doesn't matter how great the performance of your codebase is. If it can't store users messages securely - people won't be willing to use it.. I don't know enough about Blowfish as an alternative to provide a fair answer. Perhaps someone else could add a blowfish example. – Luke Jan 19 '16 at 09:00
  • There's a fatal error that says undefined function openssl_random_pseudo_bytes. – DASH Jan 19 '16 at 09:05
  • See here: http://stackoverflow.com/questions/11212808/fatal-error-call-to-undefined-function-openssl-random-pseudo-bytes The openssl library is an extension to core PHP - you'll need to enable it in your `php.ini` – Luke Jan 19 '16 at 09:07
  • 2
    Since there's a non-zero chance that ":" will be in the encrypted string, using explode is not the best choice. I'd recommend using substr. – Mav Jul 12 '18 at 17:58
  • 3
    @Mav as long as you dont use OPENSSL_RAW_DATA then $encrypted is a base64 string, and if you base64_encode($iv) before concatenating with ':' then you'll be safe as base64 doesn't use ':' – Shardj May 14 '19 at 10:28