# Key derivation after ECDH: why h(q ‖ pk1 ‖ pk2)?

I want to use the X25519 DH key agreement for generating a single AES-128 key. The distribution of the shared secret of such a key agreement is not uniform, so it shouldn't be used directly.

The libsodium docu suggests to hash it with: h(q ‖ pk1 ‖ pk2). As hash function h() I want to use SHA-256. As the output is 256 Bit I would just use the lower half.

Why do you append the public keys there? Shouldn't h(q) be good enough?

• In theory there are multiple ways to arrive at any given $q$ (namely there should for each public key exist another public key such that the DH result is $q$) so I guess it serves something like a light authentication purpose or maybe some sort of channel-binding. – SEJPM Mar 24 '17 at 1:17
• I just found a similar explanation in RFC7748: "Designers using these curves should be aware that for each public key, there are several publicly computable public keys that are equivalent to it, i.e., they produce the same shared secrets. Thus using a public key as an identifier and knowledge of a shared secret as proof of ownership (without including the public keys in the key derivation) might lead to subtle vulnerabilities." Does this mean an attacker can easily compute an equivalent public key? Or even a full private/public key pair? – user2436850 Mar 24 '17 at 8:57

## 1 Answer

I'm not sure whether it's the only reason, but adding pk1 and pk2 gives you more entropy, hence a higher security level. Like the docs say, the number of points on the curve is $\approx 2^{252}$, so for a 256-bit hash function $h$ you have $\#\{ h(q) \}_q = 2^{252}$ instead of $2^{256}$.

• the public keys are supposedly public thus they normally should only add negliglible amounts of uncertainity at best. – SEJPM Mar 24 '17 at 1:13
• The function mapping (pk1, pk2) to $q$ is hard to compute (and its inverse is far from injective), so I don't see how the public nature matters. – Mark Mar 24 '17 at 7:48