Is it safe to hash a password two separate times with two separate salts and save both hashes on the same server

Viewed 121

I hope I didn't create a duplicate question. I tried to look for already existing questions, but I didn't find anything.

I have successfully set up a database with username, salt and hashed password for logging in. For checking the password, I compare the generated hash with the one of the database, see code below.

password_hashed_from_user = res[0][0]
salt = res[0][1]

key_generated = hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), base64.b64decode(salt.encode('utf-8')), 100000, dklen=128)
key_encoded = base64.b64encode(key_generated).decode('utf-8')

if key_encoded != password_hashed_from_user:
    logging.debug("Password was wrong:\n{}\n{}".format(key_encoded, password_hashed_from_user))
    return "Username and/or password incorrect", False

The problem now is that I want the user to be able to act completely anonymously, which means I want the user to be able to use a generated token for identification, which cannot be traced back to his account.

Therefore I would need to store the token in a separate table, not correlated to the one with the credentials. In order for the user to not be able to cheat and just ask the server for a new token every time he logs in (and therefore act as a new user), I wanted to compute the token based on the credentials.

So I figured, I could just have a separate salt and create a new hash based on the password (with the same method as in the code example). Since the password itself is not stored on the server, this hash could not be generated without the password of the user itself.

This way, the generated token is always the same, as long as the salt doesn't change. So I can make sure that a specific user is always identified as the same one, while the user can make sure that I cannot trace back his actions.

Background

The background is that I need to create a voting environment, where people have to register and identify themselves in order to prevent double voting, but the vote results, as well as the participation etc should not be traced back to the specific user. As this is a project in my studies, I cannot just use existing frameworks/libraries.

Now my question:

Is it safe to store two separate hashes of the same password with different salts on the same server or would the duplication make it feasible to recreate the actual password? Both salts would be stored together, together with one of the hashes. The other hash would be in a separate, unrelated table.

I always struggled a bit with encryption on that level.

1 Answers

Is it safe to store two separate hashes of the same password with different salts on the same server or would the duplication make it feasible to recreate the actual password?

Yes, it is safe.

The basic idea behind that statement is that the salt "injects" sufficient uniqueness into the process that the password hash can work with to ensure that two different salts yield unrelated-looking hashes. A real-world example of this would be the worry of two different users having the same password (but different salts) - which also doesn't leak anything about the password and was one of the main motivations to introduce salts.

The more cryptographic argument is either you assume your hash acts like a random oracle - which yields unrelated random ouputs for unique inputs - in which case the uniqueness of the salt hides all output. Or you use a weaker assumption that your password hash is a randomness extractor combined with a pseudo-random function (not unreasonable for a cryptographic hash-based password-hash) with the key in the password input. In that case assuming the password is unknown and sufficiently random all unique salts will be mapped to strings that are indistinguishable from random output and therefore cannot yield any information about the output.

Alternatively you can also use Bellare, Ristenpart and Tessaro's definition for password hashing security which essentially says "breaking a password hash is as hard as guessing the password if said hash is good".

Related