2

I want to encrypt some data within my php file when I add the stuff to my mysql database.

This is how I do it.

I create a static key like:

$key = md5("pass");

Then I have two functions called encrypt() and decrypt() and they do this:

function encrypt($string, $key){
    $string = rtrim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $string, MCRYPT_MODE_ECB)));
    return $string;
}

function decrypt($string, $key){
    $string = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($string), MCRYPT_MODE_ECB));
    return $string;
}

I am not sure if this is best practice but like how do I generate a key other than md5?

  • Is there a reason by design that you can't randomly generate a key, or do you have to use a password? – RoraΖ Mar 25 '16 at 12:58

1 Answers1

7

There are at least two problems with this approach.

  1. Your choice of key generation
  2. Your choice of encryption mode

Key Generation

You're doing md5("static password") as your key. This is really bad. First, you're "only" getting 128-bits from MD5 and you're using 256-bit keyed AES, thereby wasting cycles (because AES-256 is slower than AES-128) on something you're not using anyways. Secondly, you password is weak. "pass" is not a secure password and I really hope you replace it with something much stronger for production use. Third, you're using plain MD5 for the password processing (also see our canonical answer on password hashing). This is as bad as it can get, because the ciphertexts could be attacked using precomputed (rainbow) tables and MD5 is a fast hashing function, allowing fast brute-forcing of your password. Fourth: Why are you even using a password!?. There's no logical reason to use a static (human-readable) password instead of a secure, randomly generated key of the desired size. This way you don't have to worry about brute-force, you don't have to worry about using MD5 (which will give bad press) you don't have to worry about your key to be too short.

Encryption mode

While you use AES-256 as encryption algorithm (which is OK), you're using ECB as your mode of operation for AES. This way you have two problems: a) you're leaking which AES blocks (16-bytes) are equal and b) you have to pad your messages to be a multiple of 16-bytes. To fix these problems you need to swithc the mode. GCM is the best option you have. Unfortunaly, this isn't properly supported by PHP until PHP 7.1 via openssl_encrypt() or mcrypt_encrypt() (which you really shouldn't use, because it's slower, no longer maintained and less hardened than OpenSSL). If you already have PHP 7.1, then fine, you can use AES-GCM with openssl_encrypt(), which will protect your ciphertext from being read and / or modified, provided you hand a unique (not secret) nonce over for each encryption. Until you have proper PHP 7.1 AEAD encryption, you have to use an ad-hoc construction. This means, you first encrypt the data using a (random) 16-byte IV with CTR mode and then you calculate the HMAC-SHA256 of the ciphertext and store the resulting tag, so you can verify it upon next read access.

SEJPM
  • 9,540
  • 6
  • 37
  • 67
  • Hi, Many thanks for your kind comments. Firstly, I am not encrypting a password - but the actual data in the database such as the customers bank card details. I want to ideally encrypt that and then decrypt it# – Benj Mikesozery Mar 25 '16 at 22:02
  • @BenjMikesozery, when talking about passwords and their processing, I was specifically referring to your `$key = md5("pass");` and not to the bulk data that you're encrypting using this key. The bulk data (your database contents secured by the *secure* key) should of course be reversibly encrypted (i.e. using GCM or CTR+HMAC). – SEJPM Mar 25 '16 at 22:52
  • Many thanks for your response. The only real question I have is, how do I securely encrypt and decrypt the data? Apologies, I am new to web development and security in general – Benj Mikesozery Mar 25 '16 at 23:08
  • @BenjMikesozery, [the linked question by Xander](http://security.stackexchange.com/q/80888/71460) does a really good job and NaCl / libsodium is really easy to use normally and should allow you to get the data encrypted securely, easily. – SEJPM Mar 25 '16 at 23:16
  • is openssl_encrypt() safe and any good? – Benj Mikesozery Mar 25 '16 at 23:33
  • @BenjMikesozery, libsodium should be safer to use (because it apparently already has an AEAD interface), but `openssl_encrypt()` will do the job if used properly. – SEJPM Mar 25 '16 at 23:36
  • Hi, thank you for your response - I am leaning more towards openssl_encrypt(). Is it easy to use? – Benj Mikesozery Mar 25 '16 at 23:39
  • @BenjMikesozery follow the advice given here (use openssl_encrypt() with AEAD directly or paired with HMAC) and you'll be fine. If you do this (and use a strong key), chances are, you won't screw up. – SEJPM Mar 25 '16 at 23:55
  • The question is, how do I do this? Are there any tutorials online? – Benj Mikesozery Mar 26 '16 at 00:25