I am working on a web app with an integrated chat. All chats can only occur between two users - not more, not less.
I am very concerned with security, so I would like to encrypt all chat messages with end to end encryption. My favored protocol so far is the Signal protocol.
However, the problem of web apps is that it's not possible (as far as I know) to reliably store the private key of a user. Also, you can't really save anything locally (i.e. in the local storage of the browser) because the web app can be accessed from everywhere and the user should be able to view all messages as soon as he logs in wherever he might be.
So my solution would be:
- User X creates an account in his browser.
- A key pair is created and the private key is encrypted symmetrically using the entered password.
- The public and the encrypted private key are sent to the server where they are stored in the database.
Then, if a user Y wants to start a chat with X:
- Y's message is encrypted in his browser two times:
- Once with the public key of user X, stored in the database,
- and then with the password of user Y.
- Both encrypted version of the messages are transmitted via WebSocket to the server.
- The server sends the first version of the message to user X if he is currently logged in. Also, it stores both versions of the message in the database.
- The browser of user X decrypts the message(s) received from the server as soon as he is logged in and displays them to the user.
Each time user X logs in and views the chat:
- The user logs in and receives the encrypted private key. Using the entered password, the private key is decrypted.
- The already existing chat messages are requested from the server.
- Locally, the messages are decrypted with the private key.
Is this safe at all?
I think that this would prevent some of the following disadvantages when researching other methods:
- The server does not have to decrypt and re-encrypt all messages when a user changes their password.
- The browser does not need to generate a new key pair each time a user logs in at a new location.
- The messages can be stored long term for both users to be easily read.
One potential vulnerability I thought of would be:
- Because there are two versions of the message stored in the database, a potential attacker could have an easier job of brute forcing the original content. Though, this might be prevented by signing both messages with some userspecific value, i.e. the username.