I am new to AES encryption but trying to build a solution which:
- Accepts consumer data
- Encrypts that data using AES and a
“public” key - Store that data in a MySQL database
- Have the ability to pull and decrypt
the data ONLY with a private key
(stored on my personal machine, not
the server itself).
I realize this may be overkill but want to be overly protection for my consumer data.
A few things to note:
- This is not credit card information
so please don’t write telling me
about PCI-DSS, it is other form of
personal information all under 500
characters in length for each field. - I may store pieces of the consumer
information and others in a second
database tied together by a unique
member ID for additional security. - Incoming MySQL calls can only be
made to my server directly from my
static IP. - SSH root is disabled, ports changed,
and so on so I feel my server is in
faily good shape to prevent any
“basic” misuse.
I have looked for articles online and SO but have not found much in terms of keeping the private key off the server completely. Even if I need to keep on the server itself – thoughts or suggestions for how to move forward are appreciated.
EDIT – CLARIFICATION
Just to be more clear, the goal I am trying to achieve is this (in very basic form):
-
Customer enters his/her phone number
online. -
The phone number entered is encrypted
online using key A and stored within
the mysql db -
The customer will never be able to
see the full phone again at this
point, but can certainly update it
(going through key A process a nth
time) - As a system administrator, I am only able to access the data by either downloading and decrypting the data on my local machine (that or I must first upload a temporary file which is used to then decrypt the data I need).
EDIT 2 – I’m a an idiot
I am using Andrew Cooper’s response below but am having trouble getting my script to read the contents of the .pem file I generated. Based on the code below – how would I get $public key to correspond to a specific .pem file on my server?
<?php
if (isset($_SERVER['HTTPS']) )
{
echo "SECURE: This page is being accessed through a secure connection.<br><br>";
}
else
{
echo "UNSECURE: This page is being access through an unsecure connection.<br><br>";
}
// Create the keypair
$res=openssl_pkey_new();
// Get private key
openssl_pkey_export($res, $privatekey);
// Get public key
$publickey=openssl_pkey_get_details($res);
$publickey=$publickey["key"];
echo "Private Key:<BR>$privatekey<br><br>Public Key:<BR>$publickey<BR><BR>";
$cleartext = '1234 5678 9012 3456';
echo "Clear text:<br>$cleartext<BR><BR>";
openssl_public_encrypt($cleartext, $crypttext, $publickey);
echo "Crypt text:<br>$crypttext<BR><BR>";
openssl_private_decrypt($crypttext, $decrypted, $privatekey);
echo "Decrypted text:<BR>$decrypted<br><br>";
?>
EDIT 3 – maybe not ‘idiot’ but semicolons hate me
I had a semicolon misplaced. I am using the function: file_get_contents() but is there a more preferred method of reading in the data for the .pem file?
You should be able to generate the public/private key pair on your personal machine, and then publish the public key in your app so the data can be encrypted. In this way the server never sees the private key, and if the server is hacked the data is still safe.
You’ll want to make sure the whole transaction occurs over SSL. The client side can generate a random session key, encrypt the data with that key (using AES), then encrypt the key with the public key from your app (using RSA), and send the encrypted data and key to the server. You could store the whole blob in one database field or two. The only way the data can be decrypted is to decrypt the key first, and the only way that can be done is by using the private key on your personal machine.
Update
Check out http://plugins.jquery.com/project/jQuery-Gibberish-AES. It’s a JQuery plugin that appears to allow this type of scenario. I have no experience in using it, but it appears to me to be a good start.
New Update
Just to be clear about what I’m suggesting, and to address your edit:
You can’t use only AES encryption. With AES there is one key that is used both to encrypt and decrypt. The key would have to exist wherever the encryption operation occurs, either in the client code, or on the web server. In the first case anyone can get your key. In the second case, if the web-server is compromised, then the key, and the data, are also at risk.
The solution is to use good, strong AES encryption in combination with public-key crypto (RSA). I’d suggest doing to the crypto on the client-side, for reason I’ll outline below. Here, though, are the steps I’d suggest:
You now have encrypted data in the database that can only be retrieved using the private key stored on your private machine. Even if the user somehow manages to capture the session key while it’s in the clear on his machine, the worst that can happen is that that one record could be decrypted.
The reason I’d suggest this client-side approach is that it means that your server never see the encryption keys in the clear. If the same scheme where employed on the server-side then, theoretically, an attacker could be sitting on your server watching it happen. At the end of the day it basically comes down to how paranoid you want to be.
Following this scheme, when you want to retrieve the data you’d dump the required data, in encrypted form, from the database to your private machine. The for each chunk of encrypted data:
Anyway, that’s the approach I’d suggest. I’m sure there’s libraries out there to handle this.