1

This Question has been reposted from StackOverflow according to the suggestion given in comments

I am creating an application where I need to store client's information(Like their API Keys and API Secret to access my service, along with other confidential information).

Now, in the database, I want to store these in the encrypted format. In this regard, I decided to with symmetric key cryptography, AES in specific to encrypt the details.

However, for security purposes I want to use a different AES encryption key on a per client basis, so that even if the DB is compromised, all the data cannot be decrypted using a single key.

However, due to obvious reasons, I do not want to store my private keys in the DB with the encrypted informations.

So, I cannot seem to decide how to store my keys, especially since I need to have a binding that which key belongs to which client.

How can I achieve this, and which is the best approach in scenarios like this?

Ayush Gupta
  • 113
  • 4
  • For something like an API key, is there any reason you can't store it hashed? And why is an API key confidential user information anyway? I assume it is randomly generated and only used for authentication. – forest Dec 30 '17 at 04:17
  • I can store it hashed yes, but to hash it I want to use a different hashing key/salt per user. – Ayush Gupta Dec 30 '17 at 04:20
  • Hashes do not use keys. You just hash the salted secret. You obviously won't be able to access it at runtime, but you don't need to. You just need to compare the hash of the inputted secret with the stored hash of the known good secret. But do you really need to do this for API keys? They are not secrets submitted by the users, so are not the same class of sensitivity as password. They are already (presumably) random, anyway. – forest Dec 30 '17 at 04:24
  • Not the API Key, but I am thinking of using the API Secret as a salt(or encryption key depending on the mechanism I go by) for encrypting the other information, so I think it would be better if I could. – Ayush Gupta Dec 30 '17 at 04:27
  • You should use a unique, random salt, not the API key. What other information do you need to protect? Things like passwords should be hashed, with the random salt saved next to the hash (e.g. $hash:$salt). – forest Dec 30 '17 at 04:30
  • 4
    Your question is very similar to [Where to store a key for encryption?](https://security.stackexchange.com/questions/12332/where-to-store-a-key-for-encryption) and other questions asking [where to store key for encryption](https://www.google.com/search?q=site%3Asecurity.stackexchange.com+store+key+for+encryption). I thus consider it a duplicate. – Steffen Ullrich Dec 30 '17 at 05:12

1 Answers1

2

This is one situation where using a KEK (Key Encrypting Key) and multiple DEKs (Data Encrypting Keys) comes in useful. (Background question here).

What you would do is encrypt each client's key (these will be the DEKs) using the KEK. The DEKs are stored (encrypted) in the database. When the application starts up, it uses the KEK (which is not stored in the database) to decrypt the DEKs, then the (decrypted) DEKs (which exist decrypted in the App, not in the Database) to perform crypto operations. When the App shuts down the DEKs are all safely encrypted in the database, waiting for the KEK to unlock them again.

This model can allow you to separate the keys (DEKs in the database, KEK on an application server file), to require manual intervention (KEK provided to App at start-up time), or to rely on an HSM for the KEK. All of these provide more security than simply stuffing client DEKs into the database without protection.

gowenfawr
  • 71,975
  • 17
  • 161
  • 198