4

I'm developing a server (Java + Spring) and I want to encrypt users' sensitive data on the database, using a key that's specific for each one.

I thought of encrypting the user's data using their password as a base for the key but...

  1. I'm only storing hashed (bcrypt) passwords on the database
  2. User only sends the password to the server when creating their account and logging in. For request authentication it's using JWTs (only containing the user Id, with a strong secret and a low expiration time) generated after each login.

I thought of storing the password as plain text on the database but that leads me to the same problem, if the db gets compromised, an attacker could easily decipher user's content.

Is there any way to accomplish this?

Alex Probert
  • 493
  • 1
  • 3
  • 17
alex
  • 41
  • 4
  • Little broad to answer on here. You might be best googling and reading up on the wider topic of securing data at rest. You should find ideas that way if your knowledge is indeed basic, as you say, I would suggest speaking to someone who has more experience as well. – ISMSDEV Nov 13 '17 at 14:45
  • 1
    If the data is encrypted with a key based on the user password, it will be definitively lost if a user forgets her password. Whether it is desirable or not is another question... – Serge Ballesta Nov 13 '17 at 15:41
  • @SergeBallesta I'm okay with that. For instance, Firefox Sync does it that way. When a user forgets the password their data is lost. I'll take a look at the source code – alex Nov 14 '17 at 10:02

2 Answers2

2

One option is to generate the users key from their password at login (or store randomly generated keys encrypted with it). This is then stored in memory while they are logged in and wiped from memory on logout / session expiry.

There are still issues here -

  • How do you enforce wiping the key on session expiry? - an action occurring here isn't usual server workflow.
  • You need to take steps to prevent the keys being paged out to disk.

Another option is to encrypt/decrypt at the client side using something like the WebCrypto API.

Hector
  • 10,893
  • 3
  • 41
  • 44
2

If you want to use the user's password to unlock their encryption key, the best bet is to use a password derived key to decrypt a data encryption key. This way the key used for actual encryption of a large amount of data is purely random, but then that key itself is encrypted with the password derived key.

You then have to either re-prompt for a password to decrypt data or store the decrypted data key in some form of temporary storage (session perhaps), such that it is only available while the user is logged in and then dump it when the user logs out.

You could provide some additional at rest protection for it if you have a TPM on the server that can encrypt it with a server key such that a dump of the session data will not directly reveal the key, but that's going a level beyond what you were initially describing.

There's also many other ways you can attempt to keep the key secure while in use depending on what hardware you have available, but ultimately that's a bit broader than a Q/A format answer can handle.

AJ Henderson
  • 41,816
  • 5
  • 63
  • 110