For a new application I'd like to store messages for each user's account on a centralized server.

The user accesses the application through a SPA javascript web app through their browser.

These messages:

  • Should be unreadable by the server
  • Are readable only by the user themselves (not other users)
  • Can be added by the server (readable only transiently before encrypting)
  • Can be added by the user (then encrypted and sent to the server)

I'm using libsodium and my proposed solution is to:

  • Generate a randomly generated salt client-side using randombytes_random
  • Derive a key from their plain-text login password, on account creation, using crypto_pwhash and the previously generated salt
  • Use this key as a seed to generate a public and secret keypair using crypto_box_seed_keypair
  • Store the public key and salt on the server (sent via secure transport)
  • Store the secret key on the client in localStorage (I'd like to avoid the user having to enter their password too often)
  • Regenerate the secret key on login by retrieving the salt from the server and recreating the seed to generate the keypair
  • Client encrypts with the public key using crypto_box_seal
  • Server encrypts with the stored public key using crypto_box_seal
  • Client decrypts with the public key and secret key using crypto_box_seal_open

Is this scheme vulnerable?

I'm worried about storing the secret key in localStorage.

Does it instead make sense to:

  • Store the seed in localStorage
  • Generate another salt that is then retrieved from the server
  • Hash that together with the original seed to generate a new seed
  • Use the new seed to generate the keypair?
  • Why using asymetric encryption? An AES key should be enough for what you need. About the store of the key, most fo the end to end encryption app I saw put the key in the URL after a '#' (which is not send to the server)
    – Sibwara
    Aug 13 '20 at 12:30
  • I'd like the server (controlled by me) to not be able to read the stored data. But would also like it to be able to add stored data from a third-party. Which means that it would have to read unencrypted messages temporarily before encrypting them with a public key and storing them. I don't think I can do that with an AES key? Otherwise the server would also be able to decrypt the messages
    – fli
    Aug 14 '20 at 1:50
  • I think I don't understand well the case but is it not easier to make the third party encrypt its data at the client side and send them already encrypted to your server ?
    – Sibwara
    Aug 14 '20 at 8:18
  • Unfortunately not possible in this use case. I'd like the user to be able to add messages via SMS, which means that I need to process the response from a third party (Twilio). So there will be some moment where the message is seen in plain-text before it is encrypted and stored in the server.
    – fli
    Aug 14 '20 at 9:35
  • So your approach is to encrypt the received datat with a public key but whos generated this key ? the server or the client ?. If it's you, how do you manage to send the private key to the user ? If it's the user, why he cannot encrypt its message and send it encrypted through sms
    – Sibwara
    Aug 14 '20 at 10:49

Your Answer

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

Browse other questions tagged or ask your own question.