2

As a bit of a thought experiment, I've been thinking through how one might design a web application where a user's data (say, from a form on a webpage) is stored, encrypted, on the server, using a per-user key. The decrypted data is shown in a form on the webpage when the user logs back in.

I've come up with two potential approaches and I've attempted to identify the pros & cons of each, but I'd love to get others' thoughts - I'm certain I haven't thought of every possible attack.


Here are some properties of my hypothetical system that are consistent across all three approaches:

  1. Everything occurs over SSL.
  2. Any cookie that goes over SSL is marked as secure.
  3. Data to be encrypted: a single form field on a webpage, consisting of plain text
  4. Data is encrypted with a N-digit PIN
  5. N-digit PIN is stored in DB on server (bcrypted or scrypted)

  6. N-digit PIN is passed through password derivation function to generate 256-bit encryption key

  7. Data encrypted using AES-256-CBC mode, random IV. Signed using Encrypt-then-MAC approach (e.g., some form of authenticated encryption). HMAC key is derived from N-digit PIN.


Option 1: Encrypt on server, with key stored temporarily in server-side session object:

  1. User logs in with PIN.
    • Server authenticates against PIN digest in DB.
    • Server passes PIN through password derivation function to generate 256-bit key.
    • Server stores key in server-side session object (& persisted in Redis or memcached).
    • Server renders form for user to enter data in (& sends cookie with session ID to client).
  2. User enters data in form, submits to server.
    • Server encrypts data with key in server-side session object, signs encrypted data.
    • Server stores signed, encrypted data in DB.
  3. User logs out / session expires
    • Key is wiped from session & wiped from persistent cache.

Cons
- In a server-side attack, attacker would be able to get encryption key for any logged in user & would be able to decrypt their data.

Pros
- Key only exists temporarily on server. Once user logs out, persisted encrypted data is (relatively) safe in DB.
- Client-side attack doesn't get the attacker much - only a session ID in a cookie.
- In a server-side attack, attacker would only be able to attack logged in users - not sure how much of a pro that is, though.
- In a server-side attack, attacker wouldn't be able to get users' raw PINs.


Option 2: Encrypt on server, with key stored in encrypted cookie sent to client:

  1. User logs in with PIN.
    • Server authenticates against PIN digest in DB.
    • Server passes PIN through password derivation function to generate 256-bit key.
    • Server stores key in encryped cookie.
    • Server renders form for user to enter data in (& sends cookies with session ID and encrypted key to client).
  2. User enters data in form, submits to server.
    • Server extracts key from encrypted cookie.
    • Server encrypts data with key from client's cookie, signs encrypted data.
    • Server stores signed, encrypted data in DB.
  3. User logs out / session expires
    • Cookie is deleted locally on client's machine

Cons
- On the client, attacker has encryption key - but that's really all they have. They don't have encrypted & signed data, they don't have unique IV, etc.
- That said, if you're logged in (presumably with the PIN), you're already looking at the decrypted data. Having the encrypted key doesn't buy you anything. The encryption key doesn't work for other users' data (unless they happened to use the same PIN, obviously, but there is no way for an attacker to know that).

Pros
- Key is never persisted on server, and only exists in memory for fleeting moments. Persisted encrypted data is (relatively) safe in DB.
- In a client-side attack, attacker wouldn't be able to get users' raw PINs.
- In a server-side attack, attacker wouldn't be able to get users' raw PINs.
- In a server-side attack, attacker wouldn't be able to get any other users' encryption key.
- To do any damage, attacker would need to successfully attack both the server and the client, and the damage would be limited to a single user.


I completely understand that in security, there are always tradeoffs, and nothing is perfectly secure - but assuming that an attacker can get inside a server (e.g., cough, the NSA), it feels like a server-side approach where encryption keys are even only temporarily stored is risky.

I feel that counterintuitively, option 2 is more secure.

Am I right/wrong? Is either approach a Bad Idea (TM)? If so, what are some alternative approaches to consider?

  • Are you trying to make it so only the user who put the information into the db can decrypt it locally without the possibility of the site owner decrypting it? – Eric G Mar 23 '14 at 19:53
  • Effectively, yes, though the decryption would take place on the server before the content was sent back (e.g., to be rendered in a form on a webpage). What I'm trying to avoid is situations where an attacker, gaining access to the server, is able to decrypt at-rest user data. – Rob Mar 23 '14 at 20:13
  • Hi @RobRingham, how did you solve this issue? I am trying to implement the same concept. Thanks for more info. – Artegon Feb 24 '17 at 9:11
1

This feels more like a point of discussion, rather than a question. This is because there is no definitive answer to your question, merely conjecture.

The best method for answering your question is to conduct a risk assessment. This will encompass your risk appetite and thus give a better indication as to which method is best suited to gathering and storing the information that will be processed.

The risk assessment will also include the context of this application, which your question does not include. Without understanding the context and, thus, the value of the information, the best course of action will merely be speculation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.