Search code examples
securityencryptionauthenticationcryptographysymmetric-key

Storing symmetric key for rest of the database while encrpted in the database itself


Following up on my question here I now need to store the symmetric key safely. After reviewing options it sounds like this may be a good option:

Set up:

There is a table in the DB that has two fields

php_key - stores a symmetrically encrypted symmetric key that is used for OTHER tables
php_key_hash - stores a hmac of the symmetric key

other tables (as mentioned in other post):

last_name - symmetrically encrypted value encrypted with key after being unencrypted from php_key
last_name_hash - hmac of last_name

Login/Safe guarding of key:

1) The user logs in - (unrelated) user/pass is just stored in the DB (pass is a hmac)

2) After logging in the user is presented with a screen where they have to enter another password - this password would be shared with all employees of the company (only 5 employees so easy to remember). Lets call this key1.

3) That password has hmac performed and is compared to the php_key_hash in the DB.

If it fails I can just error the user here.

4) If it matches then pull down php_key, decrypt it using the same password, store it in session variable.

At this point the key is stored in memory on the server and will be destroyed when the user logs out. Lets call this key2.

After this normal decryption of fields occurs as in the other post

This seems really secure to me because

1) key2 is stored on a different server than the web server

2) key2 is itself encrypted - it's never stored in plain text

3) The key1 is located no where in the code or the file system or in the db - it's only known in the minds of the employees

4) You have to login to the site basically twice (one with your login, again with key1)

5) The use of session variables means key2 is only stored in memory and only on the server and is destroyed after the session ends

6) I can just re-key key1 at any time if we need to change the passphrase - for example if an employee leaves or we think it's compromised

Potential Problems AKA My Questions (finally)

First, I'm by no means a security expert hence why I would just like the opinion of someone who is better than me at security :)

1) I'm potentially storing an encrypted symmetric key (key2) in the same database where it would be used to decrypt other fields. I don't think this is an issue since it itself is encrypted?

2) Storing the symmetric key (key2) in the session variable - potential problems with people surfing RAM? Perhaps it would be better just to store key1 in a session variable and then have to go through the double decryption every time (but probably slow)? Am I being over cautious?


Solution

  • OK I think I now understand what you mean. I assume you mean:

    key1 = PBKDF2(password, salt, many_iterations)
    php_key_hash = HMAC(key1, salt)
    

    When you say HMAC for password, I assume you mean PBKDF2 with many iterations (e.g. a few seconds). Anyway, to answer your 2 questions:

    1) Saving key2 encrypted right next to the data encrypted by key2 is OK. In fact AWS KMS works this way, except that they use a different key2 for every encryption. If one key2 is compromised, only its corresponding data would be compromised (not the whole database). And it makes key rotation simpler.

    2) If you keep key1 in RAM instead of key2, that would not help: if someone manages to get key1 from RAM, you can probably assume they have access to php_key from the database also and will be able to decrypt key2. If you want to prevent this problem and don't want the keys in RAM, you should consider an HSM (and key2 in plain would never leave the HSM). Without an HSM, key2 would have to be in RAM at some point.