I'm working on a project where following constrains apply:

  • There's no remote database or any other means of storing extra data like random salt
  • When user logins in, only username and password are known and no extra information can be accessed until successful login

We decided to use scrypt and scrypt needs salt. Ideal solution would be to generate random salt but in this case we just can't store that value anywhere.

The system has been designed in a way that username is not stored at any point so if the system is compromised, there's no way of knowing which hash belongs to which username (in case usernames are compromised from other sources).

So the question is that would it be sufficient to use, for example, username+password as the salt?

  • Even when usernames are known to attackers they're pretty good as salt. The point of a salt is uniqueness. Username+site aren't perfectly unique since a user can have different passwords over time, but it's close enough in practice. – CodesInChaos Oct 28 '13 at 11:08
  • Doesn't scrypt bundle the salt and hash together anyway? Even if not, what is stopping you from storing a tuple? – lynks Oct 28 '13 at 11:40
  • There's no remote database? Scrypt generates its own salt as I recall. If the username is not stored, how do YOU know which hash to check for a successful login? – Jerry Saravia Aug 7 '15 at 2:23
up vote 3 down vote accepted

Reusing the password as part of the salt is, on a general basis, not recommended. The password is secret, and information may leak that way, depending on the internal details of the hash function. I suggest you refrain from it.

The username is, by itself, a not-too-good salt, but if you only have that, then use it. The one and only property of salts is uniqueness. When using the username as salt, you run the risk of salt collisions when:

  • The same username is used in two distinct systems (e.g. if each system instance has an "admin" user with that exact username, it becomes worthwhile for attackers to compute rainbow tables using "admin" as salt).

  • A user changes his password (old and new password then use the same salt, and an attacker may attack both in parallel).

If your usernames are unique worldwide (e.g. email addresses) then the first problem is avoided. A variant is to use as salt the username with, as suffix, a '@' sign followed by the server name. For password changes, you can diminish the intensity of the issue by the simple expedient of not requiring regular password changes from your users (these don't improve security anyway).

  • Good point about adding a suffix. What do you think about using scrypt to create a salt first from password using username+password as a salt for that? Of course there's no "new uniqueness" added but at least it would be way more expensive to brute-force it. – JohnC Oct 28 '13 at 11:18
  • @JohnC if you want to make it more expensive, you increase the work factor. Salts are about preventing precomputation attacks, not increasing the cost of brute forcing an individual hash. – lynks Oct 28 '13 at 11:43

Despite your claim of not having any means to store a salt, you do (possibly without realizing): You obviously are storing the username and the hash of each user's password. The same storage could be used to store one more item for each user, a random per-user salt.

You also do not need any additional information about the user to generate a salt. You only need a random number generator once, when the user account is created. Hence you only need a good source of entropy, which of course is more easily said than done on a headless server.

Maybe the confusion stems from the fact that the term "salt" is sometimes used in different meanings. Some authors seem to use the term "salt" for a global (constant) additional input used to calculate the password hashes. Whilst good enough to foil some rainbow attacks, that is not a very good way to implement a salt. A better way is to choose a different salt for each user. Many implementations, e.g. PHP's crypt function, even append the salt (and some hashing parameters) to the computed hash value for convenience, relieving you of having to separately store and retrieve the salt.

A few programmers dislike storing the salt in a database, arguing that the salt could protect in the scenario that an attacker obtains the password database but not some global salt possible hard-wired into the authentication code. I suspect you might be of this persuasion based on your comment about not having a remote database. Please consider that such an argument can be dangerous: If you build on the assumption that your password database may be compromised but some external source of information (the salt or salts) is not, then you are much better off securing your per-user password database as well as this additional store of per-user information. They fulfill the exact same function and hence should be equally easy (or hard!) to secure.

  • I get your point but without going more into the details, the system really doesn't actually know the password hash as-is. Sorry I can't be more specific but the username and password never leaves the client which is the reason we can't store anything else. We can't use client side storage because client side storage is tied to one specific device which won't work in our case. So it all has be based on username & password. – JohnC Oct 28 '13 at 11:48
  • Sorry to hear my answer wasn't helpful. I'd love to understand why! Anyways, surely you must store some per-user secret on your server to allow it to determine if an authentication succeeds or fails? If calculating a hash is involved in this, this secret (even if different from the hash) gives you an example of how you can store the salt. Conversely, if no hash calculation is involved, I don't understand what you mean by "salt." – pyramids Oct 28 '13 at 12:01

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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