I am trying to implement ECIES properly with X25519/HKDFwithSHA256/AES-128-GCM with Node.js crypto library. It is not clear to me how to determine the input key material (IKM) to HKDF.

Initially, I thought it is okay to directly use the shared secret generated by X25519 as the IKM.

const {diffieHellman, hkdfSync} = require('crypto');
const sharedKey = diffieHellman({
const aesKey = hkdfSync('sha256', sharedKey, '', '', 16);

But apparently, if diffieHellman does not contain publicKey and the output only contains the x-coordinate of a point, then this is not CCA2-secure, as mentioned in https://eprint.iacr.org/2001/112.pdf:

There are a number of simple examples that illustrate why ECIES does not achieve this level of security. In particular, it is malleable. If the group is an elliptic curve, and the partial encoding function E′ encodes only the x-coordinate of a point, then the derived key K is the same if one takes a given ciphertext $C_0$ encoding a point $\tilde{g}$ and replaces it with an encoding of $−\tilde{g}$.

Some implementations of X25519 also suggests users to include the public values as inputs to the KDF.

Do not use the shared key directly, rather use a key derivation function and also include the two public values as inputs.

Is it sufficient to use the shared secret directly as IKM? If not, what is the proper way to include the public key in the IKM?

  • 2
    $\begingroup$ It might be worth it to use HPKE blog.cloudflare.com/hybrid-public-key-encryption) instead of writing your own ECIES protocol. If you want to anyway, you can see how they use HKDF with LabeledExpand and LabeledExtract functions. $\endgroup$
    – rozbb
    Aug 1, 2023 at 16:41
  • 1
    $\begingroup$ The shared secret is meant to be used as the IKM, but the public keys concatenated together should be used in the info parameter. Including the public keys in the key derivation is mentioned in RFC 7748. $\endgroup$ Aug 1, 2023 at 19:36
  • $\begingroup$ @rozbb Good to know about HPKE. However, it seems like to me there is no popular Node.js/TypeScript/JavaScript implementation yet... $\endgroup$
    – Eri
    Aug 2, 2023 at 9:04
  • $\begingroup$ It looks like hpke-js, referenced in the RFC draft repo github.com/cfrg/draft-irtf-cfrg-hpke, is pretty featureful $\endgroup$
    – rozbb
    Aug 3, 2023 at 0:05

1 Answer 1


To use HKDF (HMAC-based Key Der255:

. Generate an ephemeral X25519 private key. 2. Use the private key to compute. Perform a key exchange with the other party's public key using X25519. 4. Use the resulting shared secret as the input keying material (IKM) for HKDF. 5 Set an appropriate salt value, if required, for HKDF. 6. Use HKDF with the the input key material, the salt value, and the desired output length.

Here is an example code in Python using the cryptography library:

from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
 cryptography.hazmatimitives import hkdf

# Generate ephemeral X25519 private key
private_key = X25519PrivateKey.generate()

# Compute corresponding public key
public_key = private_key.public_key()

# Perform key exchange with other party's public
shared_secret = private_key.exchange_key)

    length=32,  # Length of desired output key
).derive(shared_secret# Use derived key for cryptographic operations
# (e.g., encryption, authentication, etc.)

Remember to handle errors, securely store private keys, and properly manage the lifecycle of cryptographic materials.

  • $\begingroup$ This does not address the question, which is about avoiding a specific pitfall, described in §15.6.1 there $\endgroup$
    – fgrieu
    Aug 6, 2023 at 16:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.