5

Background

I am trying to develop a web application where a user will be able to login using their password 'P' and upon logging in can create a master password 'MP'. MP can be used to open / close a vault (much like password managers) wherein the user can store sensitive information. Upon doing some research on the topic I have decided to ensure the followings:

  • The master password MP is never stored on / sent to the server
  • All encryption / decryption are carried out on client side (in my case that is the browser)

Now as I am storing the key MP′ (defined below) in memory, the vault is essentially closed every time the browser is refreshed or the user opens the site on a new tab. How can I keep the vault to stay open for as long as the user wants? Cookie is not a solution as that will cause MP′ to be sent to the server on every request; however, HTML5 local storage may be a possibility

Now if a hacker happens to get access to the local storage, they would get MP′ and can decrypt all sensitive information using it. As a solution here is what I am thinking of:

  1. When the vault is opened, client requests for a one-time random key 'Rk' from the server
  2. Server generates Rk, stores it in the user's session and sends it back to the client
  3. Client uses Rk to encrypt MP′ to get MP′′
  4. MP′′ is stored in HTML5 local storage while Rk is held in memory
  5. When needed MP′′ can be decrypted using Rk and used for subsequent operations
  6. On browser refresh, the client re-fetches Rk from server (the server simply returns the one already stored in session)
  7. Rk is expired if the user explicitly closes the vault or ends the session by logging out

The question

How secure would this solution be? Any obvious caveat that I am missing? What would be the ideal approach to fix it?

Additional notes

For your understanding here is a brief overview of how I am planning to fulfill my needs:

  1. User creates a new MP
  2. MP is encrypted with a key-stretching algorithm to produce MP′
  3. MP′ is used as a key to encrypt a known value V to get Vh (obviously V ≠ MP or MP′)
  4. Vh is stored on server against the user's record

Vh serves 2 purposes:

  1. It indicates that the user has already created an MP. If it is yet not there I can ask the user to create a new one
  2. Whenever the user enters MP to open the vault, I can retrieve Vh from server and try decrypting it with MP′. If the decryption is successful, I assume that the user entered the right MP

As you can imagine here's how the rest should work:

Whenever the user wants to store / retrieve sensitive information:

  1. They login using P and open their vault with MP
  2. The client produces MP′ as previously mentioned
  3. Sensitive information are encrypted using MP′ before being sent and stored on server
  4. Based on user's need, encrypted sensitive information is retrieved from server (as is)
  5. Client uses MP′ to decrypt the data

migrated from crypto.stackexchange.com Jun 20 '17 at 23:40

This question came from our site for software developers, mathematicians and others interested in cryptography.

  • 1
    From what I understand, everywhere you say "hash" you mean "encrypt" – bmm6o Jun 21 '17 at 15:01
  • @bmm6o You are correct. When I said 'hash', I specifically wanted to mean 'symmetric encryption' – Tanvir Jun 21 '17 at 15:37
  • @Tanvir Can you update your question to reflect that then? The two are very different methods. – Bacon Brad Jun 21 '17 at 17:13
  • It also depends of how Rk is generated. Make sure it's not guessable eg from the previous keys or from the time. – Xavier59 Jun 22 '17 at 0:54
  • @Xavier59 Well that's a good point. I'm using java.security.SecureRandom to generate the key and salt to ultimately compute Rk via PBKDF2 – Tanvir Jun 22 '17 at 4:46
2

There are several problems with your approach:

1) Forward Secrecy. Suppose the attacker can monitor the communication (via hacked corporate https proxy or other way). At some later point the user deletes the account and reveals MP as he think it's useless. Using the logged data and MP all information can be restored by the attacker because you are encrypting the vault with MP'.

2) It's not clear how do you defend against compromising P. Capturing P (which goes over the network) the attacker can log in, acquire Rk and decrypt MP", unless Rk is regenerated at all logins, what means the user will be effectively logged out if she closes the browser (it might be ok and intended, I don't know). Anyway, it's better not to send P (see ideas below).

3) Encryption will give you limited security improvement. If the attacker can access localStorage, she probably has physical access and/or compromised your machine, so you are doomed anyway (you are facing keyloggers, local script injections, whatever). Encryption will help you if the hard disc is stolen or the attacker is able to fake your domain (eg. DNS cache poisoning). It's better not to store the password in the first place.

Several ideas:

  • to mitigate (1) use one time session keys to encrypt all messages. For example you can use asymmetric crypto to send some random session key to the server (encrypted with the server's public key). Alternatively, you may want to enforce proper SSL sessions (by informing and educating your users ) since SSL has quiet good forward secrecy.

  • for (2) instead of using P to authenticate, use some advanced method eg. OAuth, preferably 2FA.

  • you might consider using sessionStorage instead of localStorage which is guaranteed to be deleted at browser restart (other ways it's very similar to cookies without networking). I'm not sure if all (or any) implementations can securely remove all traces of the storage at exit, so encryption still might be a good idea.

0

I think it might be worth reevaluating your premise. Presumably you're wanting to encrypt things client side so that the server has no access to unencrypted data, but this isn't really the case, and I think it ends up being more security theater than actual security.

This is from 2011, but I think the main issue here is still relevant, if you can't trust the server to handle data encryption properly (ie, encrypt it then forget the plaintext and the password) then how can you trust it to deliver the code that's supposed to handle encryption client side?

It seems like this might be of benefit in the case of a compromise allowing the attacker to read requests without modifying them, but you're still putting so much trust in the server I'm not convinced it's worth it.

  • thanks for the link. there're good things to learn. now, the reason that it is a bad idea to store plain passwords on server is not that users don't trust the server, rather it is because the attacker won't gain much if they can manage to have access to the database only. that's the only prominent reason that i can think of. having said that, SSL / TLS for all communications between the server and client is already being enforced. through the proposed design my goal is to claim the same set of benefits (that we have by storing encrypted passwords) for securing other sensitive information too – Tanvir Aug 4 '17 at 8:16

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.