Generate a private key at the browser.
9876691 opened this issue · 2 comments
Is there a way to generate a private key from the users password which we then use to encrypt a random private key.
From the skiff docs https://www.skiff.org/security
- Bob enters his email and generates a secure password
(more than n digits, upper/lower case letters, numbers,
and special characters). Random encryption and signing
keypairs are generated (tweetnacl.js) for Bob’s account
in-browser. - On the browser, we run Argon2id to derive a symmetric key from Bob’s password. Using HKDF, this symmetric key is used to generate one symmetric key for
login (using the Secure Remote Password protocol),
and another symmetric key for encrypting Bob’s secrets (i.e. private keys). This second key is called Bob’s
password_derived_secret. - We use Bob’s password_derived_secret to encrypt
sensitive data associated with Bob’s account; this encrypted data is called Bob’s encrypted_user_data.
This includes Bob’s private keys but not his password.
This encrypted information is stored by our server butcan only be decrypted with Bob’s password_derived_
secret. The next time Bob logs in, Bob downloads
his encrypted_user_data from the server, then decrypts the encrypted_user_data in-browser by using the password_derived_secret. The password_
derived_secret never leaves the browser.
In this system, Bob’s public keys are publicly visible, while
his private keys are encrypted end-to-end. His password and
password_derived_secret are never stored, not even as encrypted data. Bob’s password_derived_secret and password are also never sent over any network, even as encrypted
data.
We use the secure remote password (SRP) protocol to authenticate user login. After Bob is authenticated using SRP,
the server sends Bob’s encrypted_user_data as well as a
signed JSON Web Token (JWT) to indicate that Bob has properly logged in within a certain amount of time. In our security
model, the time-limited JWT is used for “read-only” operations, including downloading encry
Concerns
Any JS we add to the client creates more opportunities for side channel attacks.
The data stored by SRP is it more secure than a hashed password. i.e. can we repliucate the private key with a dictionary attack.
The key doesn't have a lot of entropy.
Have a look at https://docs.rs/opaque-ke/0.5.0/opaque_ke/
Note that this is not specific to SRP; for any password-based authentication method, if the attacker can learn everything the server knows, then he can impersonate the server, and in addition, he can perform an undetectable dictionary attack (for example, by simulating a client logging in with various passwords; this is undetectable because since this occurs entirely on the attackers equipment, you aren't informed that someone that someone is trying to log into the system with a long series of passwords).
Looks like BitWarden has a good solution for this.
https://bitwarden.com/help/article/bitwarden-security-white-paper/
Example code