0

I have read a lot about hashing and salting passwords. I know how hashing works, that is all very easy, but the thing I am confused about is salting.

If I hash and salt a password and stick it into the database, how can I check that password with the password given when a user tries to log-in. Surely because the salt is completely random, it will be near-impossible to get that salt again to be able to match the database

EXAMPLE:

//On create account.
hash(password + randomSalt) to the Database

//On log-in
hash(password + differentRandomSalt) compare to Database
Sirko
  • 72,589
  • 19
  • 149
  • 183
  • 3
    You store the salt along with the password in the database. – Sirko Jan 02 '15 at 17:38
  • Maybe [Password hashing, salt, and storage of hashed values](http://stackoverflow.com/questions/1191112/) will help. It also has pointers to still other questions. You record the salt; it doesn't even have to be kept secret (though there's no point in exposing it if you don't have to). When the password is provided, you hash it with the recorded salt; if it matches the saved value, all's well. The point of salting is that even if the user uses the same password as other people, because the salt is unique, the hash will be different, making it harder for an attacker to 'rainbow attack'. – Jonathan Leffler Jan 02 '15 at 17:51
  • Also [How does password salt help against a rainbow table attack?](http://stackoverflow.com/questions/420843/how-does-password-salt-help-against-a-rainbow-table-attack?lq=1) – Jonathan Leffler Jan 02 '15 at 18:00

2 Answers2

2

You generate a random hash of a fixed length with every password you hash. Then you store that salt in combination with the computed hash into one database column.

When the user wants to login, you extract the salt-part from the database and can match the results.

Example:

var salt = GenerateSecureRandom(16) // generates e.g. 0x42552241
var saltedHash = Hash(salt + password)

Login scenario:

var saltedHash = GetSaltedHashFromDatabase()
var salt = GetFirstBytes(saltedHash)     // 0x42552241
var hash = GetRemainingBytes(saltedHash) // 0x47111337
var match = IsMatch(hash, salt, userInput)

A database entry could look like this (where = is the salt and * is the hash):

0x4255224147111337
  ========********

For (much) more details have a look at: https://crackstation.net/hashing-security.htm

Jan Köhler
  • 5,817
  • 5
  • 26
  • 35
  • Currently it is not clear what is the salt and what is the hash from your pseudo-code. Happy to vote up instead if you fix the pseudo-code. – Maarten Bodewes Jan 02 '15 at 18:59
  • @Maarten what are zoo missing ? – Jan Köhler Jan 02 '15 at 19:09
  • The creation scenario does not show how the final string is constructed, and the verification retrieves the salt from the hash, but then performs `IsMatch` on the full string. At one point `hash` just contains the hash, in the other it also contains the salt. – Maarten Bodewes Jan 02 '15 at 19:10
  • @Maarten `hash` was in both cases meant to hold the salted hash. I've edited my answer. Hope it's clearer now – Jan Köhler Jan 02 '15 at 19:21
  • Changed it a bit more. Note that a 16 bytes would normally be about the maximum amount of bytes required for a salt (128 bits of security for a salt should be plenty). – Maarten Bodewes Jan 02 '15 at 19:31
  • Yep, was just a example. Thanks. – Jan Köhler Jan 02 '15 at 19:34
  • Final comment, maybe change `var salt = {constant value}` to `var salt = GenerateSecureRandom(16) // generates binary value such as 0x4....` – Maarten Bodewes Jan 02 '15 at 19:35
1

The salt is random for each different user/password combination. It's not random for the same user/password combination. If that would be the case, then you would not be able to verify the password, as you already found out. If a large enough salt is generated with a sufficiently secure random number generator then it would even be impossible to verify the password. The idea of the salt is to protect against rainbow table attacks as well as creating a different password hash for different users if the password is the same.

The salt is usually stored together with the username and password hash in the database. It could be made part of a special construct that contains the salt and the password hash or it could be stored in a separate column. Sometimes the password-hash is actually a special string containing both the salt and the hash in some kind of format (using hexadecimal or base64 encoding) that needs to be parsed, but it could also a binary value simply consisting of a statically sized salt and statically sized hash.

An example bcrypt string would be:

$2a$12$QyrjMQfjgGIb4ymtdKQXIewDBqhA3eNppF8qOrMhidnEbzNvmHqhy

which is constructed as in this SO answer.

Setup:

  1. find user
  2. receive & verify old + password (see below)
  3. receive new password
  4. generate random salt
  5. calculate hash from password and salt
  6. store salt & hash in database with user

Verification:

  1. find user
  2. receive password
  3. retrieve salt & hash for user
  4. calculate hash to verify from password and salt
  5. compare and return result

Usually, for security reasons, you should try and do a time-constant compare, even if that's not really an issue for password hashing. Furthermore often no distinction is made between unknown user and wrong password, simply to avoid giving information to attackers.

It makes sense to construct your password hashing scheme in such a way that it allows for updates to the amount of iterations, hash size, hash function etc.

Community
  • 1
  • 1
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263