# Using a KDF (PBKDF2) properly

I am new to crypto.

I have a password for my user, e.g. &&38:while:HAVE:havana:60&&
I want to encrypt several documents with 10 pages each with AES.

Now when do I run my salt, KDF and init vector functions?

As often as possible, e.g. for every page? (This is what I do now, but it gets too slow. I store salt and initialization vector with the encrypted page.).

Or KDF once at login (so I use the same derived key for all encrypted documents) and a different salt and initialization vector for every page?

PBKDF2 is deliberately slow (and gets slower and safer with more iterations, so you want to make it as slow as you practically can). Because of this, you should generally avoid running it more times than you absolutely need to.

Using the same key and a different IV for each encrypted document is indeed OK — that's what the IV exists for. Most encryption schemes do have limitations on how much data and/or how many distinct messages you can safely encrypt with a single key, and you should check the documentation for the scheme you're using to make sure you're not at risk of exceeding these limits. But usually they're fairly generous, and if you limit yourself to, say, $$2^{32}$$ distinct documents per key, of up to $$2^{32}$$ cipher blocks each, you're probably fine. (In fact, you might need to worry more about message length limits than about message count limits, depending on which encryption mode you're using, especially if some of the documents you're encrypting might be larger than 64 GB.)

Alternatively, if you'd prefer to use a distinct key for each document, you can achieve that efficiently in (at least) two ways. One is to first derive a single master key from the password using PBKDF2 (with a high iteration count), and then derive the document keys from the master key using a faster KDF such as HKDF-Expand, with a distinct salt/info value for each document. The other method is to generate a random key for each document, encrypt that key using the master key (derived from the password using PBKDF2, as in the first method), and store it alongside the encrypted document.

Ps. Your question seemed familiar to me, so I checked to see if I might have answered something similar here before. While I didn't find any exact duplicates of your question, I did locate a couple of related questions that you might find useful, such as these:

• "You should generally avoid running it more times than you absolutely need to". Very important. If you find yourself deriving the same key twice and you could have safely kept the key cached in volatile memory, then you could have just ran the KDF for twice as long and doubled cracking costs. Someone only needs to brute force your password for one derived key, so they are going to attack the weakest link. (The least costly hash.) (Also keep PBKDF2 output length less than the hash output length for the same reason. If you need longer outputs use a key-based KDF or Argon2. Also, use Argon2.) – Future Security Mar 4 '19 at 20:00
• Is there a clever way to share this document key with another user (without establishing a full private - public key system)? Right now my users use a login password and a shared encryption password (which is bad, I know). – Obiwahn Mar 5 '19 at 8:29
• @obiwahn: Sure, if you somehow have access to the other user's master key, in which case you can just make another copy of the document key and encrypt it with their master key instead of yours. In general, though, if you don't want your users to have access to each other's master keys (and don't want to share document keys unencrypted), then your options are limited: either you need some kind of public/private key pairs for each user (which actually isn't that hard to do), or you need to somehow establish a shared symmetric key for each pair (or group) of users who want to share documents. – Ilmari Karonen Mar 5 '19 at 9:32