1

I want to hash a set of sensitive data using a hash+salt. I've done a little research and now I know that:

  • The salt should be random.
  • The salt should not be reused.
  • Using hashing without salt makes it possible to use rainbow tables and dictionary attacks (using the top 10000 passwords, hashing them, and finding matches).

I've seen alot of libraries that store the salt alongside the data. In some cases as a prefix for the hash i.e. (salt.Hash).

I'm confused as to where you should leave the salt. Storing the salt with the hash itself seems illogical. What if the attacker reads the salt from the field, hashes his dictionary with the salt and then finds a match. It seems as just one easy extra step.

  • Yes, that extra step is the point. Because now they don't just need to hash the whole dictionary once, they need to do it once for every single password. – MechMK1 Oct 29 '19 at 9:36
  • So for every field there is a unique 10.000 dictionary needed. Somehow, this does not seem hard. – MichielDeRouter Oct 29 '19 at 9:39
  • I added an answer that hopefully explains the concept better. Please leave a comment if something is unclear or if you disagree with some part. – MechMK1 Oct 29 '19 at 9:51
3

Storing the salt together with the hash is fine. The salt is essentially public information. Many systems store it in a format like $hashAlgorithm$parameters$salt.hash.

But isn't this insecure?

No, because the point of a salt is not to be secret. The point for the salt is to be random and unique. It should increase the work factor for the attacker, not prevent an attack completely. Let me demonstrate this:

Scenario 1

Your database contains 1,000,000 users, all just having their hashes stored in plain SHA-1. An attacker compromises it. Their possibilities are now:

  • Perform a lookup-attack, meaning that the attacker just looks up the hash in a database of pre-computed hashes.
  • Perform an attack with a rainbow-table, which is a variant of the above-mentioned attack.
  • Hash a well-known list of passwords themselves (e.g. rockyou.txt), exactly once.
  • Brute-force weak passwords, or password in a common scheme, like an uppercase character, followed by 8 lowercase characters and one digit.

Scenario 2

Your database contains 1,000,000 users, all just having their hashes stored in Argon2 with a unique, random salt. An attacker compromises it. Their possibilities are now:

  • Hash a well-known list of passwords themselves (e.g. rockyou.txt), 1,000,000 times.
  • Brute-force weak passwords, or password in a common scheme, like an uppercase character, followed by 8 lowercase characters and one digit - 1,000,000 times.

It's not possible to do a lookup-attack, because nobody would store the hashes to millions of password, with millions of possible salt combinations. It's also not possible to do a rainbow-table attack, because building the rainbow table for every user with their salt would take longer than to just computer each hash.

Furthermore, just by adding a salt, you changed the amount of work required from "Hash once, check everything" to "Hash every time". In our scenario with 1,000,000 users, you made the task of the attacker 1,000,000 times more difficult.

|improve this answer|||||

Not the answer you're looking for? Browse other questions tagged or ask your own question.