8

How would one go about using vanilla keyed Blake2B as a KDF with high-entropy inputs. Assume I don't have access to more specialized algorithms such blake2XB, HKDF, etc.

  • Salt - high entropy per-encryption salt (32 bytes)
  • IKM - high entropy static input keying material (32 bytes)
  • Info - a personalization string for the key being derived

Would a construction such as Blake2B(input: $(\text{Salt} \parallel \text{Info})$, key: $\text{IKM}$) be sound?

Taking into account that Blake2 is not prone to length extension attacks, how does the aforementioned construction compare to Blake2B(input: $(\text{Salt} \parallel \text{Info} \parallel \text{IKM})$)?

SEJPM
  • 46,697
  • 9
  • 103
  • 214
hunter
  • 4,051
  • 6
  • 29
  • 42

3 Answers3

6

Actually, what you want is possible with plain Blake2b - if your implementation supports the full specification (PDF) (which is marked as optional by RFC 7693).

If this is the case, you'd do the following mappings:

  • Feed the info data into the personalization -part of the parameter block.
  • Feed the salt data into the salt -part of the parameter block.
  • Feed the IKM data into the key-input of the Blake2b.

Alternatively you can also just feed the info into the main hashing input.

Note thought that key is limited to a size of 64 bytes (the maximum for Blake2b). So if you expect your IKM to be regularly larger than that, it might make sense to mandate straight pre-hashing of your IKM so it fits in.

It gets more interesting if your salt and info exceeed 16 bytes in size (which is the maximum defined for Blake2b) or if your Blake2 implementation only supports the key-input.

In this case what you want is to use a proper pairing function, so that a salt of 0xDEADBEEF won't produce the same result as a salt of 0xDEAD and a personalization of 0xBEEF. Now the simplest such pairing function would be to also include the lengths of the inputs. So you would hash info_length || salt_length || info || salt where the lengths are 32- or 64-bit integers (constant-sized!). Alternatively you could fix a maximal length for either input and then append fill up the remaining space with 0xFF(0x00)*.

SEJPM
  • 46,697
  • 9
  • 103
  • 214
4

Shortening the definition of HKDF (for sufficiently short output) it is just:

HMAC(HMAC(XTS, SKM), CTXinfo || 0)

(format: HMAC(key, msg))

Since this is barely more complicated than your example of

Blake2B(input: (Salt || Info), key: IKM)

I would recommend doing that instead. I know you explicitly stated you don't have access to HKDF but I don't see the big difference here.

Elias
  • 4,933
  • 1
  • 16
  • 32
1

You can use PBKDF2, using Blake2b as the hash function. One of the parameters to PBKDF2 is the hash function you want to use:

PBKDF2(PRF, Password, Salt, Iterations, DesiredBytes)

So it can be:

  • PBKDF2sha1(Password, Salt, Iterations, DesiredBytes)
  • PBKDF2sha2-256(Password, Salt, Iterations, DesiredBytes)
  • PBKDF2sha3(Password, Salt, Iterations, DesiredBytes)
  • PBKDF2blake2b(Password, Salt, Iterations, DesiredBytes)

Blake2b algorithm has the ability itself to generate keys up to 512 bytes long.

  • but if you need an alternative
  • or someone is demanding the use of PBKDF2
  • or you need a key that is longer than 512-bits

then using a password-based key-derivation function to derive a key from a password also works.

It's also useful information to know, as many people only think of:

  • PBKDF2_sha1
  • PBKDF2_sha256

and don't realize that you can substitute any hash function you like.

And in the end, spreading more information to man-kind is what stackexchange is about.

Ian Boyd
  • 1,041
  • 13
  • 16