168

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?

Anders
  • 64,406
  • 24
  • 178
  • 215
Radek
  • 1,783
  • 2
  • 11
  • 5
  • 3
    There really isn't a way to store it, at least not in a safe way, more information is needed to expand this comment. – Ramhound Mar 01 '12 at 17:28
  • 8
    Without secure hardware, I think you are out of luck. That is why it is most common to store a hash of a password instead of an encrypted version of a password. If you have secure hardware such as a TPM, you could use that. – mikeazo Mar 01 '12 at 18:16
  • 4
    For those who are looking for a key management solution for an application running in Amazon Web Services, [AWS Key Management Service](http://aws.amazon.com/kms/) (KMS) may be a good option. – Ville Jul 30 '15 at 22:07

4 Answers4

175

Here are your possibilities, roughly in decreasing order of sophistication.

  1. 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.

  2. Tie the encryption to your hardware. In theory HSMs do precisely this, only we tend to expect a bit more sophistication from an HSM than just hardware-backed crypto. But there are cheaper options available if you don't need the throughput and compliance that a true HSM brings to the table. TPM chips were invented in part for this purpose, and many examples exist showing how to integrate with them. Additionally, dedicated crypto hardware has become fairly inexpensive, and re-purposing devices like Open-Source U2F Keys for this is simpler than it sounds.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. Store the key in the database. Now you're not even trying. Still, a depressingly popular option.

Many cloud-based KMS solutions (e.g: AWS, GCP, Azure) when used most effectively will bind your encryption to your cloud VMs or environment. The unique identity of your VM is easy for the hypervisor to establish and assert, and the KMS uses the combination of that identity and the permissions you've assigned it to allow access to an HSM-managed encryption key. This is similar to a combination of options 1 and 2, modulated to account for the ephemeral nature of Cloud VMs. These KMS solutions generally also are compatible the platform's other identity mechanisms, effectively tying encryption keys to login keys; a lot like option 3.

tylerl
  • 82,225
  • 25
  • 148
  • 226
  • i'm dealing with this same issue, where i am trying to use encryption at rest, and i'm required to have the encryption key sitting on the filesystem. it might be ok if it was a temporary file that can only be read once, and supplied remotely on startup. the idea is to prevent a tar of the filesystem from being enough to recover the database. i looked into vault.io a while back for scenarios like this, but it just moves the problem around when connecting to the secret server requires... a private (x509 verify) key on disk. – Rob Jan 28 '16 at 15:55
  • 20
    As soon as you put your keys in an external service (opt 1 + 5), you then have the credentials to access those services in plain text on your server. So the problem is not solved, you have just created a new class of problems. How are these avoided? – Chris Seufert May 08 '18 at 03:48
  • 2
    @ChrisSeufert I agree this applies to option 1 but not completely to option 5, where, if someone captures the database, they can't decrypt the data without access to the server where the encryption takes place. The database doesn't point at the other server. – Ian Warburton Oct 11 '19 at 16:08
  • 4
    @IanWarburton this assumes that whoever managed to capture the database didn't do it from the webserver in the first place. But yes I can see option 5 is more secure than it all on one machine. – Chris Seufert Oct 14 '19 at 03:25
  • 6
    _Tie the encryption key to your admin login_ __NO__. You get fired, your account gets deleted as you've left, and gone is the encryption key, possibly leaving the data irrecoverable. Applications shouldn't hang on specific user accounts that are tied to actual people. You can tie it to a service account, but that's likely not really better than just storing it on-disk – Erik A Dec 02 '19 at 09:22
  • 5
    I don't really think any of them really solve the issue, they're just different ways of obfuscating how to get the key and slow an attacker temporarily. Consider the #1 option, suppose you have some service/app server which can make requests to the HSM to sign/encrypt/decrypt stuff, then getting into that server is basically the same as having the HSM private key, because you can send data to the HSM and have it sign/encrypt/decrypt anything you want. – hPNJ7MHTyg May 27 '20 at 01:59
  • 1
    @ErikA unless you know... it's YOUR data. – AwokeKnowing Jul 15 '20 at 15:04
7

I realize this was answered a while ago, but to give a couple of examples to Tyler's good answer:

  • I plan to use his #3 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 used it on two servers.

  • For his #5, 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.

bracco23
  • 123
  • 5
Mike
  • 408
  • 1
  • 5
  • 8
2

You can create two layer architecture for the key management.

  1. A key to encryp your data at rest encrypting the tablespaces,or column based.
  2. 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.

Hugo R
  • 177
  • 2
  • 11
    That's nice for centralised key management. But how does this support security? Since now you need to store e.g. your asw kms credentials to be able to reach aws kms. I am puzzled. I am [not the only one](https://security.stackexchange.com/questions/146330/how-to-use-aws-kms-securely). – musicformellons May 16 '18 at 11:13
1

What about segmenting the key into two parts and storing each segment on USB flash drives? On system startup the USB flash drives would be inserted into a physical box, combined, and stored in the application context.

user2782
  • 111
  • 2