~ read.
Storing Passwords 101

Storing Passwords 101

Don't use hash algorithm

I mean, not only.

MD5, SHA1, SHA256, SHA512, SHA-3,...

These are all general purpose hash functions, designed to calculate a digest of huge amounts of data in as short a time as possible.

This means that they are fantastic for ensuring the integrity of data and utterly rubbish for storing passwords.

Salt for prevent brute force attacks

A salt is a random value that is generally not a secret, which is used to make some precomputed attacks harder.

hash(salt+password)=hashed password  

Salts are closely related to the concept of nonce.

The primary function of salts is to defend against dictionary attacks versus a list of password hashes and against pre-computed rainbow table attacks.

NOTE: A seed is a random value which generally has to be kept secret or the encryption is broken, don't confuse with salt!

Use strong salt rounds

Bcrypt is an adaptative password hashing function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.

How much slower is bcrypt than, say, MD5? Depends on the work factor. Using a work factor of 12, bcrypt hashes the password yaaa in about 0.3 seconds on my laptop. MD5, on the other hand, takes less than a microsecond.

So we’re talking about 5 or so orders of magnitude. Instead of cracking a password every 40 seconds, I’d be cracking them every 12 years or so. Your passwords might not need that kind of security and you might need a faster comparison algorithm, but bcrypt allows you to choose your balance of speed and security. Use it.

That's little benchmark to know how salt rounds affect:

rounds=8 : ~40 hashes/sec  
rounds=9 : ~20 hashes/sec  
rounds=10: ~10 hashes/sec  
rounds=11: ~5  hashes/sec  
rounds=12: 2-3 hashes/sec  
rounds=13: ~1 sec/hash  
rounds=14: ~1.5 sec/hash  
rounds=15: ~3 sec/hash  
rounds=25: ~1 hour/hash  
rounds=31: 2-3 days/hash  

Saving password on database

Always store the hashed password.

About store the salt, exists different approach about what store:

  • A fix salt for all the user passwords.
  • A salt per each user password.

and where:

  • In the same database than password.
  • In a different database.

In the case of bcrypt, it explore A salt per each password and In the same database than password:

var hash = bcrypt.hashSync(myPlaintextPassword, saltRounds);  
bcrypt.compareSync(myPlaintextPassword, hash); // true  

Let's see how looks the hash has been generated:

> bcrypt.genSaltSync(10) // $2a$10$Yq0.l.cOsImF1s1kJL2IOe
> bcrypt.genSaltSync(10) // $2a$10$Rtqb0Kjma5W93bDDJRUdO.
> bcrypt.genSaltSync(11) // $2a$11$/7YSZ7uZH0ouTTDl4BAGve

The salt is part of the final hash.

As you can see, it stores both the salt, and the hashed output in the string.

Strong password in the user side

All this is useless if the input password is 12345.

Best trick that I know for that: auto-generate strong password per service using 1Password:

Bibliography