Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP, MySQL, and AES Encryption / Decryption for User Data

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:

  1. 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.
  2. I may store pieces of the consumer information and others in a second database tied together by a unique member ID for additional security.
  3. Incoming MySQL calls can only be made to my server directly from my static IP.
  4. 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?

like image 813
JM4 Avatar asked Feb 26 '23 23:02

JM4


2 Answers

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:

  1. On your private machine create a public/private key pair, and keep the private key safe.
  2. Put the public key somewhere in the code you send to the client.
  3. When the user submits the form the client code:
    1. Generates a random AES key (the session key)
    2. Encrypts the form data
    3. Uses your public key, and the RSA algorithm, to encrypt the session key
    4. Discards the plaintext session key
    5. Sends the encrypted form data, and the encrypted session key to your server
  4. Your server accepts the encrypted form data, and stores it, along with the encrypted key, in the database.

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:

  1. Decrypt the session key using the RSA algorithm and your private key
  2. Decrypt the data using AES with the session key from step 1.

Anyway, that's the approach I'd suggest. I'm sure there's libraries out there to handle this.

like image 166
Andrew Cooper Avatar answered Mar 07 '23 20:03

Andrew Cooper


Encrypts that data using AES and a "public" key ... decrypt the data ONLY with a private key

But AES is a symmetric encryption algorithm - i.e. the same key is used for encryption and decryption.

Or do you mean you want to implement something like SSL, where some assymetric algorithm is used for encrypting a randomly generated key then the end points use that key for a symeetric algorithm? This kind of approach is only of benefit where the data to be encrypted is significantly larger than the keys used - is that the case here?

Have a google for PHP and RSA or ELGamal for assymmetric encryption algortihms. (note it'll probably be significantly faster and easier to program if you shell out to something like GPG to do the encryption - there are wrappers on phpclasses for this).

C.

like image 26
symcbean Avatar answered Mar 07 '23 21:03

symcbean