I'm using AES-CBC-256 with PKCS#7 compatible padding. I already have 32 bytes that come from a 'cryptographically secure random number generator'. In this scenario, does it make sense to use PBKDF2 to derive the key eventually used for encryption/decryption?

My scenario is that I need to port old code to a new stack. It all works fine, but I haven't yet implemented key derivation. In the old lib, the input is 32 random bytes + 32 bytes salt (all generated using https://www.cryptopp.com/docs/ref/class_auto_seeded_random_pool.html for the initial random bytes), which is treated as 'password', and PBKDF2 with 65536 iterations is used to derive the final key.

I thought PBKDF2 is supposed to derive a bigger secret from a short user password, but here it is used to derive a 32 byte secret from 2 * 32 byte blocks.

I get my 32 bytes from what is considered a 'cryptographically secure random number generator', which would mean I already have enough entropy. Do I need to derive the key? Does is add any security?

  • 2
    $\begingroup$ For compatibility with a spec or another piece code, something that makes no cryptographic sense often ends up to be necessary. $\endgroup$ – fgrieu May 12 at 9:49
  • $\begingroup$ In this case, it isn't. I implemented the necessary code (without key derivation) and am able to validate it against sample data from the old one. As it seems, I will not implement key derivation, which means I'm done ;) $\endgroup$ – wujek May 12 at 9:53
  • 1
    $\begingroup$ Test sample data includes the AES key and IV, and the original and encrypted files. I can initialize my implementation with this data and encrypt and decrypt to get the same results (so I know I'm using the correct mode of operation, padding etc., which required wading through the code because nothing is documented...). The library should also be able to initialize its key and IV without external data, hence this question. I know I won't be able to decrypt sample data with such an AES instance. $\endgroup$ – wujek May 12 at 10:11
  • 2
    $\begingroup$ "With PKCS#7" is a dangerous statement. If I read your question I'm presuming you mean PKCS#7 padding. However, PKCS#7 as a standard doesn't name a padding scheme at all. It specifies the Cryptographic Message Syntax. The padding is just a detail used within this Cryptographic Message Syntax. So either use "Cryptographic Message Syntax" / CMS or PKCS#7 compatible padding rather than just "with PKCS#7". $\endgroup$ – Maarten Bodewes May 12 at 18:10
  • 1
    $\begingroup$ @MaartenBodewes I edited the question to be more correct. $\endgroup$ – wujek May 13 at 6:07

You're right. Unless the software is doing something very peculiar, which should be very apparent when reading the code and documentation, and I can't imagine what it could be, the salt generation and the application of PBKDF2 are unnecessary.

If you have 32 bytes from a cryptographically secure random generator, you can use these 32 bytes as an AES-256 key. A CSRNG is as good as it gets: it's uniformly random and non-guessable.

You would use a (“plain”, non-stretching) key derivation to obtain a key deterministically from some inputs which are not necessarily uniformly random, but have sufficient entropy. A typical case that requires a key derivation step is the output of a Diffie-Hellman key exchange algorithm: it needs to be deterministic so that both parties calculate the same secret key, and you can't use the output of the DH computation directly because it's a number with some mathematical properties and so it isn't uniformly distributed. Another case that requires key derivation is when you have some secret material of limited length (but enough so that it can't be found by brute force: at least 128 bits), and you want to construct multiple keys whose total length is more than the secret material.

A CSRNG takes an entropy source as input and applies a pseudorandom computation (CSPRNG: cryptographically secure pseudo-random number generator) to produce random output. A key derivation function (KDF) takes input and applies a pseudorandom computation to produce pseudorandom output. A CSPRNG and a key derivation function have fairly similar security properties: as long as the adversary doesn't see the secret input, even if the adversary sees part of the output, they can't figure out anything about the part of the output that wasn't given to them. It wouldn't make sense to just chain them. It can make sense to chain them in combination with some third thing, for example using a CSRNG to generate a public salt and a KDF to combine this public salt with a secret key to generate another secret key, or using a KDF to generate a seed for a CSRNG which then gets used by a subsystem that doesn't have access to the original KDF anymore.

A stretching key derivation function (such as PBKDF2) is useful when the input has low entropy. “Low entropy” means that the input is plausibly guessable through brute force. A CSRNG output has maximal entropy for its length, and 128 bits (16 bytes) is enough to put it well outside the realm of brute force guesses. (Quantum cryptanalysis might raise the bar to 256 bits in the future.) Key stretching is used for secrets that are short enough to be memorable, typically passwords or passphrases. The only reason why you'd need to apply key stretching to the output of a CSRNG is if this output was deliberately kept short to be memorized as a password (presumably in a form encoded suitably for humans, such as a string of printable characters or a list of words).

Taking 64 bytes from a CSRNG and passing them through PBKDF2 doesn't make any sense. Just use the CSRNG output as a key. The use of PBKDF2 isn't a direct security risk, but it hurts performance and it increases the attack surface. Beware that if the current software does this, it indicates that the authors didn't understand what they were doing and there may be other problems that are actually security flaws.

| improve this answer | |
  • $\begingroup$ Thank you. The good thing is the software doesn't do much, it basically just generates the key and IV, encrypts and decrypts using it. $\endgroup$ – wujek May 12 at 9:51
  • 3
    $\begingroup$ It's also possible that the structure of the program might be due to its history; it might have been password based (hence they used PBKDF2) - they later changed to a CSRNG-based, but didn't change anything else (hence, PBKDF2 is still there...) $\endgroup$ – poncho May 12 at 11:31
  • $\begingroup$ This makes sense, but I know that's not the case. The code was written specifically for a certain system, that is getting an overhaul right now. $\endgroup$ – wujek May 12 at 18:22

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.