Summary of the discussion in the comments regarding the updated question
Calculating pw = sha256(sha256(user_password)) strikes me as a bad idea for several reasons.
- The first one was already mentioned by AgentMe: Don't use simple hash
functions such as sha-whatever to hash passwords. These hash functions were designed to be implemented efficiently in hardware and are much, much
too fast; to hash passwords, you want slow hash functions. See AgentMe's
- With this scheme, pw can be calculated if you know gk (which is just sha256(user_password)). So when someone steals your localstorage, you give him access both to the master encryption key and to the authentication/authorization token he needs to download the encrypted files. It would be better to keep the two secrets independent of each other, so if one is compromised by a third party, it's not enough to calculate the other one and break the confidentiality of the encrypted data.
- Finally, you're not salting your user_password with this scheme. This means that identical passwords across your whole userbase will yield identical hash values (and there are already large rainbow tables for unsalted sha-hashes out there containing the few million most common passwords).
You suggest an alternative, e.g. gk=sha256(user_password) and pw=sha128(user_password). While this solves point 2, it doesn't address 1 und 3. Also I wouldn't recommend it because I could imagine that this needlessly provides additional information to an attacker (the same password hashed to two different hash values), even though I don't know how to exploit it.
I suggested using gk=hmac(user_password, n) and pw=hmac(user_password, m), where m and n are known, but different for each user. How you arrive at m and n is irrelevant, as long as they're random and sufficiently large to make them unique across your user base with a high probability. You could create them on the client and submit them for storage at the server, indexed by the username so they can be retrieved on other clients. Or you can have the server generate them when the user first creates an account. The values don't need to be kept secure; they're worthless without the user_password. An improvement improvement would be to use gk=hmac(bcrypt(user_password), n) and pw=hmac(bcrypt(user_password), m) to make brute force attacks harder.
Now, I'm not convinced that this suggestion is a good idea, since hmac is designed for message authentication, not for creating authentication tokens or encryption keys, so I'd take that suggestion with a grain of salt. But it seems to solve all three points I raise, so it seems like a better solution than chaining the same hash function or using two different hash functions on the password.