161

I've always been curious... Which is better when salting a password for hashing: prefix, or postfix? Why? Or does it matter, so long as you salt?

To explain: We all (hopefully) know by now that we should salt a password before we hash it for storage in the database [Edit: So you can avoid things like what happened to Jeff Atwood recently]. Typically this is done by concatenating the salt with the password before passing it through the hashing algorithm. But the examples vary... Some examples prepend the salt before the password. Some examples add the salt after the password. I've even seen some that try to put the salt in the middle.

So which is the better method, and why? Is there a method that decreases the chance of a hash collision? My Googling hasn't turned up a decent analysis on the subject.

Edit: Great answers folks! I'm sorry I could only pick one answer. :)

Adam Marshall
  • 2,542
  • 7
  • 32
  • 70
Randolpho
  • 52,575
  • 15
  • 139
  • 173
  • 1
    See also: http://stackoverflow.com/questions/1645161/salt-generation-and-open-source-software/1645190#1645190 – Jacco Aug 11 '10 at 07:49
  • you could use this: http://encrypto.codeplex.com/, that's for .net – Omu Sep 14 '10 at 08:31
  • @Omu: Hmm... that uses a 4-byte random salt, and stores it with the hashed password. The latter is clever, but the former... I think that might be a little low. Still, useful if you want quick and dirty password hashing. – Randolpho Sep 14 '10 at 14:21
  • @Randolpho you can specify the salt size, 4 byte is by default – Omu Sep 14 '10 at 14:36
  • @Omu: Ahh, you're correct. I missed that. – Randolpho Sep 14 '10 at 15:55
  • 3
    The best practice is to use a cryptographic function that does the salting for you, using either PBKDF2 (the standard), bcrypt or even scrypt. Thanks to Stephen for pointing that out. – Maarten Bodewes Aug 13 '12 at 00:04
  • 1
    Pretty much all standard password hashing constructions take care of combining salt and password, so you shouldn't worry about this. If you don't use a standard password hash, migrate to one. – CodesInChaos Aug 16 '13 at 16:06
  • 1
    @Omu Bad recommendation. 1) A single iteration of SHA-1 is too fast, you should use at least 10000, and even that's pretty weak. 2) Default salt is too small. 8 bytes is minimum and 16 is recommended. – CodesInChaos Aug 16 '13 at 16:09
  • 1
    Related: [Does prepending a salt to the password instead of inserting it in the middle decrease security?](http://security.stackexchange.com/q/11625/38016), [Salt placement prior to one-way hash](http://security.stackexchange.com/q/40523/38016), [How to securely hash passwords?](http://security.stackexchange.com/q/211/38016) – Piotr Dobrogost Aug 04 '14 at 15:09
  • Please fix the link .Its not working :| – Shekhar Pankaj Nov 11 '16 at 08:53
  • @ShekharPankaj both links in my post still work perfectly for me. – Randolpho Nov 14 '16 at 11:38

8 Answers8

112

Prefix or suffix is irrelevant, it's only about adding some entropy and length to the password.

You should consider those three things:

  1. The salt has to be different for every password you store. (This is quite a common misunderstanding.)
  2. Use a cryptographically secure random number generator.
  3. Choose a long enough salt. Think about the birthday problem.

There's an excellent answer by Dave Sherohman to another question why you should use randomly generated salts instead of a user's name (or other personal data). If you follow those suggestions, it really doesn't matter where you put your salt in.

Community
  • 1
  • 1
Georg Schölly
  • 116,521
  • 48
  • 204
  • 258
  • As a non-security guru, I don't really get point 1. Is hashed_pw = hash(canned_salt + login + password) sufficient, or do you need to store your salt along with the password? Any pointers to why? – wowest Mar 23 '09 at 19:50
  • 4
    I've added a link to an old question, read those answers. Basically, by not using a different random salt per password you're taking an unnecessary security risk, that might be a real problem in the future. – Georg Schölly Mar 23 '09 at 19:59
  • If you read his answer, he is saying you should use a random salt versus their username or other user data. Having one side wide random salt is still valid. – Samuel Mar 23 '09 at 20:10
  • Should be secure enough, unless you have a lot of users and a hacker creates a rainbow table, just for your site. – Georg Schölly Mar 23 '09 at 20:15
  • Yes, still very secure. You just might want it to be more secure so you could generate a salt for each user. – Samuel Mar 23 '09 at 20:27
  • 39
    Site-wide random salt is bad, since an attacker can precompute rainbow tables and grab your entire user database. If you don't understand this, please don't write login/security systems :) - you NEED per-user salts. – snemarch Mar 23 '09 at 20:52
  • 3
    Yes, per-user salt. Ideally, with per-user iterations stored (so you can increase the number of iterations used over time). Any decent framework will have this built-in. (.NET has PasswordDeriveBytes which will handle everything for you.) – MichaelGG Mar 23 '09 at 23:27
  • You don't need salts at all. You *should* have salts. And as to if you need per user salts, it all depends on the incentive for someone to compromise your user accounts. If there is a huge incentive, you need per user since it will be very costly to compromise all users. – Samuel Mar 23 '09 at 23:41
  • "You don't need salts at all" - heck, you don't need hashing at all, if you think you can keep your database secret ;-) – Steve Jessop Mar 23 '09 at 23:52
  • 2
    If you're designing any kind of security system, it's braindead not using per-user salt. *your* site might not be super-interesting, but consider users using the same password on multiple sites... trying to keep the database safe tends to fail :) – snemarch Mar 24 '09 at 00:30
  • Salts don't protect against dictionary attacks, only against rainbow-tables. But he's right that it makes such an attack much slower. – Georg Schölly Mar 24 '09 at 16:27
  • 2
    Of course salts protect against dictionary attacks, precisely by making them much slower. The use of salts in passwords far predates rainbow tables. Salts were added specifically to slow down dictionary attacks, by preventing attackers from hashing a password once then comparing it against all users. – Glenn Maynard Mar 05 '12 at 16:20
  • An attacker could precompute MD(pass) for many frequently used passwords and then compute MD(pass+salt) at a cheaper price for every salt in the password database because message digests work in an incremental way so as to support streaming. – Erwan Legrand Dec 18 '13 at 13:23
27

I think it's all semantics. Putting it before or after doesn't matter except against a very specific threat model.

The fact that it's there is supposed to defeat rainbow tables.

The threat model I alluded to would be the scenario where the adversary can have rainbow tables of common salts appended/prepended to the password. (Say the NSA) You're guessing they either have it appended or prepended but not both. That's silly, and it's a poor guess.

It'd be better to assume that they have the capacity to store these rainbow tables, but not, say, tables with strange salts interspersed in the middle of the password. In that narrow case, I would conjecture that interspersed would be best.

Like I said. It's semantics. Pick a different salt per password, a long salt, and include odd characters in it like symbols and ASCII codes: ©¤¡

Tom Ritter
  • 94,954
  • 29
  • 130
  • 168
  • @onebyone, damn! He's discovered my salt of 'passwordsalt'! – Samuel Mar 23 '09 at 23:44
  • 6
    @Samuel: I don't know about you guys, but we use '12345' for our salt. :) – Randolpho Mar 24 '09 at 13:35
  • @onebyone valid. I really meant "common" as "all salts under length X in characterset Y" where X, Y are reasonable; say 20 chars and alphanumeric upper/lowercase. Extendable to say all hexadecimal strings under length Z (say 160) since I think a rainbow table of hashed hashes would be useful.. – Tom Ritter Mar 24 '09 at 13:51
  • 1
    @Randolpho: Hey, that's my salt, too! What're the odds? – Adrien May 26 '09 at 23:08
  • And make sure the salt is non-predictable/Random : http://stackoverflow.com/questions/1645161/salt-generation-and-open-source-software/1645190#1645190 – Jacco Dec 26 '09 at 13:25
  • Salting passwords far predates rainbow tables. – Glenn Maynard Mar 05 '12 at 16:49
18

The real answer, which nobody seems to have touched upon, is that both are wrong. If you are implementing your own crypto, no matter how trivial a part you think you're doing, you are going to make mistakes.

HMAC is a better approach, but even then if you're using something like SHA-1, you've already picked an algorithm which is unsuitable for password hashing due to its design for speed. Use something like bcrypt or possibly scrypt and take the problem out of your hands entirely.

Oh, and don't even think about comparing the resulting hashes for equality with with your programming language or database string comparison utilities. Those compare character by character and short-circuit as false if a character differs. So now attackers can use statistical methods to try and work out what the hash is, a character at a time.

Stephen Touset
  • 2,404
  • 2
  • 24
  • 24
  • 1
    Regarding the last paragraph: how could attacker get any info on the exact number of character the comparison has failed? This makes no sense.. – halloweenlv Nov 19 '17 at 02:11
  • 1
    You're both correct and incorrect. [Timing attacks](https://en.wikipedia.org/wiki/Timing_attack) are real and have been repeatedly demonstrated to be viable with frightening accuracy even over variable-latency network connections to determine exactly where the comparison failed. That said, timing attacks are not actually applicable to common password hashes, since it's computationally infeasible to find inputs that only change small parts of the output. – Stephen Touset Nov 21 '17 at 22:12
9

It shouldn't make any difference. The hash will be no more easily guessable wherever you put the salt. Hash collisions are both rare and unpredictable, by virtue of being intentionally non-linear. If it made a difference to the security, that would suggest a problem with the hashing, not the salting.

Phil H
  • 18,593
  • 6
  • 62
  • 99
  • 1
    Hash collisions depend on the size of the hash. Thanks to the birthday problem collisions are quite likely. – Georg Schölly Mar 24 '09 at 07:19
  • 2
    Only if you truncate the result. Anyway, I still stand by the point that it won't make a difference where the salt is, because the point of the hash is to make the relationship between input and output contain no patterns. – Phil H Mar 24 '09 at 09:27
7

If using a cryptographically secure hash, it shouldn't matter whether you pre- or postfix; a point of hashing is that a single bit change in the source data (no matter where) should produce a different hash.

What is important, though, is using long salts, generating them with a proper cryptographic PRNG, and having per-user salts. Storing the per-user salts in your database is not a security issue, using a site-wide hash is.

snemarch
  • 4,770
  • 24
  • 35
  • 2
    Wrong anwser: an attacker could precompute MD(pass) for many frequently used passwords and then compute MD(pass+salt) very cheaply because message digest work in an incremental way so as to support streaming. – Erwan Legrand Dec 18 '13 at 13:16
5

First of all, the term "rainbow table" is consistently misused. A "rainbow" table is just a particular kind of lookup table, one that allows a particular kind of data compression on the keys. By trading computation for space, a lookup table that would take 1000 TB can be compressed a thousand times so that it can be stored on a smaller drive drive.

You should be worried about hash to password lookup tables, rainbow or otherwise.

@onebyone.livejournal.com:

The attacker has 'rainbow tables' consisting not of the hashes of dictionary words, but of the state of the hash computation just before finalising the hash calculation.

It could then be cheaper to brute-force a password file entry with postfix salt than prefix salt: for each dictionary word in turn you would load the state, add the salt bytes into the hash, and then finalise it. With prefixed salt there would be nothing in common between the calculations for each dictionary word.

For a simple hash function that scans linearly through the input string, such as a simple linear congruential generator, this is a practical attack. But a cryptographically secure hash function is deliberately designed to have multiple rounds, each of which uses all the bits of the input string, so that computing the internal state just prior to the addition of the salt is not meaningful after the first round. For example, SHA-1 has 80 rounds.

Moreover password hashing algorithms like PBKDF compose their hash function multiple times (it is recommended to iterate PBKDF-2 a minimum of 1000 times, each iteration applying SHA-1 twice) making this attack doubly impractical.

Community
  • 1
  • 1
cygil
  • 3,456
  • 1
  • 16
  • 10
  • You should double check the description of rounds. The rounds are on a per chunk basis, not the entire message. (Otherwise, hashing streaming data would require rewinding again and again.) But using iterations does prevent the problem onebyone mentions. – MichaelGG Mar 25 '09 at 15:20
4

BCrypt hash if the platform has a provider. I love how you don't worry about creating the salts and you can make them even stronger if you want.

Samuel
  • 35,821
  • 11
  • 83
  • 84
2

Inserting the salt an arbitrary number of characters into the password is the least expected case, and therefore the most "secure" socially, but it's really not very significant in the general case as long as you're using long, unique-per-password strings for salts.

jeffcook2150
  • 3,780
  • 4
  • 37
  • 51