Cryptography ‐ HKDF - Arrbat/Veil-Forge GitHub Wiki

Introduction

The HMAC-based Key Derivation Function (HKDF) is a type of Key Derivation Function (KDF).

The primary goal of a KDF is to take some initial source of keying material and derive from it one or more cryptographically strong secret keys.

Why not just divide a key into smaller parts and use them?

For example, imagine you have a securely generated 64-bit key. Suppose you have an encryption function that uses 8 rounds, each requiring its own round key.

If you simply divide the 64-bit key into 8 parts for each round key, that means each round key is 8 bits (64 / 8 = 8 bits).

The problem is: an attacker can brute-force each 8-bit round key separately.

Since each round key is 8 bits, there are 2^8=256 possibilities per round.

There are 8 rounds, so brute-forcing all round keys independently requires (2^8)*8 =2048 attempts.

This is extremely weak compared to brute-forcing the original 64-bit key, which requires 2^64 ≈1.84×10^19 attempts — a number vastly larger and currently infeasible to brute force.

So, simply dividing the key into smaller parts drastically weakens security.

HKDF

HMAC

If you want to deeply understand HKDF you need to know what HMAC is

HKDF

Explanation is described here by using great book:

A Graduate Course in Applied Cryptography
Dan Boneh and Victor Shoup

8.10.5 HKDF

The input to HKDF consists of a secret s, an optional salt value salt, an optional info field, and an output length parameter L. The parameters s, salt, and info are variable length byte strings.

There are 2 stages: extract and expand.

Extract:

t ← HMAC(salt, s)

Expand stage:

  • Use the intermediate key t obtained from the extract stage.

  • Compute as many HMAC blocks as needed to produce L bytes of output.

  • Each block z_i is calculated as:

z_i ← HMAC(t, z_{i-1} || info || Octet(i))

where:

  • z_0 is the empty string,

  • info is the optional context and application-specific information,

  • Octet(i) is a single byte encoding the integer i.

  • Concatenate all blocks z_1 || z_2 || ... || z_q (where q = ceil(L / HashLen)) and take the first L bytes as the final output key.

Project`s context

The key point is that the string obfuscation-context is used as the info parameter. While other values may be used, the info parameter is generally intended as public context and is not recommended to be private or random.