148
$\begingroup$

I'm a beginner to cryptography and looking to understand in very simple terms what a cryptographic "salt" is, when I might need to use it, and why I should or should not use it.

Can I get a very simple and clear (beginner level) explanation?

If you know of any references on the topic, those would also be useful.

$\endgroup$
1
  • 1
    $\begingroup$ Salt is the "extra entropy" (the extra pinch of salt) added to something that is already entropic (a fancier word for random). It's whatever you add to a random thing to make it "more random". While randomness is inherently mathematical, it does invite a philosophical discussion also. But what salt actually is is entirely subjective and up to you, the cryptographer. It could be as simple as flipping a coin and deciding whether or not to even add salt. That by definition is salt. $\endgroup$
    – user90222
    May 14, 2021 at 16:05

5 Answers 5

204
$\begingroup$

The reason that salts are used is that people tend to choose the same passwords, and not at all randomly. Many used passwords out there are short real words, to make it easy to remember, but this also enables for an attack.

As you may know, passwords are generally not stored in cleartext, but rather hashed. If you are unsure of the purpose of a hash-function, please read up on that first.

Now, what the attackers can do is to simply generate a list of common passwords and their corresponding hashes. Comparing the hashes that a site has stored with the table will, if common passwords are being used, reveal the passwords to the attacker.

A salt is simply added to make a password hash output unique even for users adopting common passwords. Its purpose is to make pre-computation based attacks unhelpful. If your password is stored with a unique salt then any pre-computed password-hash table targeting unsalted password hashes or targeting an account with a different salt will not aid in cracking your account's password. A long randomly generated salt (using /dev/urandom) is expected to be globally unique. Thus salts can be used to make pre-computation attacks totally ineffective.

The simplest way to combine the salt and the password is to simply concatenate them, i.e. the stored hash value is Hash(salt||password). The common password password1 now magically becomes, e.g., 6$dK,3gCA%Jpassword1 which is unlikely to be found in a password cracker's table.

The salt can be stored completely in the clear in the database, next to the hashed value. Once the attacker has the database and wants to find the passwords, he needs to generate the pre-calculated table for each salt individually, a costly operation.

Another way to help defend against offline password cracking is to perform password stretching, ie. making a password hash slower to compute for any person, including the log-in service and password crackers. One method used to stretch passwords is achieved by iterating the hash-function many times, i.e. storing Hash(Hash(Hash(Hash…(Hash(salt||password)))…).

Another common idea related to salting is called a pepper. That is, another random value concatenated to the password, such that the stored value is Hash(pepper||salt||password). The pepper is then not stored at all. Both the login server and password cracker need to brute force the unknown pepper value, slowing password hash comparisons for both parties.

From 2013 to 2015 a password hashing competition was held to search for a better password-stretching algorithm. The winner was the Argon2 algorithm. Programmers are recommended to use Argon2 instead of implementing their own algorithm.

$\endgroup$
9
  • 5
    $\begingroup$ So essentially, when you have only one or 2 passwords stored in the database, the use of salt is effectively useless? What I understand is that this is only helpful when the number of passwords stored in the database is not small. $\endgroup$ Jul 15, 2014 at 12:26
  • 17
    $\begingroup$ @AbhinavChoudhury: No, it defends against rainbow tables - i.e. precalculated tables for a specific hash. An example: Take a password "password1". If you don't salt, you'd store HASH("password1") in your database. Now, if an attacker gets your records, and has precalculated HASH(*) for all 9-character passwords, he can recover the password. If you instead salted the password, HASH('somesaltforyou'||'password1') will NOT be in the attackers rainbow table (since it's more than 9 characters). $\endgroup$
    – QuadrExAtt
    Feb 25, 2015 at 9:17
  • 1
    $\begingroup$ The point of the salt is to make sure that the hash is not found in a precomputed table. It must be stored in order to verify the password (otherwise it's a "pepper"). The salt is not supposed to be "secret", only to make the password unique. This of course means that every stored password must have its own, unique (and random) salt. $\endgroup$ Jan 25, 2021 at 16:51
  • 1
    $\begingroup$ @Siddhartha Yes, this is called key stretching and the point is to require more resources for an attacker. It is usually good practice to tune such parameters such that the resources/time for the server takes as long as you "can afford", i.e. the slower the better for security. $\endgroup$ Feb 28, 2021 at 12:31
  • 1
    $\begingroup$ @Siddhartha All modern algorithms (already built into modern frameworks and languages) have key stretching built in, so absolutely no need (and most likely insecure) to implement salt/pepper manually. $\endgroup$ Mar 1, 2021 at 8:46
18
$\begingroup$

Can you help me understand what a cryptographic “salt” is?

In the context of password creation, a "salt" is data (random or otherwise) added to a hash function in order to make the hashed output of a password harder to crack.

When might I need to use it?

Always.

Why should or should I not use it?

You should always use a salt value with your hash functions, for reasons explained below.

It is generally true people choose weak passwords, and it is certainly true there are gigabytes of publicly available rainbow tables chock-full of hashed values representing them. So when somebody creates an account on your service and selects a password to secure their identity, you can typically bet the password they choose will be 1) common, 2) unsecure and 3) available for cross-reference in lookup tables.

For example, the password Nowayin1 when hashed via MD5 is 6f367d65bc74b88e21fb9959487ffa3a and is obviously not a good choice. Even if it may look okay (and it doesn't), the fact the password's MD5 hash appears in open databases makes it worthless.

But that's just 128-bit MD5. What about something stronger, like SHA1 (160-bit) or even Whirlpool (512-bit)?

Same problem.

For example, P@$$word with SHA1 is 1e69e0a615e8cb813812ca797d75d4f08bdc2f56 and 1qazXSW@ hashed with Whirlpool is 0bf7545b784665d23b9c174ca03688a405f05b048e9d6c49bfc2721a1fa872bbd6576273d002e56d7c2a9c378efe607af36eea9d708a776e6f60ecb26e081cdf.

The root issue with all of these passwords, and billions more like them, is the fact their commonly-used hashes have become common knowledge.

A password salt changes that.

If a random value (the salt) were added to the user's selected password, then the SHA1 hash 1e69e0a615e8cb813812ca797d75d4f08bdc2f56 would no longer reveal P@$$word as the user's password, because the hash value in the rainbow table would no longer match it.

And it wouldn't take much. A small 16-bit random value, for example, would yield 65,536 variants of each hashed value in the lookup tables. So a database of 15 billion entries would now need over 983 billion hashes in it to account for the salt.

So, that's the point of salting your hashes, to thwart lookup and rainbow tables. But don't hang your hat on a salted hash, because hackers won't waste much time using rainbow tables to figure out your passwords.

They'll use a five-server 25-GPU cluster system running Hashcat that can burn through 350 billion guesses per second cracking hashes for every conceivable eight-character password containing upper- and lower-case letters, numbers and special characters, in just under six hours. (And that was back in 2012.)

Techniques such as key-stretching that make hashes run slower can be used to offset the speed of such hardware, making dictionary and brute-force attacks too slow to be worthwhile, but hardware just keeps getting faster and faster.

UPDATE 2018:

Current best practices include securely hashing your passwords with Argon2i (preferred over scrypt), a memory-hard function which is very resilient to FPGAs, multiplecore GPUs and dedicated ASIC modules used to easily crack non-stretched passphrases. In the PHP7 implementation of Argon2, the salt is handled internally for you.

$\endgroup$
0
9
$\begingroup$

I'm going to attempt to answer a part of your question that has so far been neglected:

when I might need to use it and why I should/should not use it.

The short answer is that, as an amateur, you should not be using cryptography at a level that requires dealing with salts directly.

For instance, the bcrypt password hashing algorithm uses salts internally. But it doesn't expose that fact to developers using it — you simply pass the password to bcrypt (and optionally, a parameter that sets the "level of CPU effort" needed to generate the hash) and it returns the hash. When you need to validate if a password is correct, you pass bcrypt both the password and the previously-generated hash. It will indicate whether or not the password was the one used to generate the hash.

Do not take the advice given here and try to hash your own passwords using a salt. It is a low-level implementation detail, and if you find yourself working at a level where these sorts of things are needed, you are working at far too low a level of abstraction. Cryptography is very difficult to do correctly, and the Internet is absolutely littered with well-intentioned developers' completely insecure home-grown password hashing schemes.

$\endgroup$
0
4
$\begingroup$

Quoting “Exam Ref 70-486 Developing ASP.NET MVC 4 Web Applications (MCSD): Developing ASP.NET MVC 4 Web Applications” by William Penberthy, Pearson Education, 15 Sep 2013:

Salting is a process that strengthens file encryption and hashes, making them more difficult to break. Salting adds a random string to the beginning or end of the input text prior to hashing or encrypting the value. When attempting to break a list of passwords, for example, hackers have to account for the salt as well as possible password information before being able to break into the application. If each value being salted is assigned a different salt value, the ability to create a table of potential password values for a password-cracking program becomes unwieldy.

$\endgroup$
0
3
$\begingroup$

A salt is a random number that is needed to access the encrypted data, along with the password.

If an attacker does not know the password, and is trying to guess it with a brute-force attack, then every password he tries has to be tried with each salt value.

So, for a one-bit salt (0 or 1), this makes the encryption twice as hard to break in this way. A two bit salt makes it four times as hard, a three bit salt eight times as hard, etc. You can imagine how difficult it is to crack passwords with encryption that uses a 32-bit salt!

$\endgroup$
3
  • 3
    $\begingroup$ No. Salt is usually assumed to be known to the attacker. In this case, past some low threshold, salt does not improve security. $\endgroup$
    – fgrieu
    Mar 7, 2012 at 20:24
  • 5
    $\begingroup$ "Salt is usually assumed to be known to the attacker" -> Who is assuming this? $\endgroup$
    – Mike
    Mar 8, 2012 at 14:45
  • 5
    $\begingroup$ @Mike: Who? Someone says "You should always assume the attacker knows the salt.". People at another page says "Salts are public", and later says "the salts are known, because that's the industry-standard use of the word salt." Another says "the salt are public knowledge, or at least should be treated as public knowledge.". $\endgroup$
    – David Cary
    Jun 11, 2014 at 4:49

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