21

I have no cyber security knowledge whatsoever, and am trying to safely store passwords in a database. I understood I need to use salt, to avoid rainbow table attacks and to make sure two users with the same password will have different password hashes.

However, does the complexity of the salt matter? I was planning on simply using the user's id (an integer that's incremented each time a new account is created), but is it good enough, or should I generate a more complex salt?

Anders
  • 65,052
  • 24
  • 180
  • 218
Oscar Sjöstedt
  • 313
  • 2
  • 5
  • 16
    No offence, but if you “have no cyber security knowledge whatsoever”, then I don’t want you anywhere near my passwords. There is a lot more to safely handling passwords than using a good salt to store them. I hope this is just for practice, not for a production system. (On the other hand, your second sentence indicates that you do have *some* cyber security knowledge.) – Brian Drake Nov 09 '20 at 13:35
  • 1
    This is mainly for practice! And yes maybe I have _some_ cyber security knowledge, by which I mean I read a little bit about it on a couple websites – Oscar Sjöstedt Nov 09 '20 at 13:43
  • 1
    In that case, there’s probably no reason not to share. Consider posting relevant code here or to [the code review SE](https://codereview.stackexchange.com/) to learn more. – Brian Drake Nov 09 '20 at 13:47
  • Maybe related to the topic https://crypto.stackexchange.com/questions/1776/can-you-help-me-understand-what-a-cryptographic-salt-is – O.Badr Nov 09 '20 at 21:42
  • @O.Badr How about [an answer on this site](https://security.stackexchange.com/a/36838/244958)? – Brian Drake Nov 10 '20 at 11:53

3 Answers3

44

The important part

The fact that you are generating salts on your own is a red flag. The best way to do this, especially if you have little experience with security, is to use an established library for password hashing.

A well-designed library will generate and use salts automatically for you, and it will store the salt and the hash in the same string, that you put in one column in your database.

So, use a slow algorithm designed for password hashing, and use an established library, and you won't have to think about how to generate the salt.

The answer

Still, I should answer your question. Does it matter if the salt has high entropy? There are two properties that we may want the salt to have here, that randomness helps with:

  • Unique, in your database, between password changes and preferably globally, so that an attacker can only crack one password at a time.
  • Unknown to the attacker (before a breach), so that an attacker targeting a specific account can not start any preparatory work before the database is leaked.

Using a counter as salt is a decent solution, but not perfect. The salt is at least locally unique, but it's not globally unique or even unique over multiple installations of the same software. It's not unknown to the attacker, but that really isn't such a big issue. Once the hash is leaked, the salt will be leaked too.

But still, using a library that gives you a random salt will be better. Don't mess around with homebrew solutions for something as important as this!

Anders
  • 65,052
  • 24
  • 180
  • 218
  • Okay, I will do so, thank you! Still, I was interested in knowing how it works, even if I end up using a library in the final product. – Oscar Sjöstedt Nov 08 '20 at 14:58
  • 4
    @OscarSjöstedt As long as the salts are unique, you get almost all of the benefits. However, if an attacker is targeting a specific account, if the salt is known (e.g. its the user id) the attacker can start making rainbow table or computing hashes for that specific account even before the breach, giving them more time. I would not consider that a big issue, though. – Anders Nov 08 '20 at 16:04
  • @OscarSjöstedt I updated my answer to be more of an actual answer to your question. – Anders Nov 09 '20 at 08:28
  • 11
    Using a counter is even more problematic if you plan on running many instances of the same program, say if you are writing a CMS or a forum software. Likely the first few accounts will always be generated in the same order and include some sort of admin-account with additional powers. If you use a counter as salt, this means that all these admin accounts have the same salt, which makes calculating the one corresponding rainbow table much more valuable. – mlk Nov 09 '20 at 12:56
  • @mlk Thanks for the good input. This was sort of what I had in mind, but I had not formulated it very clearly. I have updated the answer to reflect this better. Again, thanks! :-) – Anders Nov 09 '20 at 15:07
  • "Unknown to the attacker" until, ya know, it isn't... – corsiKa Nov 09 '20 at 23:03
  • What's the difference between a password and salt that is unknown to the attacker? (Other than that a password is generally known to the user) – Acccumulation Nov 10 '20 at 03:24
  • 1
    @Acccumulation The salt is not secret, but also not shown to the attacker at will. The reason why you don't want to show your salt is to prevent attackers from already pre-generating hashes without even cracking he database. But you don't take any special steps to "encrypt" the salt because that'd be useless anyways. –  Nov 10 '20 at 10:45
1

Yes it does matter, Using a known salt or like you are using by incrementing id is not much secure. You should use a random salt. You some salt generator alog/libraries etc.

semw
  • 47
  • 2
1

TL;DR: it's not good enough, instead let your salt be 10 bytes of /dev/urandom.

the salt does matter, and an user id is "not good enough" - it's much better than no salt at all, but to imagine a scenario where "uid as salt" is not good enough, imagine that multiple systems used salt is uid, and uid 0 is admin user (for example, on all linux systems, uid 0 is the admin account known as root), if Linux used uid as the salt for password hashes, i guarantee there would be rainbow tables out there for the 0-salt to attack root passwords, you'd probably even be able to google the hashes if that were the case, defeating the purpose of the salt :)

(another popular uid in Linux is uid 1000 or 1001, which is usually "the first user account", and the first user account is usually an account with sudo-access)

user1067003
  • 564
  • 4
  • 11
  • 1
    Why do you make this very specific recommendation: “10 bytes of /dev/urandom”? Why 10 bytes? What if the developer is using a high-level language where there is a better way of getting entropy? – Brian Drake Nov 10 '20 at 13:32
  • 1
    @BrianDrake well 10 bytes is way more than enough, but i don't know what the lower limit is (maybe even 4 bytes is good enough, i don't know, but i know that 10 more than enough), as for `/dev/urandom`, i meant the concept of /dev/urandom: `cryptographically secure random bytes`, regardless of the source (/dev/urandom is just a famous source - less famous sources include the linux api [getrandom](https://man7.org/linux/man-pages/man2/getrandom.2.html), the windows api CryptGenRandom, the openssl api [RAND_bytes](https://www.openssl.org/docs/man1.1.0/man3/RAND_pseudo_bytes.html), etc) – user1067003 Nov 10 '20 at 13:46