Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the recommended approach for encrypting/decrypting large text data in MySQL?

I have a client/server application that runs on an intranet, and I have the requirement to encrypt the data in one field of one table of the database. That field is currently TEXT data type, which I have learned is not good for encryption in MySQL. The text stored in the field is similar to an employee performance evaluation containing narrative comments from supervisors. Because of personal information restrictions concerning the network the system runs on, this data cannot be stored in plain text. The data also needs to editable by different users with differ "roles" (authentication levels) via the client side of the application.

So... I have been researching how to encrypt this data, and this is what I understand so far:

  • MySQL docs explain the AES functions, and that I should change the field datatype likely to a BLOB to accomodate the encrypted information.
  • The key will have to be fixed (i.e. not salted with a user password etc. as I have read on SO), because different users need to be able to edit/review the comments.
  • I think the best option is to store the key and pass it as a variable in the php code, similar to what I do with the MySQL login information for the application.

Is using the AES functions in this scenario a suitable way to proceed with this, or are there issues I don't know about? I did wonder about problems (performance?) because of the potential length of the text. Most examples I have found relate to encrypting smaller data: e.g. name, address, credit card numbers, etc.

Any advice would be greatly appreciated. Thanks in advance!

like image 947
Carvell Fenton Avatar asked Sep 09 '11 12:09

Carvell Fenton


People also ask

How do I decrypt encrypted data in MySQL?

The MySQL AES_DECRYPT function returns the original string after decrypting an encrypted string. It uses AES(Advanced Encryption Standard) algorithm to perform the decryption. The AES_DECRYPT function returns the decrypted string or NULL if it detects invalid data.

What encryption is used in MySQL?

MySQL Enterprise Transparent Data Encryption (TDE) protects your critical data by enabling data-at-rest encryption in the database. It protects the privacy of your information, prevents data breaches and helps meet regulatory requirements including: Payment Card Industry Data Security Standard (PCI DSS)

How can we encrypt and decrypt a data present in a MySQL table using MySQL?

Register now or log in to answer. Use AES_ENCRYPT (),AES_DECRYPT() functions in mysql for encryption and decryption. There's a library from php for encryption which is php5_mcrypt.

How do I encrypt an entire database in MySQL?

To enable encryption for the mysql system tablespace, specify the tablespace name and the ENCRYPTION option in an ALTER TABLESPACE statement. mysql> ALTER TABLESPACE mysql ENCRYPTION = 'Y'; To disable encryption for the mysql system tablespace, set ENCRYPTION = 'N' using an ALTER TABLESPACE statement.


2 Answers

Using AES, in CBC or CTR mode is fine. Avoid ECB mode as it is insecure. Use PKCS7 padding.

If you want to store the encrypted file as text, rather then a BLOB, then convert the binary cyphertext to Base64 before saving to the database. Base64 only uses text characters. You will obviously need to convert the Base64 back to binary before decrypting.

Your major problem is key handling, since everyone with access to the database is going to need the key and you cannot store the key in the database itself. You may want to take some expert advice on this as it is critical.

like image 124
rossum Avatar answered Sep 21 '22 03:09

rossum


Security of the DB

First you need to ask yourself: "why are you encrypting the data in the database?".
The reason is that the database might fall into the wrong hands.
For this reason you cannot store the key in the database itself.
You must assume that all data in the DB is known to an attacker.

Therefore the only answer is to have the key outside the DB.
I would advise to salt the key using data in the same row as the article, so that an attacker cannot use a rainbow table against all articles.

pseudocode for select statement:

SELECT AES_DECRYPT(article, CONCAT(salt, '$secret_key')) FROM articles
WHERE id = '123' 

PHP security
Note that listing the AES encryption key in the PHP source code will also be a fail.
It will have to only live in memory on the computer which also needs to be secure.
An option is to read it in from a remote computer (make the transfer encrypted) that is secure (datacenter with guards) or have a senior official key it in upon program startup.

How to avoid the MySQL ECB hole
If you need to have it really secure, you will have to do the encryption in php.

See this article to know why MySQL (which uses ECB mode) has a problem: http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29

pseudocode

<?pseudophp
$secretmessage = $_GET['secret_message_from_user'];
$randomprefix = hash('sha512',$timestampinmilliseconds);
$secretmessage = $randomprefix."@@@@".$secretmessage; 
//$password = "really long password entered by a trusted superuser";
$key256 = hash('sha512',$password); //stuff the password into 256 bits.
//You'll have to check that the output is really 256 bits, an tweak it if not.
$iv =  '1234567890123456'; //this is public, because the iv is already in the text.

printf("iv: %s\n",bin2hex($iv));
printf("key256: %s\n",bin2hex($key256)); //debug stuff
printf("message before\n %s\n",$secretmessage);

//We use AES aka RIJNDAEL.
$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, '');
if (mcrypt_generic_init($cipher, $key256, $iv) != -1)
{
  // PHP pads with NULL bytes if $cleartext is not a multiple of the block size..
  $cipherText = mcrypt_generic($cipher,$cleartext );
  mcrypt_generic_deinit($cipher);
  // Display the result in hex.
  printf("256-bit encrypted result:\n%s\n\n",bin2hex($cipherText));
}
like image 27
Johan Avatar answered Sep 23 '22 03:09

Johan