Why is it safer to store passwords with a different salt for every password?
As passwords are hashed after being salted, I see no reason to use a different salt.
Is it easier to brute-force the password with a known salt or something? Or do hackers make their own rainbow tables once they know the salt?
Kind regards
When you give each password its own individual salt there is no common bond between every salt in every password. So even if the "hacker" cracks one password, he won't have a salt for any other password.
When it comes to using PHP and salting your passwords, you should use a slow encryption, such as crypt. The faster you encrypt something, the quicker the "hacker" can find a way to decrypt it.
You could simply a function that creates a new salt based on a person's username, email, or combination of a few things.
If you use only one salt, the hacker only has to rebuild their rainbow tables once and can use them for your entire database. Duplicate passwords will be easier to find, too.
Use individual hashes and an expensive algorithm (bcrypt, scrypt).
Ok, let's get one thing straight: Salting has nothing to do with rainbow tables. Yes. Say that again. Salting has nothing to do with rainbow tables.
Well, that's not entirely true. Salts are used to prevent time and memory tradeoffs by amortizing the cost of attacking one hash against the cost of other hashes.
In the case of a rainbow table, using a salt means that the entire table is invalidated.
But there are other ways of invalidating an entire table. You could append a static string to each password (which is not a salt). That would defeat rainbow tables...
The Real Enemy
The real enemy here is not rainbow tables. The real enemy is brute forcing. Modern day machines are so fast at brute forcing that it's cheaper to build a gigantic GPU cluster and do advanced brute-forcing than it is to store enough rainbow table to make it worth the slow disk access.
A salt helps defeat bruteforcing because it's unique. Not per password. Not per user, but unique in the universe (statistically at least). This is why you want to use a random number, and not the username, email or anything predictable.
Again, not because we don't want predictability. But because we want statistical uniqueness. If an attacker attacks two sites that both use usernames as salts, he can amortize his attacks against both hashes at the same time (even though both may be using different passwords).
Salts should be random, and per user.
Related
From this site http://codahale.com/how-to-safely-store-a-password/:
It’s important to note that salts are useless for preventing dictionary attacks or brute force attacks.
If salt is useless to prevent dictionary attack, why using salt?
For single passwords, it doesn't make that much of a difference. Brute-forcing an unsalted password is just as hard as brute-forcing a salted password. You just try out keys until you get a hit.
The difference is when there are a lot of passwords, for example in a leaked database. The basic idea is that part of the necessary computations can be re-used when cracking many passwords. This is done by constructing a rainbow table. Doing that is computationally expensive, but once done it allows the attacker to crack a lot of passwords relatively fast. Cracking N passwords with a rainbow table is a lot faster than brute-forcing those N passwords individually.
If every password is hashed with an individual salt, you can't re-use information in the same way. You could still construct rainbow tables, but they would only be usable for exactly one password in the database, which renders them useless. So in order to crack N passwords, you really have to brute-force all N passwords individually, which is usually not practical for the attacker.
For unsalted passwords and popular hash algorithms, you can simply download pre-calculated rainbow tables from the Internet, so an attacker wouldn't even have to calculate them by himself. He can just download a table and lookup the password for a particular hash. A salt prevents that.
Unsalted hashes also have the drawback that the password hash for two users with the same password is identical. So if an attacker finds multiple users with the same password hash, he only has to crack that password once.
If the 'attacker' has the password hash (and salt) used by your site/app they will simply brute force "salt" + "password".
However, using a salt offers more protection against rainbow tables (precalculated hash tables) so they're still worth using.
Salts prevent instant cracking from a dictionary via rainbow tables; the article and follow-up make the point that the CPU/Storage tradeoff is now such that rainbow tables don't make sense, and so salts don't help you. And of course, they never helped with brute-force attacks.
For illustration purposes, say you are using 2 character string for salts which can be a random element from the set
salts = {'00', '01', '02'...... '99'}
The formula you use is:
salt = salts[rnd(100)] # gets a random element from the set above, say '87'
password_hash = MD5(password + salt) # say the hash is 'dai480hgld0'
Thereafter you'll save the hash and salt in your database, something like
+---------------------------+
| password_hash | salt|
+---------------------------+
| dai480hgld0 | 87 |
| sjknigu2948 | 23 |
| . | . |
| . | . |
+--------------------+------+
We assume that in a compromised system an attacker has access to your code - so he knows how you calculated your hashes.
The attacker will also have access to your database, so he has all the password hashes and the salts.
Given this information, in order to do to crack your password (which has a hash: 'dai480hgld0') he'll have to do the following:
for word in dictionary_words #iterate over all the words in dictionary
for salt in salts #iterate over all possible salts (100 iterations)
password_hash = MD5(word + salt)
if password_hash == 'dai480hgld0'
print "The password is " + word
exit()
endif
next
next
Note that if you'd have not used any salt at all, the algorithm would have been
for word in dictionary_words #iterate over all the words in dictionary
password_hash = MD5(word)
if password_hash == 'dai480hgld0'
print "The password is " + word
exit()
endif
next
From the above two code samples, its obvious that adding a salt to the password increases the number of attempts in the brute force attack. In our case since there are 100 possible salts, you've made the attacker try each word with 100 salts.
So, to conclude:
Salts are good. They make your passwords tough to crack. Even if your users enter weak passwords, the salt makes sure that the resultant hashes are not googlable. For eg, its easy to google a hash '3cc31cd246149aec68079241e71e98f6' which is actually a password that is fairly complex and will meet almost all password policies. Still cracking it requires not a single line of code !
Salts are not panacea. They just increase the time it takes for a cracker to brute force your passwords. However, if your salt address space is fairly big then you are pretty good. For eg, if you have 32 characters alphanumeric string as a salt - brute force will really take very long.
Slow algorithms like bcrypt help you in this regard just because they are well... 'slow'. For a brute force attack, it will take unrealistically long to break hashes that are slow to compute.
Salt makes the encryption stronger. However, dictionary attacks don't try to decrypt the password hash, so salt or no salt, it doesn't matter, they will just try out many passwords until one works.
Now this doesn't seem like a programming question, so I'll just give you some info on salting and encryption:
The purpose of salting is to aid in one-way functions like Hashing, which is used widely in Cryptography, often in use of passwords because of its difficulty to guess, and time it takes for other attacks like brute-force attacks to crack them.
If you want to securely store passwords, the best way is definitely encryption. Look up encryption on Wikipedia for more info on that.
It is not entirely accurate, as with most things it depends on your assumption.
main assumption are:
Attacker has salt
calculation of hashes "on the fly" are done pretty quick (as with salt he will need to recalculate all and wont be able to use predefined lists)
same salt for each user.
Two comments:
Regular hash algorithms can be iterated. There is no need to use a non-standard algorithm just because you want to increase the work factor.
Using a Salt is to be recommended even if you use a slow hash method. It might not necessarily increase the work load of the best attack, but it will stop trivial attacks in case a user chooses a password identical to that of another user, another account or to an old password.
This belongs on security.stackexchange.com
The problem is one of compute capacity in combination with the speed of the hashing algorithm. Basically, he's pitching bcrypt which is slow.
If a hacker has both the hash and salt used as well as knows the algorithm used to hash the password, then it's simply a matter of time to crack it.
If using a very fast algorithm, then that time is pretty short. If using an extremely slow algorithm then the time is, obviously, much longer to find a hit.
Which brings us to the primary reason why we hash/salt things in the first place: to buy time. Time that can be used in order to change all of the passwords listed and time to contact all of the users to let them know in case they need to change their passwords on other systems.
The reason we use salt is to force the hacker to build a rainbow table per salt value. This way one table can't be used to crack all of your passwords. The only reasons to do this are to buy time and, hopefully, dissuade the common hackers from investing further resources in cracking all of them.
Hashed passwords, regardless of mechanism used, are not secure in the sense that most people take that word. Secure doesn't mean "can never be cracked". Rather it means "this is going to be expensive in term of time/effort to crack". For most hackers, they want low hanging fruit such as clear text only. For some, they'll go to whatever extreme is required, such as building massive rainbow tables per salt value to get them all.
And, of course, underpinning this is whether any "super" user accounts are easily identified in your user table. For most systems just cracking the sys admin type of account is good enough and therefore the fact of using a different salt value per user is immaterial. The smart ones will just bother with that one account.
As I understand it, the best practice for generating salts is to use some cryptic formula (or even magic constant) stored in your source code.
I'm working on a project that we plan on releasing as open source, but the problem is that with the source comes the secret formula for generating salts, and therefore the ability to run rainbow table attacks on our site.
I figure that lots of people have contemplated this problem before me, and I'm wondering what the best practice is. It seems to me that there is no point having a salt at all if the code is open source, because salts can be easily reverse-engineered.
Thoughts?
Since questions about salting hashes come along on a quite regular basis and there seems to be quite some confusion about the subject, I extended this answer.
What is a salt?
A salt is a random set of bytes of a fixed length that is added to the input of a hash algorithm.
Why is salting (or seeding) a hash useful?
Adding a random salt to a hash ensures that the same password will produce many different hashes. The salt is usually stored in the database, together with the result of the hash function.
Salting a hash is good for a number of reasons:
Salting greatly increases the difficulty/cost of precomputated attacks (including rainbow tables)
Salting makes sure that the same password does not result in the same hash.
This makes sure you cannot determine if two users have the same password. And, even more important, you cannot determine if the same person uses the same password across different systems.
Salting increases the complexity of passwords, thereby greatly decreasing the effectiveness of both Dictionary- and Birthday attacks. (This is only true if the salt is stored separate from the hash).
Proper salting greatly increases the storage need for precomputation attacks, up to the point where they are no longer practical. (8 character case-sensitive alpha-numeric passwords with 16 bit salt, hashed to a 128 bit value, would take up just under 200 exabytes without rainbow reduction).
There is no need for the salt to be secret.
A salt is not a secret key, instead a salt 'works' by making the hash function specific to each instance. With salted hash, there is not one hash function, but one for every possible salt value. This prevent the attacker from attacking N hashed passwords for less than N times the cost of attacking one password. This is the point of the salt.
A "secret salt" is not a salt, it is called a "key", and it means that you are no longer computing a hash, but a Message Authentication Code (MAC). Computing MAC is tricky business (much trickier than simply slapping together a key and a value into a hash function) and it is a very different subject altogether.
The salt must be random for every instance in which it is used. This ensures that an attacker has to attack every salted hash separately.
If you rely on your salt (or salting algorithm) being secret, you enter the realms of Security Through Obscurity (won't work). Most probably, you do not get additional security from the salt secrecy; you just get the warm fuzzy feeling of security. So instead of making your system more secure, it just distracts you from reality.
So, why does the salt have to be random?
Technically, the salt should be unique. The point of the salt is to be distinct for each hashed password. This is meant worldwide. Since there is no central organization which distributes unique salts on demand, we have to rely on the next best thing, which is random selection with an unpredictable random generator, preferably within a salt space large enough to make collisions improbable (two instances using the same salt value).
It is tempting to try to derive a salt from some data which is "presumably unique", such as the user ID, but such schemes often fail due to some nasty details:
If you use for example the user ID, some bad guys, attacking distinct systems, may just pool their resources and create precomputed tables for user IDs 1 to 50. A user ID is unique system-wide but not worldwide.
The same applies to the username: there is one "root" per Unix system, but there are many roots in the world. A rainbow table for "root" would be worth the effort, since it could be applied to millions of systems. Worse yet, there are also many "bob" out there, and many do not have sysadmin training: their passwords could be quite weak.
Uniqueness is also temporal. Sometimes, users change their password. For each new password, a new salt must be selected. Otherwise, an attacker obtained the hash of the old password and the hash of the new could try to attack both simultaneously.
Using a random salt obtained from a cryptographically secure, unpredictable PRNG may be some kind of overkill, but at least it provably protects you against all those hazards. It's not about preventing the attacker from knowing what an individual salt is, it's about not giving them the big, fat target that will be used on a substantial number of potential targets. Random selection makes the targets as thin as is practical.
In conclusion:
Use a random, evenly distributed, high entropy salt. Use a new salt whenever you create a new password or change a password. Store the salt along with the hashed password. Favor big salts (at least 10 bytes, preferably 16 or more).
A salt does not turn a bad password into a good password. It just makes sure that the attacker will at least pay the dictionary attack price for each bad password he breaks.
Usefull sources:
stackoverflow.com: Non-random salt for password hashes
Bruce Schneier: Practical Cryptography (book)
Matasano Security: Enough with the Rainbow Tables
usenix.org: Unix crypt used salt since 1976
owasp.org: Why add salt
openwall.com: Salts
Disclaimer:
I'm not a security expert. (Although this answer was reviewed by Thomas Pornin)
If any of the security professionals out there find something wrong, please do comment or edit this wiki answer.
Really salts just need to be unique for each entry. Even if the attacker can calculate what the salt is, it makes the rainbow table extremely difficult to create. This is because the salt is added to the password before it is hashed, so it effectively adds to the total number of entries the rainbow table must contain to have a list of all possible values for a password field.
Since Unix became popular, the right way to store a password has been to append a random value (the salt) and hash it. Save the salt away where you can get to it later, but where you hope the bad guys won't get it.
This has some good effects. First, the bad guys can't just make a list of expected passwords like "Password1", hash them into a rainbow table, and go through your password file looking for matches. If you've got a good two-byte salt, they have to generate 65,536 values for each expected password, and that makes the rainbow table a lot less practical. Second, if you can keep the salt from the bad guys who are looking at your password file, you've made it much harder to calculate possible values. Third, you've made it impossible for the bad guys to determine if a given person uses the same password on different sites.
In order to do this, you generate a random salt. This should generate every number in the desired range with uniform probability. This isn't difficult; a simple linear congruential random number generator will do nicely.
If you've got complicated calculations to make the salt, you're doing it wrong. If you calculate it based on the password, you're doing it WAY wrong. In that case, all you're doing is complicating the hash, and not functionally adding any salt.
Nobody good at security would rely on concealing an algorithm. Modern cryptography is based on algorithms that have been extensively tested, and in order to be extensively tested they have to be well known. Generally, it's been found to be safer to use standard algorithms rather than rolling one's own and hoping it's good. It doesn't matter if the code is open source or not, it's still often possible for the bad guys to analyze what a program does.
You can just generate a random salt for each record at runtime. For example, say you're storing hashed user passwords in a database. You can generate an 8-character random string of lower- and uppercase alphanumeric characters at runtime, prepend that to the password, hash that string, and store it in the database. Since there are 628 possible salts, generating rainbow tables (for every possible salt) will be prohibitively expensive; and since you're using a unique salt for each password record, even if an attacker has generated a couple matching rainbow tables, he still won't be able to crack every password.
You can change the parameters of your salt generation based on your security needs; for example, you could use a longer salt, or you could generate a random string that also contains punctuation marks, to increase the number of possible salts.
Use a random function generator to generate the salt, and store it in the database, make salt one per row, and store it in the database.
I like how salt is generated in django-registration. Reference: http://bitbucket.org/ubernostrum/django-registration/src/tip/registration/models.py#cl-85
salt = sha_constructor(str(random.random())).hexdigest()[:5]
activation_key = sha_constructor(salt+user.username).hexdigest()
return self.create(user=user,
activation_key=activation_key)
He uses a combination of sha generated by a random number and the username to generate a hash.
Sha itself is well known for being strong and unbreakable. Add multiple dimensions to generate the salt itself, with random number, sha and the user specific component, you have unbreakable security!
In the case of a desktop application that encrypts data and send it on a remote server, how do you consider using a different salt each time?
Using PKCS#5 with the user's password, it needs a salt to generate an encryption key, to encrypt the data. I know that keep the salt hardcoded (obfuscated) in the desktop application is not a good idea.
If the remote server must NEVER know the user's password, is it possible to user different salt each time? If the user use the desktop application on another computer, how will it be able to decrypt the data on the remote server if he does not have the key (it is not hardcoded in the software) ?
If the password salt for keys are viewable does it not improve security compared to without salt?
Would it be better just to not use the salt and improve some performance?
Even a publicly viewable salt increases the security a bit, because your attackers cannot use previously generated rainbow tables. They have to generate their own. This takes a very long time.
It prevents the use of pre-calculated hash tables or rainbow tables from being used to merely lookup an acceptable input.
Take a look at: http://en.wikipedia.org/wiki/Rainbow_table
Keep in mind that having the salt hidden increases security, because then the attacker does not know exactly what function is being used to generate the hashes. However, the main benefit of hashing passwords is in the event of them being obtained -- much more work to make use of a list of hashes than a list of plain passwords. If someone has your hashes, they likely have your salt as well. Just food for thought.
A unique salt will per password will prevent a Rainbow attack with a pre-computed hash. Using a unique salt per password requires the attacker to calculate the hash foreach individual password for each attempt.
It's main goal is slow the attacker down enough, to make the attack no longer feasible.
Let's say I have a table of users set up like this:
CREATE TABLE `users` (
`id` INTEGER PRIMARY KEY,
`name` TEXT,
`hashed_password` TEXT,
`salt` TEXT
)
When a user is created, a randomly-generated salt is produced and stored in the database alongside the results of something like get_hash(salt + plaintext_password).
I'm wondering that if a malicious user gets their hands on this data, would they be able to use it to crack users's passwords? If so, what's a way that it could be prevented?
No, they're not useless.
So long as you use a unique salt for each row, then the salt will prevent slow down an attack. The attacker will need to mount a brute force attack, rather than using rainbow tables against the password hashes.
As mentioned in the comments, you should ensure that the salt is a sensible size.
Salting was introduced (or at least made popular) in UNIX /etc/passwd file, which was world-readable. It is usually assumed that the salt as well as the encrypted password is known to the cracker. The purpose of the salt is the slow-down of the cracking process (since the same password won't map to the same encrypted string); it is not a secret in itself.
Knowing the salt makes it possible to do a brute-force attack, but that doesn't make it useless. Salt prevents the attacker from using an already generated rainbow table (which you could find on the web).
The best way to prevent brute-forcing is simply to use long, complex passwords.
If an attacker knows the salt, the hashed password and the hash algorithm, then they can mount a brute-force dictionary attack (or rainbow attack).
This should give you an idea of how it works.
Lets say you want to encrypt a word "secret." After it is encrypted lets say it now looks like this 00110010.
If a hacker knows the encryption algorithm, they can create a table of words and their corresponding encrypted values. So they take the encrypted password "00110010" and find it in the table. Now they know that the password used to generate "00110010" was the word "secret." If you salt the word first, then a generic lookup table will be useless to the hacker. (A generic lookup table being a table of unsalted dictionary words and their encrypted values)
If you salt the word first ("saltsecret"), now the encrypted value will look different, and the hacker wont find it in the lookup table.
However, they can still start creating their own lookup table from scratch using your salt and eventually they will be able to reverse lookup passwords.
So to answer the question, if the passwords are sufficiently complex, it will take ages for the hacker to figure them out. You could change your salt every year and they would have to start creating a table all over again.
No, it's not worthless.
To successfully attack an account, an attacker needs to know the salt for that account (and every account's salt should be different), the hashing algorightm used, and the final stored password hash.
Given all of that information, you can write a program that keeps trying to hash different potential passwords until it finds one that matches.
If it's a bad salt (too simple or short), this can be made much faster because the program can use rainbow lookup tables to match the final stored password hash to the string that was hashed, and then just subtract the salt. But they still need all the information.
If it's a shared salt, this is bad because an attacker and use the salt to generate a rainbow table in advance that's good for any account on your system.
Assuming brute force attack of MD5,SHA1,SHA256 algorithms with GPU has a throughput greater than 1 billion of tries per second and SHA512 around 300M/s. If you use one of these algorithms, it will slow down hacker who used rainbow table (less likely), but it will not slow down hacker who used brute force attack (more likely). It will definitively not protect you, it just add a bit of security against outdated rainbow table (for these algo). A bit is better than nothing.
But if you use a strongest algorithm (eg. bcrypt), salt definitively worth it even if stored with hash because brut force is not feasible in term of time so rainbow make sense.
Have a look at this
article and to summarize:
If you are a user:
Make sure all your passwords are 12 characters or more, ideally a lot more. I recommend adopting pass phrases, which are not only a lot easier to remember than passwords (if not type) but also ridiculously secure against brute forcing purely due to their length.
If you are a developer:
Use bcrypt or PBKDF2 exclusively to hash anything you need to be secure. These new hashes were specifically designed to be difficult to implement on GPUs. Do not use any other form of hash. Almost every other popular hashing scheme is vulnerable to brute forcing by arrays of commodity GPUs, which only get faster and more parallel and easier to program for every year.
Posted by Jeff Atwood
I understand that salts make the same password hash to different values. However, salts are usually stored in the database with the password. So let's say I am attacker, here is how I might use a dictionary attack against a salt (note in this example i don't write out 128 bit hashes or salts for the sake of brevity):
user_pw = 'blowfish'
Given:
email = 'blah#blah.com'
hash = '1234567890'
salt = '0987654321'
function attack(){
for each(word in dictionary)
md5( word * salt ) == hash ? cracked_one(email, word)
}
I understand this prevents hackers from using rainbow tables...but doesn't seem to prevent dictionary attacks. I guess you could add something else to the hash algorithm, but with security we must assume that the method of attack is known.
So it seems that salting prevents hackers from figuring out which passwords are likely to be dictionary passwords (ones that multiple users have) and prevents rainbow attacks...but does not prevent dictionary attacks.
Is this a correct analysis? Any suggestions for better security?
Thanks!
Salt doesn't prevent dictionary attacks, just precalculated dictionary attacks. In particular, it protects against rainbow tables (http://en.wikipedia.org/wiki/Rainbow_table) and also ensures that cracking one user's password doesn't automatically let you crack any user who shares that password.
The article I linked to mentions some ways to improve upon salting, incudling key strengthening (http://en.wikipedia.org/wiki/Key_strengthening).
Nothing keeps an attacker from just guessing the password.
Salts just make it harder by forcing an attacker to hash the dictionary on a per-user (effectively, per-salt) basis.
To improve security, a tunable hash function is your best bet. Crank the time-per-hash up, making dictionary attacks impractical on whatever hardware your attacker is likely to have available.
Basically, read this.
That's correct. If someone got the password material, a dictionary attack would be effective.
To guard against this:
Make sure your passwords aren't subject to dictionary attacks.
Make sure your password file (/etc/shadow) is readable only by root.
Without salt, the attacker can generate hashes for every word in his dictionnary then run the new dictionnary against your passwords list
With salt, each password is hashed with a random string so even with the prior hashed dictionnary knowledge, he still have to re-create a new hashed dictionnary containing the salt for every different salt in your database.
Just think of dictionnaries tables as a subset (small portion) of the rainbow tables. While rainbow tables can contain billions of entries, dictionnaries contain "known words", so maybe a few million entries at most.
The reason why rainbow tables fail against salt is because the re-creation process would be "billions of entries" of recalculation while dictionnary attacks are still "few millions of entries". The salt just blocks precomputed values
Your logic is sound, but in reality, with enough computing power and time, there is no protection against dictionary/brute-force attacks.