Imagine I have a blob that I want to encrypt-then-MAC. Now, what I can realistically ask my users for (out of UX considerations) is just an encryption password. Naturally, I bcrypt original password and use bcrypted value as an encryption key. Using the same key for MAC purposes seems risky to me, so I reckoned I'd hash my already hashed encryption key (with bcrypt or with a less expensive algorithm) and use that as a MAC key.

Is this OK to do or do I need to have some other derivation procedure?

  • 2
    $\begingroup$ I'm really not sure as to if the construction you propose is solid, but as an alternative construction, why not run bcrypt twice with different salts? Also, another thing to look at is key expansion algorithms. PBKDF2 allows you to specify the length of the derived key. If you need a 128-bit key for encryption and a 128-bit MAC key, ask PBKDF2 to produce a 256-bit key and split it in half. $\endgroup$ – mikeazo Dec 16 '11 at 12:57

As mikeazo notes, PBKDF2 supports the generation of arbitrary amounts of key data. It accomplishes this simply by appending a running counter to the salt and rerunning the key derivation process to generate new output blocks, so there's no obvious reason why you couldn't apply the same construction to bcrypt.

The scrypt KDF also supports arbitrary-length output, which is not surprising, since it's based on PBKDF2.

Ps. In PBKDF2, each block of the output is computed independently using the full iterated key derivation process. This has the disadvantage that the CPU time needed to run the KDF scales linearly with the desired output length, whereas the work of an attacker who only needs one of the output blocks doesn't. (This is not a far-fetched scenario: for example, if you generate two output blocks and use one of them as the encryption key and the other as the MAC key, an attacker only needs to generate the latter to check whether he guessed the right password.)

Given this, it would seem better to generate only one output block with PBKDF2 (using a correspondingly larger iteration count) and then use a lighter-weight KDF (or even PBKDF2 itself with a low iteration count) to expand the output to the desired length. Of course, given that this seems like such an obvious thing to do, one might wonder why PBKDF2 wasn't specified that way to begin with.

Interestingly, this also seems to be more or less how scrypt uses PBKDF2. Specifically, scrypt invokes PBKDF2 twice, both times with an iteration count of 1: first to expand the passphrase into input for the memory-hard mixing function SMix (on which the hardness of scrypt is actually based), and again to hash the output of SMix into the desired amount of key material.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.