Password Encryption and Decryption in PHP
By Michael Kramer on October 3rd 2014 @ 9:23 am
I am writing this blog on Password Encryption / Decryption for those places when you need to protect a user’s passwords, but be able to retrieve them. I only recommend this if you have situation where you NEED to retrieve the password, otherwise a one-way hash + salt is what I recommend.
This tutorial uses mcrypt extension.
In order to achieve good encryption we are going to use a static key which is set in the code, and a dynamic IV which will change for every user.
The key can be anything, I recommend using an md5 hash of a word or two.
$key = 'passwordkey';
We need to open a cipher, there are several algorithms and encryption modes available,
$cipher = mcrypt_module_open(MCRYPT_CAST_256, '', MCRYPT_MODE_CBC, '');
Generate a random IV for the user
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($cipher), MCRYPT_DEV_RANDOM);
We want to save this IV for this user into the database, I like to do an additional base64_encode on it before I put it into the DB for the user
$_encIv = base64_encode($iv); //SQL Statement here to update the current user's IV setting
We now need to know, based on our cipher how big our KEY needs to be. Using the following it is easy to find out
$key_size = mcrypt_enc_get_key_size($cipher);
This returns us the length our key needs to be to be used with this algorithm. We then need to format our key to fit this length, since my key is longer that what is needed, to get the proper size I simply do a substr:
$key = substr(md5($key), 0, $key_size);
If your key is shorter, you can simply pad it with NULL characters.
We then need to initialize our cipher with the IV and the KEY which we have created
mcrypt_generic_init($cipher, $key, $iv);
We are finally able to encrypt our password
$encrypted_password = mcrypt_generic($cipher, $password); // pass it the cipher and our password
Then cleanup – deinit the cipher, and close the mcrypt module
We now have our encrypted password, and before we store this in the database I like to a base64_encode on it to make sure none of the symbols will interfere with the database encoding etc
We will start by getting the encrypted password from the database and doing a base64_decode on it and re-initing our cipher like before
$cipher = mcrypt_module_open(MCRYPT_CAST_256, '', MCRYPT_MODE_CBC, ''); $key_size = mcrypt_enc_get_key_size($cipher); $key = substr(md5($key), 0, $key_size); //get our key into the right size $iv = null; //TODO: pull the IV from the user in the database $iv = base64_decode($iv); //decode the IV
It is now time for us to decrypt our password, which is really easy to do, pretty much the same process as encrypting
mcrypt_generic_init($cipher, $key, $iv); $decrypted_password = mdecrypt_generic($cipher, $password); mcrypt_generic_deinit($cipher);
And there you have the decrypted password.