2

I am writing a C# .NET application. For my application the data of the users should be encrypted in the database. The users should also be able to share data with other users. To that end I want to use RSA encryption.

My intended implementation is as follows: The public key of the user is stored in the database. Data that is to be shared with another user is encrypted with that users public key and stored in the database. Now, here are two problems I am facing with this approach:

1.) I want the public/private key pair to be derived from the user password so as to not have it stored anywhere unsafely on disk. Whenever the user logs into the application, the private key is derived and user data can be de-/encrypted. My question is, how can I derive an RSA key pair from the password?

2.) If the user resets their password, no previously encrypted data can be decrypted anymore, as that would require the user's old password in order to derive the private key. As far as I know, one solution to this problem is to encrypt/decrypt using a randomly generated data encryption key that doesn't ever change, and to then encrypt that key using a password based key. But then how can a user share encrypted data with other users? For that the user would have to also share their password based key in order to grant access to the public data encryption key, which obviously is against the whole point of encryption.

So, how do I go about reconciling and solving both of these issues?

automatictester
  • 652
  • 3
  • 11
csstudent1418
  • 231
  • 2
  • 8
  • It looks like what you are looking at is Database Encryption. https://en.wikipedia.org/wiki/Database_encryption#Advantages_of_application-level_encryption – postoronnim Jul 08 '20 at 18:32
  • @postoronnim If I understand it correctly then that is precisely NOT what I am looking for I don't want my app to send and receive data in plain form and only encrypt it after completing database transaction. Rather I am looking for Application-level encryption. – csstudent1418 Jul 08 '20 at 23:32
  • Reference 35 in the article is about application-level encryption. – postoronnim Jul 09 '20 at 14:50

2 Answers2

0

You are raising a few questions here actually, so the answer won't be simple, and for sure won't be complete. First thing first, this question might be better suited for crypto.stackexchange.com.

A few basic things I'd like to point out:

  • Depending on the data size, you most likely don't want to use RSA keys for encrypting that. RSA keys can encrypt only data of up to certain size, which is just under the key length. It's not particularly efficient either.
  • I don't think you want to derive RSA keys from user password. This is not what RSA was created for and there is no standard solution to do that. RSA key is just a bunch of large integers, but of certain important characteristics. What I'd suggest to do instead is to encrypt data using a symmetric key derived from user password using one of the *KDF* functions. You can then use static, long-term RSA keys to encrypt the symmetric keys - both master and derived ones.
  • As for the password-based key derivation, I believe this is more about key lifecycle management than anything else. One solution would be to store key id for the current and previously derived keys in the metadata of the data it was encrypted with. Assuming the password changes, this will change the current symmetric key id (as well as the key itsefl), but previously derived symmetric keys could be used to decrypt data encrypted in the past. This all assumes keys are effectively rotated on password change, but never expired.

Apologies for my answer not being as complete as I'd like. However, I think it would be good to take a step back and rethink the original requirements, as what you have described in your question is more like a partial solution. If the community gets to know the original problem, they may be better equipped to provide the best answer possible.

automatictester
  • 652
  • 3
  • 11
0

The answer to this would depend on who you are protecting the data from. E.g., if you trust yourself not to turn (or be pressured into being) evil.

There are a lot of gotchas with encryption schemes and the devil is in the details.

If you trust yourself then you could use a standard auth/password scheme (e.g., asp.net cores built-in one or scrypt, ask another question for this) and then use database encryption. I have worked on mid level classified data systems, with a similar scheme.

If you don't trust yourself well that gets a lot harder. However it is not impossible to have a reasonable system. I suggest you read up on how Signal the message app manages their security. Also read up on how Windows DPAPI and Windows full disk encryption, works with changing passwords.

That said, some thoughts:

If you are going to have per user password encrypted data, don't derive the key from the password. Generate a random key (securely) use that to encrypt (say with AES) the data. Then encrypt the key using a secure hash (say bcrypt) from the username and password. Also store a version number of the scheme along side all this so you run 2 or more schemes side by side as you migrate from one scheme to another. This all means you can change the password without re-encrypting the data (just the encrypted key) or re-encrypt the data without changing the password (say if a weakness is found in AES). Also it protects rainbow table attacks on the encrypted key.

Services like Azure Blob storage have similar built-in encryption schemes which can solve some of these issues for you.

Finally remembered crypto is hard and very easy to miss one thread which causes everything to come undone. So be careful, get help, have fun and good luck!

DarcyThomas
  • 1,298
  • 1
  • 10
  • 15
  • "Generate a random key (securely) use that to encrypt (say with AES) the data. Then encrypt the key using a secure hash (say bcrypt) from the username and password." Yea but then users can't share data with other users, can they? Because they would need the username AND password of the other user in order to compute the hash and decrypt the AES key. Thats the whole difficulty I am having, solving all these issues together to satisfy the requirements. – csstudent1418 Jul 09 '20 at 00:32
  • @csstudent1418 My point is don't just use a password as a key. Use the password to secure a key to encrypt the data. In your sharing case you will want one key per person per file. I.e., original file at rest is encrypted with a key, protected by the 1st users password. When they want to send a copy use the password to decrypt the key, decrypt the file re-encrypt with a new key (new encrypted **copy**) send the copy and securely share the new key (with RSA maybe). Or something like that. – DarcyThomas Jul 09 '20 at 03:05