5

I'm looking to create a system where a lot of the data is encrypted within the database. The encryption method will be a currently accepted strong algorithm.

To access this data, a user would need to log in and then the data will need to be decrypted with some key. There will be many users who should all have access to the same data.

I don't want to store this 'master' key in the source code (PHP), on disk, or anywhere else in plain text.

So, I thought I could encrypt the 'master' decryption key with each users' own password and store it alongside their user record. Upon login, they get the decrypted master key, which is then available in memory for them to decrypt the application data.

My initial concern is that if there is a data breach of source code and data, then an attacker would see that the same key was encrypted many times (once for each user). Could this then reduce the security of the 'master' key? Either by patterns in the encrypted data or by testing that a decryption attempt on one record matches that of another?

Or, am I simply barking up the wrong tree and there is a better method already out there?

schroeder
  • 123,438
  • 55
  • 284
  • 319

3 Answers3

4

You are describing a few different problems.

Storage of credentials and other secrets

I don't want to store this 'master' key in the source code (PHP), on disk, or anywhere else in plain text.

You are correct that hardcoding secrets is a bad idea, you may want to try using something like hashicorpo-vault (This particular article may be related to your workflow as well) or a Key management service like Amazon KMS.

Multi-user Encrypted Access

There are a few different strategies to this type of setup. You can encrypt the data with a shared key and then encrypt that key for each user using the user's public key. You would then need to update the per file key and re-encrypt with each user's public key again if there was any change in the access group's membership.

Deriving a key based on the password can be complicated because you need to ensure you properly update all of the keys and redo all the encryption if the user's password changes.

You may want to look at MIT's Mylar project, as it tries to accomplish something similar to the storage and access model you described.

Breach scenario

My initial concern is that if there is a data breach of source code and data, then an attacker would see that the same key was encrypted many times (once for each user). Could this then reduce the security of the 'master' key?

If you are ever decrypting server side and the attacker has access they can grab the decrypted copy of the data.

If you are creating user's private keys using the password as the seed then you have some risks especially if the passwords can be identified by stealing them or reversing the hashes.

More Generally

Could this then reduce the security of the 'master' key? Either by patterns in the encrypted data or by testing that a decryption attempt on one record matches that of another?

I believe you are asking if encrypting the same value with multiple different per-user keys would make it easier to get back to the original plaintext value (?).

If you happen to know the plaintext value you may be able to figure out the other encryption values. This is known as a "known plaintext" attack. However, this does not mean it works if you just happen to know two different encryption outcomes and know the input was the same, but you don't know the actual input.

Your question may also be that given encryption function f(key, masterkey) and then running it once with key1 and then with key2 would comparing the two outcomes allow you to figure out masterkey or would knowing the output of f(key1, masterkey) allow you to figure out key2?

It may be possible, but would depend on the specific algorithms, if there is padding, etc. If there is significant entropy in the algorithms then slight changes in inputs should give very different outputs that do not show patterns. You may also want to read up on "weak keys" and chosen-plaintext attacks.

Eric G
  • 9,691
  • 4
  • 31
  • 58
  • Thanks Eric G, some good points to look into. Yes, my original concern was whether it would be easier for an attacker to determine the master key, having figured out that it was encrypted and stored and many times with the same algorithm, albeit different keys – Chris Rutledge Jan 05 '18 at 22:03
2

What's important to look at in a hypothetical like this is where your weak-points are, and what a breach of that will mean.

So in this case, we have a very strong master decryption key.

Obviously, we are storing this encrypted with something Sufficiently Strong (TM).

Now we come to the worlds oldest cryptographic weakness of user passwords. Say you have 1000000000 users. All of them are security/comp sci PhDs who've written dissertations on good password management. One is Jim. Now, Jim is the owner's son. When it comes to security savvy he's about a 3 watt. His password is passworddrowssap, and he thinks he's very clever for thinking of that.

Some day your database gets breached. Exfiltrated off-site, no less. They throw all of the User_tbl data into hashcat and go away for a few hours. They come back to one breached password - Jim's. Now they can decrypt the master key using Jim's password. Now they have complete access to all the sensitive, encrypted data in the database. Thanks, Jim.

Your solution isn't terrible, and I can't think of a real good solution, but it offsets all of the database security down to the weakest password your users use.

  • So, lets say I don't store the user's password in the database, so there's no list of hashes to be send off to hashcat (see answer at https://security.stackexchange.com/questions/23409/how-to-login-and-encrypt-data-with-the-same-password-key/176795#176795)? I concede that the encryption of the password is still available to the attacker and that there maybe a similar service to try to decrypt...but I'm guessing this would take longer than guessing/computing hashes? – Chris Rutledge Jan 05 '18 at 16:15
  • @ChrisRutledge Assuming you're properly using a KDF like PBKDF2 then decrypting something with the key is not nearly as expensive as the key derivation. Idk if hashcat would support it but it probably wouldn't be very different performance-wise vs just comparing the hash directly. – AndrolGenhald Jan 05 '18 at 17:41
0

DISCLAIMER: I'm not even "hobbyist" level in this, more of a "n00b". I'll let the more experienced comment further..

Also, I'm more providing what I would do as a solution to the original problem, because I don't think the original solution offered is very secure (which was more aligned with what was asked--"is it secure?"--to which I can only answer "probably not". (Encrypting the same plaintext with different keys may allow analysis to obtain too much insight in to finding an attack vector to decrypt the data).

There are a couple concerns here.. First, the possibility of a key itself becoming compromised; and Second, the possibility of the data it's protecting becoming compromised. The second case, there's little that can be done to protect against, since once the data is compromised, an attacker doesn't even need to decrypt it against another's key--they have already obtained the target goal. So I won't say much more about the second case.

For the first case, a compromised master key would compromise any and all data that it was used to encrypt, not just the one document. So you want to isolate that possibility. What I understand from methods such as PGP/GnuPG, the passphrase is NOT the master key. Rather, a OTP (one time password) is randomly generated for X-number of bits, which is then used to encrypt the data, for only that one document. So even if an attacker can obtain that random key, only the one document and OTP key is compromised, not all documents or keys.

So, in the server, you generate a OTP using a high amount of random entropy to make it very difficult to use crypto-analysis to obtain the random key, since there should be no patterns in the key data. This key is then used to encrypt one specific document. The document can then be stored in the database in an encrypted form using that OTP as the encryption key. Nothing further needs to be done with that.

Of course, you don't want to store the OTP in the database, as that would be futile storing the key with the encrypted data. Instead, you encrypt the OTP with your master key that you never store anyone but your own head. Then you can store the encrypted OTP safely in the database, since the encrypted OTP still needs to be decrypted in order to decrypt the stored document.

Now, let's add in access to the document for other users.. You do the same process for them with their passphrase! Never encrypt YOUR master key with their passphrase, because that would compromise your entire key and anything it was used to encrypt. Instead, use the user's passphrase (password) to encrypt the OTP ONLY, and store that result in the database. So when they want to access the document, they first have to pull the encrypted OTP from the database, use their password to decrypt it so that it can be used to decrypt to target document. Since your master password is never part of that, they will not be able to obtain your master password. They might be able to crack a weak password from one user, but that will only enable them to obtain the decrypted document (the second case I mentioned that is already fruitless should that happen). It won't help them discover other user's passwords, nor help to discover your master key.

Likewise, since the OTP was used only once to encrypt just that specific document, it won't compromise other documents which have a different OTP.

You won't have to store multiple encrypted documents for each user using each user's key, which MIGHT weaken the encrypted document by having multiple encrypted data to analyze; You only need to store the OTP encrypted document once, and then store a "certificate" (the OTP which is encrypted individually with each user's personal password) which is used to decrypt the actual target document.

To make a similar "real life" scenario, consider a bank lock box, but the bank itself keeps the keys to the lock box in a secured storage area, and only a bank guard can retrieve the key. All you need to do is show the guard you are authorized to access the lock box (showing your ID or something), and once they authenticate your access rights, they get the key and give it to you so you can open the lock box with it. But they will never give you the key to the key storage area itself (the "master key"), but rather, they will go get the lock box key on your behalf. It's not an exact parallel scenario, as you can always not return the lock box key, etc. But you never have access to the master key to risk compromising all the lock box keys in storage; Only that specific one.

I hope I'm being clear--AND correct. If not, hopefully the more experienced will refute, edit, and/or correct as necessary.

C. M.
  • 149
  • 1