How to store private encrypted user data in the database, but make them available to other chosen users?

Frodik picture Frodik · Sep 23, 2011 · Viewed 9k times · Source

firstly, I apologize if my question sounds little confusing, I will try my best to describe my scenario as detailed as possible:

I have website where user can input their personal data about themselves. They are mainly health data, so it's very private and sensitive information. So I need to encrypt this data on the server even then the server is compromised these data are secured because they will be encrypted with each user's password. Of course, user passwords will not be stored as clear-type text on the server, only password hashes.

But my problem is that the website will offer "social function" when user can choose to share some of his/her information with another user. But this would be problem, because I will not have any way of decrypting user private data and so I can't show it to another user.

Can you please give me some options, or at least ideas, how could this be solved ? Preferrably using LAMP environment.

Answer

phihag picture phihag · Sep 23, 2011

This can be solved using public-key cryptography:

  1. Generate a public/private key pair for each user; and only ever decrypt the private key temporarily with the user's password.
  2. For each data item, randomly choose a (symmetric) key S and encrypt the data d with it. Store S(d).
  3. Encrypt S with the the public key P+u of the user you want to grant access. Initially, that's the user u whose data you're storing.
  4. Store P+u(S) permanently. Forget all other keys.

Now, when a user u wants to share the data with the user x, do the following:

  1. Decrypt the user's private key P-u with the user's password.
  2. Using that private key, decrypt the stored data: P-u(P+u(S)) = S.
  3. Encrypt S with the public key of the user you want to share the information with.
  4. Store the resulting P+x(S) permanently. Forget all other keys.

Now, when any user x wants to access the data, perform the following process:

  1. Decrypt the user's private key P-x with the user's password.
  2. Find P+x(S). (If it's not stored, that means nobody shared the data with the poor user x).
  3. Using the private key, decrypt the stored data: P-x(P+x(S)) = S.
  4. Using S, decrypt the stored encrypted S(d): S(S(d)) = d.