3

I would like to store password hashes in a database.

In order to prevent dictionary attacks, I was thinking to use HMAC with a key parameter which is public - like user id. That means the user id would be a salt to the hashed password.

Do you think it is safe and the right algorithm for that?

EDIT:

Originally what I was really curious is this: is it safe to use HMAC for password hashing given we interpret its key as a salt and its message as the password?

A lot of answers says rightly that using the user id as a salt is not an ideal solution for two reasons:

  1. They stay the same when the password is changed
  2. They are too short

Originally I just meant this to be an example, but this was a red flag for most of you. And everyone is right here!

toni77
  • 179
  • 1
  • 8

6 Answers6

6

The username (Or user id) is not a proper salt. Salts should be unique for each combination of username+password, that means if the user changes the password the salt should change too

The salts should be generated randomly upon password changing (Or when the user registers) for example reading from /dev/random or some function that generates cryptographic random numbers. About the length of the salt, it should be long enough to ensure it never repeats

Mr. E
  • 1,954
  • 9
  • 18
  • Generally speaking it is always safer to generate those parameters every time, but here it does not make sense, because the salt is a known value. Also, the HMAC's hashing algorithm guaranties having a big distance between small password changes with the same key. The question here rather is that if it is safe to consider HMAC key parameter as a salt. – toni77 Nov 16 '16 at 13:19
  • 4
    It doesn't matter if it'is a known value. Salts are to prevent attackers precomputing all hashes and then bulk "decrypt" the passwords. Salts gives some uniqueness to prevent this, but in case an attacker wants to attack a specific user and you repeat the salt (Username won't change on password change, so the salt is the same), then the attacker can precompute all the hashes for that specific salt, if that's the case your salt is not anymore a salt but a user specific key. Just imagine what could happen if an attacker aims against an "admin" account knowing the salt will always be the same – Mr. E Nov 16 '16 at 15:28
  • Mr. E, Thanks, this is absolutely valid what you state. It is much better to have a new salt every time on password change, and also it is better to control the size of the key in HMAC directly, because if the user id is too short, HMAC will simply zero pad it for the underlining hash algorithms block size. – toni77 Nov 16 '16 at 16:03
  • Support your answer, but actually `/dev/urandom` is better suited to generate the salt, especially for applications running on a web server. – martinstoeckli Nov 17 '16 at 14:46
3

Short answer

No. See: Don't roll your own security.

Pedantic answer

You've mixed up several terms.

It's not an HMAC if the key is public

An HMAC requires a secret key (sometimes called a pepper) as opposed to a salt, which is public. Otherwise it is not an HMAC; it is just a hash.

A common use of an HMAC is to create a tamper-resistant fingerprint in order to provide message integrity. It is not used for password storage.

Don't think you're talking about a dictionary attack

The purpose of using a salted hash to store a password is not to mitigate dictionary attacks. The purpose is to thwart attacks that use a rainbow table. Salt does not affect a pure dictionary attack; the only mitigation is to use a password that is not in the dictionary, e.g. by requiring special characters or requiring longer passwords.

I think you are asking...

I think you might be asking "Is it OK to use an HMAC algorithm with a public key (instead of a proper password hashing function, like BCrypt) to store a password hash?" In that case, the answer is still NO. You should use password hashing algorithms, not other hashing algorithms, for password hashing, because they have features specific to the problem. For example, they are purposefully slow, and/or provide parameters that let you specify number of iterations required, which increases the computational power required for dictionary attacks and can render them much more difficult when compared to ordinary hashes that work with a single pass.

Is it OK to use the user ID as a salt?

Sorry, no. It causes a few issues:

  1. Creates a problem if the user ever changes his ID (hash would need to be recomputed)
  2. User ID may not be long enough to thwart attacks
  3. Same user ID might be used for different services, making it easy for the hacker to tell if the same password was used as well
  4. Hacker might compose a set of rainbow tables based on a list of common user IDs.

Also, see this decent article on the topic, which states:

A good rule of thumb is to use a salt that is the same size as the output of the hash function. For example, the output of SHA256 is 256 bits (32 bytes), so the salt should be at least 32 random bytes.

John Wu
  • 9,101
  • 1
  • 28
  • 39
  • John, Just a few comments to you answers: 1. HMAC - whether the key is public or private is just interpretation. e.g. if you want to prove the hashed message authenticity, then you have to reveal your key and it will not be private anymore. 2. dictionary attack and rainbow attack are basically the same with different data format in the database 3. I am still not convinced: Linux based systems use hash(password+salt) based values using HMAC is more sophisticated because wiki: "because the outer application of the hash function masks the intermediate result of the internal hash" 4. I agree – toni77 Nov 16 '16 at 21:58
  • Sorry toni77, the statements in your comment are absolutely wrong. Please do a bit of research, or start another question on security.stackexchange if you'd like more details. – John Wu Nov 16 '16 at 22:12
1

It's very unsafe. Your proposed use of HMAC, from a safety point of view, is identical to the experiment in this video—almost trivial to crack in practice.

In addition to that, using the username as a salt is a problem, albeit a lesser one. It means that the same username + password combination on two different sites produces the same verification tag, which allows somebody who gets the password databases to tell that this user reuses passwords across sites. This is one reason why random salts are probably best.

Luis Casillas
  • 10,181
  • 2
  • 27
  • 42
0

That is the wrong question. You are inventing your own secure password storage scheme. You should stop immediately. Use a good vetted method like argon2, scrypt, bcrypt or at worst pbkdf2 with the parameters adjusted to take as much CPU time and RAM as you can afford while keeping up with requests.

Z.T.
  • 7,768
  • 1
  • 20
  • 35
  • 1
    He didn't list what he was using. But how is using a hashing algorithm that allows HMAC (SHA512 for example) inventing your own? While I would not recommend using just the ID, with a random long enough key it can create enough entropy that would take centuries to crack. – Bacon Brad Nov 16 '16 at 14:19
  • Z.T., You listed here password based key derivation functions, but I was about to store hash of the password, not a whole private key. In HMAC the H stands for hash and the underlying hash algorithms can be: SHA-1, SHA-256, SHA-512, MD5, etc. By the way, in password based key derivation functions the salt is a general parameter, in each algorithms we see that, whereas, for password hashing I did not see a salt yet. That is why I was interested if the HMAC's key is a proper way for salting... – toni77 Nov 16 '16 at 16:12
  • Baconface, thanks, now I am convinced not to use just the userid for keys for HMAC, because I cannot control the size, too, and if the userid size is smaller than the underlying hash algorithm block size, then it is just zero-padded. Definitely a random value, as you and Mr. E. stated, better... – toni77 Nov 16 '16 at 16:15
  • What for do you want to store hash of password? So a GPU rig can break it? 300 gigahashes per second on recent GPUs! You want to use something like scrypt which will of course use a long random salt and not do any of the other errors you're going to do with your scheme. – Z.T. Nov 16 '16 at 18:45
  • @baconface If he used a good password hashing implementation, he would not have a choice about how and when to generate salt: all good libraries generate a long random salt every time you change the password or change the work factor. The fact that he can make the wrong choice (never changing salt) means he uses a low level API (probably a naked hash function) instead of a password hashing library. Doing that is a mistake. If you have long secure random, there is no added benefit to also hash the user id, so don't do that, just use `/dev/urandom`. – Z.T. Nov 16 '16 at 22:11
0

NO, IT IS UNSAFE

This answer is to summarize the findings from the others who contributed here.

  1. HMAC is not designed to be a password hashing algorithm. In spite of the fact that the algorithm is very similar to how Linux calculates hashes of passwords in the /etc/shadow file, HMAC does only one iteration, whereas Linux does hundreds or thousands of iterations, therefore HMAC lacks the slowness requirement. Please check the reference question on password hashing
  2. Use bcrypt or other specific password hashing algorithm, with considerable iteration count and long enough salt.
  3. The salt should be at least the size of the underlying hash functions block size
  4. The user id is not a good salt.
  5. The salt should be changed every time the password is changed.
toni77
  • 179
  • 1
  • 8
-3

NO

Don't do this it's silly everyone has access to the public part of an asymmetric key pair. Thats the idea.

A salt should never been revealed to anyone or your can use a RAINBOW table to crack it SHA-1 falls over very easy like this.

https://hashkiller.co.uk/sha1-decrypter.aspx

  • 2
    Salts are not required to be made secret - a rainbow table is not a huge help to an attacker because he would have to build a fresh rainbow table just for the one salt, which ends up being a bruteforce attempt anyway, so the attack is back to the same place as if they didn't have a rainbow table (cracking the hash fresh once the password hash is in hand). – schroeder Nov 16 '16 at 21:50
  • https://en.wikipedia.org/wiki/Salt_(cryptography) – Mark Edgar Nov 16 '16 at 22:05
  • "In cryptography, a salt is random data that is used as an additional input to a one-way function that "hashes" a password or passphrase. Salts are closely related to the concept of nonce. The primary function of salts is to defend against dictionary attacks or against its hashed equivalent, a pre-computed rainbow table attack." – Mark Edgar Nov 16 '16 at 22:07
  • 2
    Yep, I know and agree with all those points - but at NO point does that suggest the salt needs to be kept secret. How can you create a rainbow table before you know what the salt is? A rainbow table suggests that one can pre-compute hashes of a range of passwords. A salt makes this impossible. You would have to find out what the salt was *then* generate a rainbow table, which offers 0 benefit. You end up simply bruteforcing the salt+hash fresh. – schroeder Nov 16 '16 at 22:22
  • The only point where knowing the salt beforehand is a benefit is if that salt is in fact a pepper, and is used for all hashes and does not change. Then, once you know the pepper, you can pre-compute a rainbow table for that password database. – schroeder Nov 16 '16 at 22:27