There are a number of questions that discuss storing sensitive information in MYSQL using encryption. Some make great suggestions about hardening the web server, database server, and web application (Store 'sensitive' data in MySQL DB). However, little has been discussed about the exact implementation of MYSQL's AES_Encrypt and AES_Decrypt functionality other than a couple questions dealing with technical issues around usage (How to use AES_ENCRYPT and AES_DECRYPT in mysql).
I am using the MYSQL prepared statements below to encrypt sensitive information:
$stmt = $db->prepare("INSERT INTO Table_Name (SensitiveData) VALUES (AES_ENCRYPT(?,UNHEX(SHA2('RandomStringofData',512))))");
$stmt->bind_param('s',$SensitiveData);
$stmt->execute();
$stmt->close();
I use the AES_DECRYPT function with the same SHA2 string to decrypt the data when needed. The way I understand this, short of someone accessing the web server itself or figuring out the SHA2 passphrase, they cannot easily access this sensitive data. For example, someone gaining access to the database server will not help them interpret this sensitive data.
I have several questions:
- I read about the Init Vector here: http://dev.mysql.com/doc/refman/5.7/en/encryption-functions.html. I don't quite understand how this works or whether it is something that should be implemented. What is an Init Vector and can it help improve the security of the encryption method I am using above?
- I am uncomfortable having the SHA2 passphrase be in plain text in the file that encrypts and decrypts this data. Is there an alternative way to code this so that it is located in a file off the public directory?
- One pitfall of this system is that if someone hijacks the web application, they can still get access to this sensitive data simply by running the script that decrypts the information. Although I have robust access control, if this is also circumvented, I am looking at a situation where data can be compromised. I've implemented the SSL precautions and others recommended in this link: How can I store sensitive data securely in a MySQL database?. I've also reviewed the recommendations in this link: How do you Encrypt and Decrypt a PHP String?. Is there a way to have this data decrypted for other applications to use, or is it far more secure to treat it like a password and just compare the hashed values to make sure they are equal?
- My final question has to do with overhead. This is a huge database that measures several gigabytes in size, with millions of rows and hundreds of columns. I am encrypting only a few fields in this database and they are not used as indices. How much of a performance impact am I really seeing with something like this?
Thanks.