I have some data that is symmetrically encrypted with a single key in my database. Rather than hard coding it into my code, I am looking for a safer way to store the encryption key. Where can I safely store it?
Here are your possibilities:
Use an external Hardware Security Module. There is an entire industry of products designed for offloading security-sensitive operations to external devices. This doesn't solve the problem so much as relocate it, but it relocates it to device that is far more secure, so altogether it's a security win. If you're doing anything high-stakes, then this is almost certainly going to factor into your solution.
Tie the encryption key to your hardware. TPM chips are useful for this, as are USB security tokens (not flash drives, though). In this case, crypto only works on that specific piece of hardware, but isn't otherwise restricted. It's a bit like the kid-sidekick version of the HSM mentioned above. Google's recently-announced Project Vault takes this a step further by making a high-bandwidth HSM embeddable into even the smallest consumer devices.
Tie the encryption key to your admin login (e.g. encrypt the the encryption key with your admin login). This is only marginally useful as it requires you to be logged in in order to encrypt/decrypt anything. But on the plus side, no one can encrypt/decrypt anything unless you're logged in (i.e. greater control). Much of the secure storage in Windows works like this.
Type in the encryption key when you start up, store it in memory. This protects against offline attacks (unless they capture the key out of RAM, which is tougher to do). Similar to the option above, but also different. However, the server boots into an unusuable state, requiring you to manually supply the key before work can be done.
Store the key on a different server. E.g. put the key on the web server and the encrypted data on the database server. This protects you to some degree because someone would have to know to grab the key as well as the database, and they'd also have to have access to both servers. Not amazingly secure, but an extremely popular option anyway. Most people who think they're doing it right do it this way. If you're considering doing this, then also consider one of the first two options mentioned above.
Store the key elsewhere on the same server. Adds marginal security, but not a whole lot. Most smaller operations do this -- they shouldn't, but they do. Typically because they only have one server and it runs in some cloud somewhere. This is like taping a key to the door instead of leaving it in the lock; guaranteed to stop the most incompetent of attackers.
Store the key in the database. Now you're not even trying. Still, a depressingly popular option.
I realize this was answered a while ago, but to give a couple examples to Tyler's good answer: I plan to use his #1 to tie a password to a service account and use a Powershell cmdlet to grab it. That way the scripts do not need to be as heavily modified. The service account's password is in Active Directory and would have to be compromised first. This works for me since I have use it on two servers. For his #4, to meet our compliance we were able to store a key in plain text on another server with external storage because that storage was itself encrypted and access to it restricted. As Tyler mentions the latter doesn't seem so secure, but it was good enough even for a tough assessor.
You can create two layer architecture for the key management.
- A key to encryp your data at rest encrypting the tablespaces,or column based.
- Master key to unlock 1.
for your master key(s) use one of one of the established key management solutions such as:
- Amazon AWS KMS
- Oracle Vault
- Microsoft MKS.
- or open source ones.
Just keep in mind that your key manager has to support equal or higher availability than your infrastructure where the managed key are used.