Nota bene: I'm aware that the good answer to secure password storage is either scrypt or bcrypt. This question isn't for implementation in actual software, it's for my own understanding.
Let's say Joe Programmer is tasked with securely storing end user passwords in a database for a web application; or storing passwords on disk for logins to a piece of software. He will most likely:
- Obtain
$password
from the end user. - Create
$nonce
as a random value about 64 or 128 bits large. - Create
$hash = SHA256($nonce$password)
and store$nonce
together with$hash
in the database.
Question one:
Why isn't the following substantially better than the above?
- Create
$long_string
once and only once. Store this as a constant in the application code.$long_string
could f.x. be 2 kilobyte of random characters. - Obtain
$password
from the end user. - Create
$mac = HMAC-SHA256($long_string)[$password]
(i.e. create a MAC using the end user password as key) and store this$mac
in the database.
I would imagine the HMAC has the following benefits?
- Collisions are less frequent?
- It is computationally somewhat more expensive than plain hashing? (But not anywhere near scrypt, of course.)
- In order to succeed with a brute-force attack within a reasonable time, and attacker would need to gain access to two things: 1) the database, where
$mac
is stored, and 2) the application code, where the original$long_string
is stored. That's one better than a hash function, where the attacker only needs access to the database?
But still, nobody seems to suggest using an HMAC, so I must be misunderstanding something?
Question two:
What would the implications of adding a salt value $nonce
be?
- Create
$long_string
once and only once. Store this as a constant in the application code. - Obtain
$password
from the end user. - Create
$nonce
as a random value about 128 bits large. - Create
$mac = HMAC-SHA256($long_string)[$nonce$password]
and store$nonce
and$mac
in the database.