2

I'm building an app and a server. The server is a node.js API with a Postgres backend.

Images created in the app will be stored at Amazon S3. Metadata about the files will be stored in Postgres.

I have zoomed in at two possible solutions for encryption keys. Both involve Amazons Presigned URLs. These URLs are generated by Amazon as a result of a call from my server.

  1. Photo taken in app
  2. File metadata saved to Postgres via my API
  3. The server gets presigned URL from Amazon for uploading the files
  4. The URL is given back to the app as a result of the call in step 2.
  5. The app uses the URL to post the file to Amazon S3

As for the file encryption I could choose to use Amazon Key Management Service (kms), i.e. Amazon generates and keeps track of individually salted encryption keys for each file. My server would need to use the master key to get the presigned URLs generated.

Or I could choose to generate individual encryption keys for each file at my server and store these keys with the rest of the metadata in Postgres. Amazon would still do the encryption/decryption, but I would pass each individual key in the request for presigned URLs instead of passing the master key.

KMS, pro:

  • No encryption keys stored with the file metadata in Postgres

KMS, con:

  • The master key unlocks every file at S3 (but the master key can be rotated)

Custom generated keys, pro:

  • Easier to implement an extra user key by XOR:ing the keys. If a client won't trust my key handling they could add an extra key which only exists on the device, probably in the iOS key chain.

Custom generated keys. con:

  • If the Postgres database is compromised, the files at S3 might also be compromised.

I'm a programmer, not a security expert. If I need to I will consult an expert, but I thought that the experts on this forum might be able to give some more insight first.

Of course other security measures have been taken. The app only talks to the API via HTTPS and the app is authenticated with the API (using Oath2 and JWT).

I really like the presigned URL concept, as this alows the app to be clueless of any keys needed for S3 upload/download.

Should I use kms or generate keys myself?

Thanks!

user
  • 7,670
  • 2
  • 30
  • 54
Michael
  • 177
  • 6
  • 2
    What's the *question?* – user May 31 '17 at 14:10
  • Should I use kms or generate keys myself? – Michael May 31 '17 at 14:11
  • 2
    What is the reason for data encryption? – Fis May 31 '17 at 14:14
  • Most clients want to hear that their files are encrypted. Some files are actually sensitive for real (floor plan blue prints). – Michael May 31 '17 at 14:16
  • If it is like that I would go for cheaper solution. You correctly stated cons and pros of both methods. You should know what you want the data protect against. I can also see third option. To store data encryption key with encrypted with the KMS key in the DB so basically combination of both methods. – Fis May 31 '17 at 14:17
  • Sorry, edited too many times: I can also see third option. To store data encryption key encrypted with the KMS key in the DB so basically combination of both methods. You would not need to use so many KMS keys, one can be enough. Then you decrypt the data encryption key then you decrypt the data with decrypted data encryption key :) – Fis May 31 '17 at 14:25
  • ok, but why would I need KMS for this? To encrypt my encryption keys stored in Postgres I only need a master key that's known by my server. Probably a good idea. Upside with kms would be that I can rotate the master key, but this would lead to non-decryptable keys in the database as these keys are decrypted with an old kms master key. I might have misunderstood, though.. – Michael May 31 '17 at 14:30
  • I just thought you would use KMS as a secure key encryption key store. Its better to have the key there only than somewhere in config. – Fis May 31 '17 at 14:31
  • I didn't work with KMS but isn't it same as HSM? So you store key there and you can't get it out from there anymore? And then you just pass data to be decrypted / encrypted there? On other hand, if it is like that it will not probably be cheap correct? – Fis May 31 '17 at 14:33
  • Yes, KMS is a closed store for keys. Only accessible by Amazon for encrypt/decrypt files. I suppose could store keys in an encrypted file if I want to use kms as a key store. But I want to keep complexity down. If it get complex enough the files might be at risk because of me loosing track of the keys.. – Michael May 31 '17 at 14:36
  • I thought you will use just one key in KMS so called Key Encryption Key. Then you will generate some data encryption key which you would use to encrypt the data. Then you encrypt this data encryption key using KMS and store the encrypted data encryption key in database together with the data. If you will need to acess the data you simply will get both, encrypted data and encrypted data encryption key from the DB then you ask KMS to decrypt the data encryption key then you decrypt the data using decrypted key then you securely release it from memory. But there will be only the one KEK in KMS. – Fis May 31 '17 at 14:40
  • 1
    This has just one problem. When you will wish to change KEK in KMS you have to re-encrypt all DEK's in the DB. If you just want to keep it simple and cheap just avoid the KMS and store KEK in application config. – Fis May 31 '17 at 14:41
  • Let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/59621/discussion-between-fis-and-michael). – Fis May 31 '17 at 14:42

2 Answers2

2

Just to summary the discussion:

you need to know what kind of attacks you want to protect keys against. As we discussed you correctly mentioned pros and cons of both solutions.

I recommended to mix them up so you will use two keys - KEK (key encryption key) and DEK (data encryption key). You will have just one KEK and as many DEKs as of data stored in the database.

When you will be storing the data to the DB you will generate DEK, encrypt the data with the DEK, encrypt the DEK with KEK and store the encrypted DEK together with the data in the database. For reading, you will get data and encrypted DEK from the DB, you use KEK to decrypt DEK and DEK to decrypt the data.

DEK is supposed to be used only in memory of the application. It should not be never stored unencrypted anywhere else. And you should take care of its secure disposal from the memory immediately once it is not needed (i.e. rewrite byte buffer with zeroes and release it - be careful about strings as those are usually immutable).

The correct way of storing and using the KEK should be storing and using it inside of the HSM (KMS) in order it can't be revealed by somebody, even by server / application administrators.

The dark side of it is probably the AWS KMS price. If you would store it in config it can potentially stolen by attacker and later used decrypt the database dump. But ye, you are probably not securing an army site ;)

It is also necessary to mention that if you will ever need to change the KEK you have to re-encrypt all DEKs stored in the DB.

Fis
  • 1,200
  • 7
  • 10
  • Thank you for the summary and the discussion. I want to clarify that I actually won't need to encrypt/decrypt. I just hand over the decrypted DEK to Amazon and get a temporary url to the file including decryption. This url can be easily used in other places in need of the files, for example a report generator. The URLs have an expire time (15 minutes is default) – Michael May 31 '17 at 15:02
0

Revisited.. posting an answer myself as well.

Short answer: I'll go with KMS.

After reading up some more on KMS it actually seems to fit my needs very well, and it's not expensive at all. We already use S3 for file storage and we will use AWS for our production environment when we are ready, so it's easy to add KMS to the setup. I will also let KMS handle other secrets as well, i.e. no more secret config files.

I was afraid that KMS would make it more complicated, but it's actually really easy to work with.

I was also afraid of the price. I thought it would be priced like an HSM, but it's way cheaper.

I'll leave some links here for others to find, should they be in the same situation as me. Unfortunately I don't have enough reputation to be able to post more than two links, so I'll post some of them without the https:// prefix.

Overview:

Price:

I'll probably handle this from within Node.js:

  • github.com/DavidTanner/nodecredstash

Also easy to use from command line:

  • github.com/fugue/credstash

Enlightening reading if you need beginners info as i do:

  1. blog.threatstack.com/cloud-security-best-practicesfinding-securing-managing-secrets-part-1

  2. blog.threatstack.com/cloud-security-best-practices-finding-securing-managing-secrets-part-2

Michael
  • 177
  • 6