12

I'm helping my friend with hashing his passwords, and I've a question - Should he use one secret string as salt for hashing or is it better to have each user its own salt for hashing?

Consider these three hashes:

hash("secretKey777" + password);
hash("secretKey777" + username + password);
hash(username + password);

Which one is the hardest to crack and the safest?

I think it's best to use hash("secretKey777" + username + password); because for each user not only has "secretKey777" as a salt but also its own username. In case code that hashes the passwords leaks, there will be no attack on all the hashes at once - each has will have its own unique salt.

7
  • 1
    There's some related info here: security.stackexchange.com/questions/58704/…
    – paj28
    Commented Oct 10, 2014 at 22:20
  • 3
    Please don't hash passwords yourself. Cryptographers have already built tools that handle all of the details for you. TL;DR: use bcrypt. Commented Oct 10, 2014 at 22:23
  • 1
    Yes a username would be good enough. The point of salting a password is to increase the bruteforce effort by a multiple of however many unique salts there are in the system. Some will insist that salts must be unique, but the point is to increase effort, thus deterring the attacker. Commented Oct 11, 2014 at 3:55
  • See also this ancient answer on SO - stackoverflow.com/a/536756/10080 (it predates security.se...)
    – AviD
    Commented Jun 21, 2015 at 19:05
  • what if a user change its username?
    – giammin
    Commented Nov 2, 2016 at 9:43

5 Answers 5

10

The primary characteristic of a salt is that it should be globally unique for each user's password hash. It need not be secret, and a username will certainly not meet the required criteria of uniqueness. A shared secret string (used for all users) is not a salt, but a pepper, and has not been demonstrated to add any security over unsalted passwords, and so is not a viable option.

One construction that has the property of being particularly likely to be globally unique is random data of reasonable length. The salt doesn't actually need to be random, but a random value, generated individually for each user gives us reasonable assurance that we have the uniqueness we need.

There's a bit more in this answer: What should be used as a salt?

10
  • 13
    Usernames are usually unique. Why do you say they will not meet the required criteria of uniqueness? Commented Oct 10, 2014 at 22:29
  • 1
    @bodacydo, you will generate a random salt value one time and store it in an unencrypted format along with your hashed password. This way you an access the salt whenever authentication needs to take place. Commented Oct 10, 2014 at 22:32
  • 7
    @AbeMiessler Usernames are not globally unique. The requirement for a salt is not just that it's unique for your application, but it's unique for all applications everywhere.
    – Xander
    Commented Oct 10, 2014 at 22:34
  • 1
    @AbeMiessler I think simple argument backs him up - if its not unique for all applications, then googling the hash "XXXusername" will find password for XXXusername in another database.
    – bodacydo
    Commented Oct 10, 2014 at 23:47
  • 2
    @AbeMiessler security.stackexchange.com/a/31846/10211 Scroll to the section on Salt Generation.
    – user10211
    Commented Oct 11, 2014 at 2:56
7

Someone had mentioned that the salt need not be secret, just unique across all applications and that a username doesn't meet that requirement.

My suggestion then is to use a combination of your domain name and the user's username as salt:

"example.comsomeuser777" This is both unique to the user and unique to the application.

Require the user to enter their password if changing their username.

2

Should he use one secret string as salt

No. One hard-coded side wide salt does prevent pre-calculated rainbow table attacks, but those are not really a major concern nowadays. The main advantage of using a random salt for each hashed password is that an attacker when bruteforcing has to hash each password with each salt, instead of just hashing once and checking against all passwords. So it slows the attack down by a factor equal to the number of users.

each user not only has "secretKey777" as a salt but also its own username

Don't use usernames as hashes. It doesn't really impact security[*], but it does have an effect on usability and maintainability. What if a user want's to change their username? This wouldn't be possible with your approach.

[*] except for the point @Xander made. It is an impact, but it is quite low.

So what is the correct approach?

hash(password+ generateRandomSalt());

And store the salt next to username and password in the database. You could also use a library that manages all of this for you (for example if you are using PHP, password_hash uses bcrypt and manages the salts for you).

2
  • 1
    "What if a user wants to change their username?" Require that they enter their password when they change their username, then recalculate and update the salted hash along with the username. Or use whatever long-lasting unique identifier you have for the user, presumably if users change their usernames you have some other immutable ID for them.
    – MikeFHay
    Commented Mar 22, 2018 at 14:05
  • If app need to store the time of user account creation, maybe that can also be used in salt creation
    – proseosoc
    Commented Jul 17, 2022 at 10:17
1

Other answers have addressed well the reasons why you should at least use a unique salt for each user. They seem less convincing on why that should not be the username.

Within the confines of a single system/site, the username will be unique, and might seem sufficient as a salt. There's indeed not any particular reason why it would be inadequate in that case -- except one: if you have some well-known usernames (like "root" or "admin") then you've lost the uniqueness property and you're vulnerable to rainbow tables again, defeating the main purpose of a salt.

However, that's not the only consideration. What happens if everyone starts doing this -- or even just a few popular sites?

The main problem with using a username as salt is that if multiple sites did this, and their hashes are leaked, it is immediately obvious when a user has used the same username+password across multiple sites and is thus a high-value target, because their hash only needs to be cracked once to gain access to all the sites. Crackers can and do compare leaked data from multiple sites, so you can't consider each one in isolation.

Using a random salt avoids this problem: even if someone did use the same username+password, the resulting hash will be different and not expose this property.

Regarding combining a (random) salt with both the username and password: this may be stronger than omitting the username, but only really by virtue of making the salt longer -- in principle (for salt+password alone) increasing the salt length by the username length would be even better. In practice, neither one makes much difference unless your salt wasn't long enough to begin with.

6
  • The lack of global uniqueness isn’t the only problem of usernames – this could be solved with a application-specific prefix, as some have suggested. Usernames are also fairly predictable and therefore allow an attacker to create lookup tables ahead of time. This is relevant for short-lived passwords: If a user changes their password before a brute-force attack is complete, then the attacker generally cannot gain access to the account. However, if the salt is predictable, then the attack can begin before the user is registered, so there may now be enough time to complete it.
    – Ja1024
    Commented Sep 5 at 7:11
  • @Ja1024 This isn't, to my understanding, considered a practical attack at all. The resources to create a lookup table like that which is usable only for one user would be much more efficiently spent elsewhere. And there are protocols, such as SRP, that use a public salt yet are still considered secure by most people.
    – n-l-i
    Commented Sep 5 at 7:25
  • @n-l-i: Who said public salts are a problem? My point is that they have to be unpredictable, i.e., random. Storing the salt as plaintext is perfectly fine, they’re not secret data. As to your argument that lookup tables are impractical: The calculations are the same as in a brute-force attack, they just happen in advance and require space – it’s a classical time/space tradeoff. I know there this idea that any kind of halfway unique salt immediately defeats all lookup tables, but this is a myth.
    – Ja1024
    Commented Sep 5 at 7:37
  • @Ja1024 But what is the benefit of it being unpredictable if anyone can get access to it whenever they want to? Seems to me like they might as well be predictable in that case.
    – n-l-i
    Commented Sep 5 at 9:02
  • @n-l-i: Predictability means the salts are known before the users are even registered, maybe even before the application has been implemented. Unpredictable (but public) salts are only known once a user account actually exists. In the second case, a brute-force attack against the specific account is limited to the time between the registration and a password change. In the first case, there's no such time limit.
    – Ja1024
    Commented Sep 5 at 9:10
-1

Assume that everybody uses this methods. And many users use the same username and password, and therefore the same hash, on multiple sites. And one site, totally unimportant by itself, is insecure and allows an attacker to download a list of usernames, passwords and hashes.

Now the attacker can visit all kinds of websites and try the username/hash combinations and will be able to login whenever a user also used that insecure site.

The goal should be that your hashes are different from the hashes on any other site. If you pick just one random salt for your application then you achieve this. But not with the username as the salt.

1
  • No, the goal is that each hash has a unique salt. If you reuse the same salt for all hashes, then an attacker can still reuse hash calculations across all accounts on your site, which massively increases the efficiency of a brute-force attack (something salts are supposed to prevent). The attacker just cannot reuse calculations across different sites.
    – Ja1024
    Commented Sep 5 at 16:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .