6

(This is not a duplicated of the linked question IMHO as this is more about the differences between a salt and password: both variables used to generate a hash)

Let's say an attacker has offline access to a database in which passwords are hashed with bcrypt (no pepper added). The hashes look like:

$2y$10$H0mRpD2XJZDguAzxTehwzunRkjUR8lB3O4UGrAGLiqJuvnlWjFA7G

In which the salt is: H0mRpD2XJZDguAzxTehwzu and the hash is nRkjUR8lB3O4UGrAGLiqJuvnlWjFA7G.

The attacker will be unable to run a rainbow table to match hashes, but she could compute common passwords using the salt included, so executing:

bcrypt("abcd1234", 10, "H0mRpD2XJZDguAzxTehwzu")

will produce:

nRkjUR8lB3O4UGrAGLiqJuvnlWjFA7G

And there you have! She could go through all the database testing "abcd1234" and be able to identify which users are using that weak password in a matter of seconds/minutes.

So what if only the hash nRkjUR8lB3O4UGrAGLiqJuvnlWjFA7G is stored at the database (no salt)?

If the attacker has a strong feeling that the user "abcdefg" might be using the password "abcd1234", how could she test her theory offline? She would need to guess the salt. How could she do it? Is there any easier method than trying each combination? Maybe in that specific case there won't be enough motivation to try it. But what if she suspects the system is using the same salt for all passwords (as some hashes are the same)? How hard it would be for her to crack it?


UPDATE

Peleus's answer is close to what I was expecting. I will try to extend it (correct me if I'm wrong):

Entropy:

In Bcrypt a salt is usually of 16 random bytes (128 bits). If we compare that to a password of the same length, then a salt will have a grater entropy than a password, as passwords are usually limited to what the user can type with a keyboard.

Those 16 bytes are encoded into HEX (using Base64) and become 22 of length. If we compare them with a 22-chars password, then the password will contain a greater entropy (as it can include symbols and the full alphabet).

Length:

Bcrypt salts are limited to 16 bytes while passwords may be limited to 72 bytes, depending on implementation.

Collision:

2 different salts will generate 2 different hashes, and so the passwords. However at some point 2 different salts could produce the same hash using the same password and vice-versa. Which is the probability for each of those cases? That is something maybe I should ask in crypto.SE. But I leave it here in case someone has the answer to it.

Design:

The algorithm was designed to protect passwords and not salts. This means that salts are not mean to be safe by design, which suggests that there could potentially be a way to obtain them without brute-forcing them.

Fictitious Case:

We are used to the user-password method to protect access to a system. But, what if something like this happens (please bare with me, its just an example)?:

Company CauseWeWantItThatWay use microchips to store a unique 22-hex-chars value (to be used as salt). Each user will generate a total of 5 passwords or PIN numbers (4 digits each, yes, they are lazy) with that unique salt to access 5 different systems.

Now let's assume I'm assigned to one of those systems and I know one of those PIN numbers, and somehow I have access to the database. If the salt were included, it would be trivial to get those PIN numbers, however without the salt, I would have to crack it.

I know what you are thinking. The company has a really bad security implementation (and they should burn in hell). Also, that they could have used the "salt" as pepper instead, and leave the salt random. So my question was, in that case, it would be the same to add a 22-hex-chars as pepper than using those as salt? According to Peleus, is the same (so no shortcuts exists to get the salt).

After all not everyone follows the recommendations and the algorithm allows you to set the salt, which makes this kind of scenario totally possible (although not so probable nor recommended).

lepe
  • 2,194
  • 2
  • 16
  • 29
  • 1
    How could you kept salt private? Only using them in your code? That's security through obscurity and disadvised. Hashes need to be in the next column next to your password in the database to be able to use them correctly. And also, random hashes for each password are more secure. Unless you can tell how to keep salts secret even after database-breach, I don't see how you can achieve this. – O'Niel Jul 25 '16 at 06:27
  • 1
    @O'Niel: its not my intention to implement this scenario, but to understand more in detail how the salt could be cracked if its unknown. But to answer your question, lets say you keep the salts encrypted in another server, so in case the database is compromised, they only have hashes without salts. – lepe Jul 25 '16 at 06:31
  • 1
    @lepe However, the application must have access to the salt to validate the password. In the scenario you proposed, the attacker need only access to the encryption key and access to the server, which the application has, to access the salts. This actually compounds the problem rather than shifting the burden. – h4ckNinja Jul 25 '16 at 06:40
  • @Micheal: Thanks for your comment. It really doesn't matter where or how the salt is stored, its not relevant for my question. The important point here is how easy is to find out the salt if its unknown. I added some extra explanation to my question. I'm looking forward for your answer. – lepe Jul 25 '16 at 07:27
  • After analyzing my own question I realized of something: Actually hiding a salt may no be a bad idea after all in some specific scenarios: If the salt is set using an external input (like a microchip), it will make the passwords impossible to hack (in terms of time) even if the code and the database are compromised (which is a nice feature). It would work the same if we set the pepper in a microchip and use a random salt stored in the db (probably that would be a better approach as the pepper can be longer). But salts could be used if for some reason the pepper is injected from the code. – lepe Jul 27 '16 at 01:29

3 Answers3

10

I think you've misunderstood the purpose of a salt, because if you understood what it is designed to achieve you perhaps wouldn't be asking this question. The only purpose is to provide a level of uniqueness to each password in order to prevent precomputed tables ("rainbow tables") being an effective form of attack.

As a result, it's not designed to be "secret" or add entropy to the password in any way, and that is why it is stored alongside the hash of the password. In fact in most cases it cannot be secret because the application itself will need access to the salt in order to calculate the correct hash of the password. It's very difficult to allow access to the application, but prevent an attacker who has breached the application from obtaining the same privilege.

Anyway to answer your actual question - in a theoretical world where you had to "crack" the salt because it was unknown, and could not be retrieved for some reason, it would be exactly the same level of complexity as passwords. Basically (character space)^(length).

In your example you give a hash of "H0mRpD2XJZDguAzxTehwzu". Assuming upper / lower case alphanumeric that's a character space of 62 characters, and it has a length of 22 characters. Hence 62^22 = 3.397504e+23 years of guessing assuming 1 billion guesses per second. In other words, uncrackable (this is even assuming the password is known and you're trying to simply guess a system wide salt).

Peleus
  • 3,827
  • 2
  • 19
  • 20
  • Thank you. I accepted your answer as it the one that makes more sense to my question. I totally understand the purpose of the salt, but I wanted to discuss a "What-if" scenario that came to my mind. If you search, you will find that some people misuse the algorithm and set fixed salts, after all the algorithm doesn't stop you from shooting yourself on the foot. – lepe Jul 26 '16 at 01:01
  • If you use a "fixed salt" it's not a salt. So to use a different salt for each password, you need another DB with salts. If you can protect this salt db better than your password db, why not just store the passwords in this more secure db? If you cannot protect that db better than the password db, you earn no security at the cost of more effort, more code, more chance of bugs. – Josef Feb 03 '17 at 08:08
4

A salt is a stored next to the password. There is no rule that says it MUST be like that, but it is a logical result of the intended purpose of a salt. Building a rainbow table is no trivial task. The point of the salt is that the attacker would need a separate rainbow table for each salted password (in which case it is easier to directly attack each password hash instead).

You can read a long answer on salt, which should make it clear why there is no point in keeping it secret.

If you want to include some secret salt, you should read up on what is commonly called a pepper, which adds an application wide secret key into your salted passwords. This could protect you against partial breaches (such as database compromises through, for example, SQL-injection), but won't help in case of full system breaches, unless you use a Hardware Security Modules (HSM) to protect the pepper value.

Jacco
  • 7,512
  • 4
  • 32
  • 53
3

When an attacker knows only the hash and not the salt, then they have to not just test every possible password but every possible password with every possible salt. With long and random salt values this is practically impossible.

However, this is not a realistic scenario. When an attacker compromises a system, you have to assume that they compromised the database of both the hashes and the salts. Separating these two datasets in some way is infeasible because they are always used together.

Philipp
  • 49,017
  • 8
  • 127
  • 158
  • Exactly. That is assuming the salts are stored somewhere, but if they come from user input (as the fictitious case I added), then it make things harder, as they have to try every possible password with every possible salt (as you said). – lepe Jul 26 '16 at 01:26