Cool project! I am also not fully convinced by one choice though.
If you're using the user password to decrypt the encryption key, why don't you simply derive the encryption key dinamically from the password each time the user logs in? I'm thinking of an algorithm that, given a string (the user's password), constructs a given key. Something like SHA-*, but more tailored to your use case.
In this way you wouldn't need to store the encryption key anywhere, as it's dinamically generated on demand.
As per the criticism on the user losing the password, I disagree with most comments. I think that if it's made very clear to the user why there is no recovery procedure, it can be a plus, but is has to be properly explained.
Anyways, to solve this, I'll throw my 2 cents. The recovery process could be done woth a local-based (no server) Q&A process. For example, when the user creates the password it is asked to provide three security questions, and the corresponding answers. Then the questions are stored locally and the answers are used to create an encryption key to encrypt the password, which is then stored locally. If the user forgets the password, it is asked the three questions and if the answers are correct the password is correctly displayed.
Now I know that many will tell me that storing the password in a database, even though encrypted, is a bad idea. But I'll respond that we are talking in this case of storing the encrypted password only locally. This means that to stole the password one would need phisical acces to the machine, and then it would need to crack the encryption. Which at this point makes this system much more secure than most SAAS that, while encrypting very well passwords server side, do allow (for obvious reasons) the user to stay logged in. So anyone with access to the machine can access all data without further work.
Why have a password at all? Just use webauthn if a device is available and skip the password completely (or give the user/dev a choice -- password sharing may make sense in a lot of contexts).
So long as we're able to get a strong static secret value from users, password or otherwise, that's all that matters. When we first looked into alternative auth mechanisms, it appeared that they did not provide us a value like that, but will definitely be looking further into webauth to explore this possibility some more, thanks for the tip
This is not the case, right now all a user needs to sign in is their password.
Only that particular password reset mechanism I described benefits from local storage. It's difficult to explain in one comment. We'll have clearer diagrams and explanations soon :)
the proper way for them to implement this would have been PAKE since they are customer facing for domains that may or may not even have a need for e2ee.
We expect all of our customers to have a need for e2ee.
And we do implement a PAKE.
For reference, I explained our approach a bit in this comment [0], and mentioned how we'll have more documents and diagrams available in the near future to explain it some more. Will explain it in more detail here (but be warned, it's still missing some steps and may seem a little convoluted to follow):
--Sign up--
1. user signs up and client generates a random seed in memory
2. client takes user's seed and inputs it through HKDF to derive a Diffie-Hellman key pair
3. client inputs user's password once through Scrypt, and then twice through HKDF to derive 2 values: password token & password-based encryption key
4. client encrypts user's seed from step 1 using password-based encryption key from step 3
5. client sends server the user's public DH key, password-encrypted seed, and password token for storage
--Sign in--
1. user inputs username and password
2. client inputs password once through Scrypt, and then twice through HKDF to derive 2 keys: password token & password-based encryption key
3. client sends server password token
4. server verifies password token matches stored token, and sends client a random message encrypted to the client's public DH key that was stored at sign up, along with the password-encrypted seed
5. client decrypts password-encrypted seed using password-based encryption key from step 2
6. client takes user's seed and inputs it through HKDF to derive DH key pair
7. client uses private DH key to decrypt random message from step 4 and sends plaintext message to server
8. client is now authenticated
Overall this approach is somewhat similar to Firefox's approach with Firefox Sync [1]
If you're using the user password to decrypt the encryption key, why don't you simply derive the encryption key dinamically from the password each time the user logs in? I'm thinking of an algorithm that, given a string (the user's password), constructs a given key. Something like SHA-*, but more tailored to your use case.
In this way you wouldn't need to store the encryption key anywhere, as it's dinamically generated on demand.
As per the criticism on the user losing the password, I disagree with most comments. I think that if it's made very clear to the user why there is no recovery procedure, it can be a plus, but is has to be properly explained.
Anyways, to solve this, I'll throw my 2 cents. The recovery process could be done woth a local-based (no server) Q&A process. For example, when the user creates the password it is asked to provide three security questions, and the corresponding answers. Then the questions are stored locally and the answers are used to create an encryption key to encrypt the password, which is then stored locally. If the user forgets the password, it is asked the three questions and if the answers are correct the password is correctly displayed.
Now I know that many will tell me that storing the password in a database, even though encrypted, is a bad idea. But I'll respond that we are talking in this case of storing the encrypted password only locally. This means that to stole the password one would need phisical acces to the machine, and then it would need to crack the encryption. Which at this point makes this system much more secure than most SAAS that, while encrypting very well passwords server side, do allow (for obvious reasons) the user to stay logged in. So anyone with access to the machine can access all data without further work.