70

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?

lc.
  • 113,939
  • 20
  • 158
  • 187
BC.
  • 24,298
  • 12
  • 47
  • 62
  • 4
    This is not a trivial question. You might want to review this abstract by several security experts to put this question into perspective: http://www.schneier.com/paper-key-escrow.html – Dan Esparza Aug 26 '13 at 16:52

7 Answers7

62

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.

bgiles
  • 1,200
  • 11
  • 12
12

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.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • @BC Here is an RFC on password based cryptography that might be interesting, but they are a little stuffy reading: http://www.ietf.org/rfc/rfc2898.txt @erickson LOL you have your public key in your about me block. – AaronLS Apr 07 '09 at 00:04
  • On a non technical note... to make it even more secure the password that is interactively entered should be chosen or distributed to two (or more) people or physical locations. This will mean no one person knows the password. This is useful in situations where you think social engineering / corruption / bribery is a consideration. – Andrew Aug 22 '11 at 17:10
6

I have used an approach where my application requires a symmetric key when it starts and looks for it in a certain file. Once the application has started up I remove the file. A copy of the file is kept remotely for any required restarts. Obviously this approach is not viable if your applciation has frequent restarts.

Another alternative would be a certificate manager such as the Windows Certificate Store. It can store certificates and their keys securely and it's also possible to mark private keys as non-exportable so it would require some serious hacking to get the key out. Your application could load its certificate from the Certificate Store and be able to call operations to sign requests or generate new symmetric keys. In addition you can assign permissions to different certifcate stores so that only certain privileged accounts would be able to access the certificate.

sipsorcery
  • 30,273
  • 24
  • 104
  • 155
4

stick it in the web.config and encrypt that section

This SO question talks more about web.config encryption

Community
  • 1
  • 1
roman m
  • 26,012
  • 31
  • 101
  • 133
  • 19
    if you encrypt the web.config, where are you going to store they key to decrypt the web.config? – Kirby Apr 16 '13 at 21:55
2

This should help ...

http://msdn.microsoft.com/en-us/library/ms998280.aspx

But, you really should consider going to PKI if you are serious about protecting your data.

JP Alioto
  • 44,864
  • 6
  • 88
  • 112
  • 1
    When using PKI, how and where do you store the private key? – Dan Bechard Dec 10 '14 at 16:54
  • 4
    Exactly! You still have a key storage problem whether you use PKI or symetric key encryption. So PKI doesn't make it a better solution when the same system or party needs to encrypt and decrypt the data. – swbandit Feb 26 '15 at 17:48
0

We have a slightly different, but related issue. We have keys generated every few days, and when decrypting, we have to try all our keys because we do not know which day the encryption took place. What we did was to encrypt the keys one more time and store them as secretes. This way, we only have one set of keys to manage.

Jie
  • 1,107
  • 1
  • 14
  • 18
0

For secure storing of encryption key you can use KMS service of AWS. Please use this service for storing such confidential keys. PFB url for kms service. documentation : https://aws.amazon.com/kms/

Onkar Kale
  • 11
  • 2