10

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.

bodacydo
  • 849
  • 9
  • 16
  • 1
    There's some related info here: http://security.stackexchange.com/questions/58704/can-client-side-hashing-reduce-the-denial-of-service-risk-with-slow-hashes – paj28 Oct 10 '14 at 22:20
  • 2
    Please don't hash passwords yourself. Cryptographers have already built tools that handle all of the details for you. TL;DR: [use bcrypt](http://codahale.com/how-to-safely-store-a-password/). – Stephen Touset Oct 10 '14 at 22:23
  • 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. – Andrew Hoffman Oct 11 '14 at 03:55
  • See also this ancient answer on SO - http://stackoverflow.com/a/536756/10080 (it predates security.se...) – AviD Jun 21 '15 at 19:05
  • what if a user change its username? – giammin Nov 02 '16 at 09:43
  • @StephenTouset Or [Argon2](https://en.wikipedia.org/wiki/Argon2), as tends to be the current advice :) – Nic Jul 12 '19 at 15:19

3 Answers3

9

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?

Xander
  • 35,616
  • 27
  • 114
  • 141
  • 12
    Usernames are usually unique. Why do you say they will not meet the required criteria of uniqueness? – Abe Miessler Oct 10 '14 at 22:29
  • Thanks for the answer. I'm confused about how to use a random value for salt. The problem is ... it's a random value ... I can only generate it once and after I hash the password I no longer know what the salt was. What did I get wrong? – bodacydo Oct 10 '14 at 22:31
  • 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. – Abe Miessler Oct 10 '14 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 Oct 10 '14 at 22:34
  • Oh interesting, I had never heard that. Even in the link you suggest the answer says, `unique for each entry` no unique `for all applications everywhere`. Not that I doubt you, but would it be possible for you to provide a link that backs your statement up? – Abe Miessler Oct 10 '14 at 23:19
  • 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 Oct 10 '14 at 23:47
  • 2
    @AbeMiessler http://security.stackexchange.com/a/31846/10211 Scroll to the section on Salt Generation. –  Oct 11 '14 at 02:56
  • 1
    Essentially, "using username as a salt enables attackers to build a username-specific rainbow table that can be used to crack passwords for *that username* across all sites that contain *that username* and use the same password-hashing algorithm with username as salt". Is this the correct interpretation? – ManRow Apr 09 '20 at 12:51
  • site:user is globally unique. not need to store it. – Erik Aronesty Mar 01 '23 at 14:05
6

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.

Robert Talada
  • 175
  • 1
  • 5
0

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).

Isantipov
  • 103
  • 3
tim
  • 29,122
  • 7
  • 96
  • 120
  • 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 Mar 22 '18 at 14:05
  • If app need to store the time of user account creation, maybe that can also be used in salt creation – proseosoc Jul 17 '22 at 10:17