Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing encryption keys -- best practices?

I have a web application that uses a symmetric encryption algorithm.

How would you store the secret key and initialization vector? Storing as a literal in the code seems like a bad idea. How about app settings? What is the best practice here?

like image 368
BC. Avatar asked Apr 06 '09 23:04

BC.


People also ask

How should encryption keys be stored?

The encryption key is created and stored on the key management server. The key manager creates the encryption key through the use of a cryptographically secure random bit generator and stores the key, along with all it's attributes, into the key storage database.

Where should private keys be stored?

A CA's private key should be stored in hardware-based protection, such as a Hardware Security Module (HSM). This provides tamper-resistant secure storage. A Private key for an end entity could be stored in a Trusted Platform Module (TPM) chip or a USB tamper-resistant security token.

What is the normal way of managing cryptographic keys?

Keys must be protected on both volatile and persistent memory, ideally processed within secure cryptographic modules. Keys should never be stored in plaintext format. Ensure all keys are stored in cryptographic vault, such as a hardware security module (HSM) or isolated cryptographic service.

What is a best practice of key management solution security?

Best practice is to utilize a hardware security module (HSM) to store keys, as these provide very strong physical and logical security protection and are typically validated to the NIST FIPS 140-2 security requirements for cryptographic modules.


2 Answers

One standard approach in the webapp world is to split the key and put it in different places. E.g., you might split the key and put part of it in the filesystem (outside of the 'webapps' directory), part of it in the JNDI configuration (or .net equivalent), and part of it in the database. Getting any single piece isn't particularly hard if you're compromised, e.g., examining backup media or SQL injection, but getting all of the pieces will require a lot more work.

You can split a key by XOR-ing it with random numbers of the same size. (Use a cryptographically strong random number generator!) You can repeat this process several times if you want to split the key into multiple pieces. At the end of the process you want, e.g., three partial keys such that p1 ^ p2 ^ p3 = key. You might need to base64-encode some of the partial keys so they can be stored properly, e.g., in a JNDI property.

(There are more sophisticated ways to split a key, e.g., an n-of-m algorithm where you don't require all of the pieces to recreate the key, but that's -far- beyond what you need here.)

If you can require the user to actively enter the password, there are PBE (password-based encryption) algorithms that convert a password to a good symmetric key. You want to find one that requires an external file as well. Again it's a case the tape backups or the password itself isn't enough, you need both. You could also use this to split the password into two pieces with JNDI - you can use a plaintext passphrase in JNDI and an initialization file somewhere in the filesystem.

Finally, whatever you do be sure you can 'rekey' your application fairly easily. One approach is to use the password obtained above to decrypt another file that contains the actual encryption key. This makes it easy to change the password if you think it's been compromised without requiring a massive reencryption of all of the data - just reencrypt your actual key.

like image 164
bgiles Avatar answered Sep 29 '22 11:09

bgiles


Is it possible for you to enter a password interactively whenever the application starts up? That way you don't have to store the key, or at least any keys (whether they are symmetric or private keys) can be encrypted with this "bootstrap" password.

If not, store your secret key in a file by itself and modify its permissions to make it accessible only to the user running the web application.

These approaches are platform-agnostic. For more concrete suggestions, information about your platform would be helpful.

By the way, an initialization vector should be used for only one message. And IVs do not have be kept secret, so you could store it anywhere, but storing it with the one message that uses it is customary.

like image 24
erickson Avatar answered Sep 29 '22 12:09

erickson