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
$passwordfrom the end user. - Create
$nonceas a random value about 64 or 128 bits large. - Create
$hash = SHA256($nonce$password)and store$noncetogether with$hashin the database.
Question one:
Why isn't the following substantially better than the above?
- Create
$long_stringonce and only once. Store this as a constant in the application code.$long_stringcould f.x. be 2 kilobyte of random characters. - Obtain
$passwordfrom 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$macin 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
$macis stored, and 2) the application code, where the original$long_stringis 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_stringonce and only once. Store this as a constant in the application code. - Obtain
$passwordfrom the end user. - Create
$nonceas a random value about 128 bits large. - Create
$mac = HMAC-SHA256($long_string)[$nonce$password]and store$nonceand$macin the database.