2

Based on: https://security.stackexchange.com/a/33520/42220 and https://security.stackexchange.com/a/41630/42220

I can see the benefits of a completely random salt per user.

If I am implementing an application that will only ever be used by one user per database, is there any point in having a randomly generated salt?

If the salt was a string, e.g. a permanent, non-changing GUID, that is generated when an initial password is provided for the first time, can this safely be reused for this user every time?

Surely if the salt was randomly generated, it would need to be stored alongside the encrypted user password and user ID, which would mean the attacker has access to the salt from the database, which is just the same as if they reverse engineered the source code and saw a single, hard-coded salt in there?

  • 2
    Unique salt per user per password. That's the standard; stick to it. – Adi Mar 25 '14 at 12:48
  • If it's really "one user per database" then why are you implementing your own authentication system and not using the authentication functionality already in the DBMS? – symcbean Mar 25 '14 at 13:09
  • @symcbean because the application will be used on a personal mobile device where data will be stored (cached) offline. – Adam Marshall Mar 25 '14 at 13:55

4 Answers4

4

Both using a random salt and several hash computations or another delaying strategy (bcrypt, scrypt, whichever) make sense not only for many users, but certainly also for one user.

Salt prevents an attacker from trivially entering your hash into Google to get an instant password without even using a tool. A good random salt makes it less likely that you've chosen one that someone else has built a rainbow table for the value anyway (such as for some obvious salts that you might see, like user IDs).

Having a different, random salt for every user prevents an attacker from reusing hashes in a rainbow table (or using a rainbow table for a specific salt that already exists readily). It forces to brute-force each individual user. You can't prevent someone from continuing a brute-force attack, and it will eventually be successful (since even "strong" passwords are relatively weak). But the longer it takes to brute-force one user, the safer the remaining ones are (if it takes 2 seconds to brute-force one user, you can do 1000 users in a few hours -- if it takes a week per user, things look much better). That is the whole point of using something like bcrypt.

Now if there is only one user, brute-forcing the first user means a 100% compromisation.

Therefore, using a strategy that delays brute-force is at least as important as with a many-user database (but conceptually more important).

Something like a GUID will do fine, it does not matter whether you store the "string" somewhere or whether you reuse it when the same user changes password. A salt needs to be accessible in some form so you can validate the password. Sure, it would of course be nice if you could keep it secret, but that is neither possible nor necessary for its purpose. Also, if someone can steal the salt, they will also have the hashed password, since that is usually stored in the same place. Insofar, there is no "additional risk" that someone might maybe prepare a rainbow table ahead of time for that known salt (before stealing the actual password). With that said, if you feel uneasy, it does not really cost anything to also change the salt every time the user changes password.

The purpose of the salt is not encryption of some kind but to thwart rainbow tables, which make inverting the hash function a trivial operation.

In principle, hardcoding a "randomly chosen" salt directly as you propose would be just as good for your one-user scenario. However, this is a bad approach since there is the possibility that you will eventually reuse the code for something else (a different project of yours) or that you will eventually have more than one user.

You may not see this coming right now, but it is generally a possibility.

Now the thing about things that may happen is that eventually they will happen. So if you directly hardcode a single salt since there's only one user anyway, you will eventually have a security hole, maybe in 10 years from now when you don't even think about it any more.
As soon as you use the same salt for several users or for a single user in several projects, it is pretty useless. You should simply not make it possible for that to happen.

The same applies, of course, to the approach of having a "permanent" salt which you use everywhere, say, for the remainder of your life. This is an open invitation to building a rainbow table, since doing so will save computional work. Attacking one of your passwords will be more or less the same workload as attacking all passwords in your lifetime.

Damon
  • 5,001
  • 1
  • 19
  • 26
4

When you do not salt (or pepper) the password, the password isn't very strong and an attacker obtains the hash, it can be cracked by just looking up the hash in a rainbow table (a precomputed list of the hashes of the most common passwords which can be found online). But when you add some additional data to the password, a precomputed rainbow table is useless and an attacker has to compute the hash of every common password themself, which takes considerable processing time, especially when you use a slow hash function (which is recommended).

When your salt is always the same (which means it is a "pepper") and an attacker obtains that pepper, they can precompute a rainbow table for that pepper which can be used to crack any future password hashed with the same pepper. When your application is widely-deployed and each deployment uses the same pepper, it would be feasible for an attacker to precalculate such a table in order to increase efficiency when targeting multiple deployments. When your application is only a single instance, such a rainbow table could still be useful. A possible attack scenario would be when there would be some vulnerability which leaks the hash and you don't know about that vulnerability. Without a rainbow table, it might take a long time for an attacker to crack the new password after each password change, which would buy you some time to find and fix the problem. With a rainbow table, it would only take seconds to crack any new password you set.

Philipp
  • 48,867
  • 8
  • 127
  • 157
  • Because this question is indeed useful, I won't downvote it. However, it doesn't really answer the question. Please note that the OP isn't asking whether he should use salts or not. I'd like to politely ask you to read the question again. – Adi Mar 25 '14 at 13:02
  • @Adnan I ammendet my answer – Philipp Mar 25 '14 at 13:14
2

It is always a good idea to salt since you don't want a pre-established table against that algorithm to be beneficial in attacking the password. If your password gets compromised because a rainbow table was built against the previous salt, then changing the password wouldn't be effective.

You need to choose a new salt in order to render any existing effort against the hash null and void.

AJ Henderson
  • 41,816
  • 5
  • 63
  • 110
-1

If I am implementing an application that will only ever be used by one user per database, is there any point in having a randomly generated salt?

Yes, salting passwords is always a good idea. It doesn't matter how many users there are. If an attacker gets hold of your database and your hashes are not salted, he has an enormous advantage, because there might be rainbow tables and other techniques to get a match for the hash values just obtained. Salted passwords on the other hand do provide security, because the salt is not known to the attacker in advance.

Think of it in terms of good practice, because your system might end up being adopted and used by more people.

Surely if the salt was randomly generated, it would need to be stored alongside the encrypted user password and user ID, which would mean the attacker has access to the salt from the database

That's not a problem at all and is usually the way it is done. An attacker has no advantage in knowing the salt - at least as long as the hash function itself is not fundamentally broken.

Karol Babioch
  • 1,247
  • 8
  • 10