2

This is a theoretical question: does this make sense and is secure?

My goal is to strengthen the passphrase. The flow is the following:

  1. I enter a pssphrase admin1234. This passphrase is going to be used to derive a key for symmetric encryption / decryption.
  2. A passphrase enters the class below. The desired amount of bytes comes out.

The PBKDF2 implementation I am referring to is provided within the Microsoft.AspNetCore.Cryptography.KeyDerivation namespace.

public static class Pbkdf2
{
    public static byte[] DeriveBytes(string passphrase, byte[] salt, int iterations, int amountOfBytes)
    {
        var prf = DeterminePrfForAmountOfBytes(amountOfBytes);
        return KeyDerivation.Pbkdf2(passphrase, salt, prf, iterations, amountOfBytes);
    }

    private static KeyDerivationPrf DeterminePrfForAmountOfBytes(int amountOfBytes)
    {
        if (amountOfBytes < 1)
            throw new ArgumentOutOfRangeException(nameof(amountOfBytes));

        if (amountOfBytes <= 32)
            return KeyDerivationPrf.HMACSHA256;

        return KeyDerivationPrf.HMACSHA512;
    }
}

What I am concerned about is the choice of the hash function. My questions:

  • Does it make sense to choose the hash function based on the desired amount of derived bytes?
  • If not, does it make sense to choose the hash function based on some other parameter to make it automatic?

I feel the answer is no to both, but some part of me wants to see a sense in it. How to choose the hash function otherwise?

3

Does it make sense to choose the hash function based on the desired amount of derived bytes?

PBKDF2 can output as many bytes as you ask it for, regardless of the size of the hash. PBKDF2 will happily output as many bytes as you need, but it will be significantly slower, as it has to go through a second pass. An attacker can easily optimize out this extra work, making it a poor idea to use PBKDF2 to generate a larger output than the hash function naturally provides. If on the other hand you are using a larger hash than the desired output, you can simply truncate the result.

If not, does it make sense to choose the hash function based on some other parameter to make it automatic?

You should choose a hash function based on its security. You should only use a cryptographically secure hash such as SHA-256 or BLAKE2. There is no need to dynamically switch between different hash functions if the one you have chosen is sufficient for the job. A few examples of modern, cryptographically secure hash functions you can safely use with PBKDF2:

  • SHA-2 (such as SHA-256 or SHA-512). This hash family is the NIST standard. SHA-256 is optimized for 32-bit operations, whereas SHA-512 is optimized for 64-bit operations. It comes in a variety of output sizes and uses 64 to 80 rounds. You can't go wrong with SHA-2.

  • SHA-3. A newer hash function standardized by NIST. Despite the name, the design is not at all related to SHA-2. SHA-3 is not in common use yet, but is generally considered solid.

  • Whirlpool. This hash function uses a block cipher internally which is based on Rijndael (AES). It has a 512-bit digest and uses 10 rounds. It boasts a high security margin.

  • BLAKE2. A rather new hash based on Daniel Bernstein's ChaCha cipher. BLAKE2b has a 512-bit digest and uses 12 rounds. BLAKE2s has a 256-bit digest and uses 10 rounds.

My recommendation would be to use PBKDF2-HMAC-SHA512 with a 512-bit output. You are unlikely to need anything larger, and if you need a smaller output, you can safely truncate it to get the desired length. For example, if you need a 160-bit output, you can truncate the 512 bits to 160.

  • Thanks! I slightly modified the question (now the code does not make use of SHA-1). I am concerned with choosing between SHA-256 and SHA-512 for PBKDF2. If both are from the same NIST-approved family (does that mean equal security?), would then code above make sense to choose one of the two based on the desired amount of derived bytes? – Randolph Apr 15 '18 at 6:13
  • I understand and will do this. Curious though — why does the PBKDF2-HMAC-SHA-256 function exist though as a standard? We could just use PBKDF2-HMAC-SHA-512 in all cases then... To rephrase it: what could be a valid reason for a person to choose PBKDF2-HMAC-SHA-256 over PBKDF2-HMAC-SHA-512 (putting compatibility aside, focusing on fresh system design only)? – Randolph Apr 15 '18 at 6:19
  • SHA-512 is optimized for 64-bit operations, so it is not as efficient as SHA-256 on 32-bit processors. There is actually a hash called SHA-512/256, which is SHA-512 truncated to 256 bits, and using a different internal constant (for compatibility reasons). It's not used as often. Truncation also prevents a type of attack called a length extension attack, but this attack does not matter for PBKDF2 because it uses HMAC which is not vulnerable to the LE attack. It is only an issue in very specific situations. – forest Apr 15 '18 at 6: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.