I want to make a password manager that from a single master password generates passwords for my services. For that I thought that HKDF suits my needs, as it is able to generate multiple keys from a single strong key. Here I read that HKDF is secure if the key is "good" which password aren't. So I thought about using PBKDF2 to generate the key to be used with HKDF.

Is this design good?

master_key <- PBKDF2(master_password, ...)
service_key <- HKDF-Extract(master_key, ...)


How would I then handle salt? It should be random, so it should be stored somewhere. Can I store it anywhere? Can I use the same salt for the two phases?

EDIT: I think I should add a clarification.

The reason why I would do this is to have a way to have my password wherever I am without the need to have on every single device I am using the database file (I've used keepassx for a while and that was frustrating, because you then need to handle syncing and such). This way the user is required to remember only the master password (and the salt?) and perform the calculations with a specific tool.

What you describe will work once, and it will be fine to use one salt, which need not even be secret as long as it's different from everyone else's salt. Just derive each service password from the same master key with a different HKDF info parameter.

But what happens when a site's password database is breached, and turns out not to have been hashed, and you need to generate a new password for the site? What happens if a site imposes restrictions on the character set, length, or structure of the password?

See Tony Arcieri, ‘4 fatal flaws in deterministic password managers’, blog post, 2016-11-22 for further discussion. (The title should perhaps have been about stateless password managers rather than deterministic ones.)

• Thank you, your link made me understand the problems associated. If I ever decide to continue this project I would know what I should take care of! – lmureu Sep 14 '17 at 13:43

# KDF Usage

Your proposal is fine, but actually more complicated then necessary. PBKDF2 does more or less the same thing as HKDF but more often. So using both together is not needed. You can use PBKDF2 (or preferably an even better password hashing function like scrypt) for the service calculation password straight away by using the service's name or URL as the salt

# State

What you appear to want is a completely state- and configuration free password manager (password calculator, actually). That's fine, but you won't be able to use a random salt in that case, since that would have to be synced across all devices thus contradicting your requirements.

Another problem with stateless password managers, as has already been pointed out, is their unability to change a single password. If you consider a single of your service passwords problematic (maybe due to a hack of the service or du to a misuse by yourself)) you have to change you master password and thus update the password of every single of your services. Everything a else, will require some sort of state or configuration file.

• You can use PBKDF2 to generate a large output, but for reasons that seem inexplicable to me, generating a $2n$-bit output from PBKDF2 with an $n$-bit PRF costs twice what generating an $n$-bit output does, rather than than negligibly more—PBKDF2 repeats the costly part for every $n$-bit chunk of output, instead of just generating an intermediate $n$-bit key and expanding it with a normal KDF. So it actually makes sense to compose PBKDF2 with HKDF here, in case you want to, e.g., cache the master key in memory. – Squeamish Ossifrage Sep 14 '17 at 13:11
• Also, the master salt need not be synced, and there's no real need for a per-service salt since the master salt already prevents attacks on multiple users' passwords simultaneously. (But there remains a need for per-service state, if you ever need to change your password. Even a counter suffices, but it must be synced.) – Squeamish Ossifrage Sep 14 '17 at 13:17
• Well, making the KDF even slower is not necessarily a bad thing in this scenario. Can you explain, what you mean with the master salt need not be synced. If it is used in the KDF, it needs to be present on every host you want to use your system (unless you store it in some webservice, but that's just a different kind of dependency) – mat Sep 14 '17 at 14:12
• Making the KDF slower may be a problem if you want to log into a dozen web sites and are willing to wait one second but not twelve. Spending one second to derive the master key and microseconds to derive the service keys still forces the attacker to spend one second per trial (times area). Spending 1/12 second to derive each service key independently lets the attacker spend only 1/12 second per trial. All I meant about the master salt is that it never needs to change. Yes, it has to be shared initially, but you don't need to update it once you've configured it. – Squeamish Ossifrage Sep 14 '17 at 14:56