"Forgot your password? - Don't worry, we'll send you an email."
- How often have you read that when you clicked on the 'forget password' link for some of your online services?
While it seems to be a good approach for your blog, Ebay, or some other web sites, this is a big no-no for encrypted email services. Why? A good analogy would be locking a safebox with your money inside and leaving the key on top.
It's amusing when such services claim to be secure but let you send a reset link to your Gmail.
Some of these services went a little further to protect your data by not allowing you to reset your password at all. This approach makes your account just another zombie, inaccessible account and forces you to open a new one. Obviously, this step (if for an email account) involves you notifying all of your contacts of an email address change, making the whole experience just as bad as not being able to have a private mailbox at all.
At SCRYPTmail we are taking security seriously, but we also understand that losing an email address may be worse than losing a credit card. After more than a month of iterations through available solutions, we realized that a solution to this issues just does not exist.
We have to solve the problem of giving users the ability to reset their password or secret phrase without compromising security. At the same time, we also need to protect users from impostor or malicious scripts which can try to brute-force and essentially lock accounts. We also must keep our server from knowing too much about a user.
The solution can be broken down into 5 steps:
- You create an account and our system will generate a random 256 bytes string. (string256)
- A hash of this string of this string will be saved in the database as
ShaToken = SHA512(string256)
- string256 is encrypted on the client side with the secret phrase you provide
EncryptedToken = AES256(string256)
- A hash of this EncryptedToken is saved in the database.
EncryptedShaToken = SHA512(EncryptedToken)
- Convert the EncryptedToken into HEX and let the user save it on his device.
byte2Hex(EncryptedToken) -> File
As the result of this manipulation, the server stores a hash of a token before and after encryption but is unaware of the secret phrase or even the encrypted result. The user has an encrypted token that can prove his/her identity to the server.
To answer the most obvious questions (feel free to send in more though!):
Q: But what if an attacker gets access to the token and tries to reset my password or secret phrase?
A: In order to reset the password/secret phrase, the user has to provide 3 items: email, secret token, and secret phrase or password. If he/she fails on any of them, the system won't reset it.
Q: How does the server know if the user provides the correct secret phrase?
A: Step 2 and 4 come into play because the user has to submit the correct hashes of the token before and after decryption.
Q: What if I forget my secret phrase?
A: To reset the secret phrase, 3 item requirements still have to be met: email, token and password. In this case, a hash of the encrypted token will be used along with the password.
To summarize the steps above: in order to reset either the secret phrase or password, a user has to provide his email, token and one of two following items: secret phrase or password.
If you lose your token, you may generate a new one on your profile page in the Reset Secret Phrase tab. It will also be regenerated when you change your secret phrase, which renders the old token useless.
You may have noticed that we encrypt raw bytes with AES-256 thus rendering any offline brute-force of the token futile since there is no result that can be distinguished from wrong or right, and will require server for verification. [and the server is required for verification?]