How to login and encrypt data with the same password/key

First of all, don't worry about the username. The username is supposed to be public information — if it wasn't, it wouldn't be a username, it would be a password. Just assume that an attacker will be able to find out the username(s) in any case, and design your system to be secure with that assumption.

Second, don't worry about the encryption (or hashing etc.) method being public, either. That's Kerckhoff's principle — the encryption method should be treated as public, the only thing that needs to be secret should be the key (or password, in this case).

There are many good reasons for this, not the least being that it allows you to publish how the system works (and thus convince your users that it's secure, or to ask for help from security experts, or to just use an existing standard system designed and analyzed by such experts) without compromising its security.

Third, don't worry about the salt either. The salt should also be treated as (potentially) public knowledge. Its purpose is not to provide any additional secrecy, but to protect against attacks using precompiled hash tables by ensuring that every user's password is hashed in a different way, even if the actual passwords happen to be the same.


OK, so what should you do, then?

Well, first of all, you should use a secure key derivation function that implements key stretching (and salting, of course) to derive the user's encryption key from their password. PBKDF2 should do nicely for that, although e.g. scrypt might be even better if you have it available.

Second, you obviously should not use the encryption key as the password hash. In fact, you shouldn't store anything in your database that could be used to obtain the encryption key without knowing the password. (For instance, the encryption key should not be a hash of the password hash.)

One thing you could do is derive both the encryption key and the password hash separately from the password using PBKDF2, but that would be kind of inefficient, since PBKDF2 is deliberately slow. Instead, you could derive the encryption key from the password with PBKDF2, and then use a normal cryptographic hash (e.g. SHA-256) of the key as the password hash for logging in. (Or, if you want to be extra careful, derive both the encryption key and the password hash from an intermediate key derived from the password using PBKDF2.)

Finally, to make changing the password easy, don't directly encrypt files with the user's encryption key. Instead, for each file, create a random file key, encrypt the file with the file key and encrypt the file key with the user's encryption key. That way, when the user wants to change their password, you only need to re-encrypt the file keys.


Eric Lippert's blog series "You want Salt With That?" was helpful for me in understanding several issues about security. It was written in 2005 but the information still holds up today.

You could also check out OWASP's Guide to Authentication and their Authentication Cheat Sheet

Those documents should prove helpful but in regards to What is the best practice for logging in... I don't think there is an easy straight forward answer on that. I am also not a security expert, hopefully someone who knows more is willing to step in and give you advice on that.