denoland/deno · error · ERR_CRYPTO_INCOMPATIBLE_KEY

ERR_CRYPTO_INCOMPATIBLE_KEY

ERR_CRYPTO_INCOMPATIBLE_KEY

Error message

Incompatible key types for Diffie-Hellman: ${privType} and ${pubType}

What it means

statelessDH() — the engine behind crypto.diffieHellman({privateKey, publicKey}) — throws ERR_CRYPTO_INCOMPATIBLE_KEY when both KeyObjects have a known asymmetricKeyType and the types differ. Diffie-Hellman can only combine two keys of the same algorithm (e.g. 'ec' with 'ec', 'x25519' with 'x25519'); mixing kinds can never produce a shared secret.

Source

Thrown at ext/node/polyfills/internal/crypto/diffiehellman.ts:1607

ECDH.prototype.setPublicKey = deprecate(
  ECDHImpl.prototype.setPublicKey,
  "ecdh.setPublicKey() is deprecated.",
  "DEP0031",
);

function statelessDH(
  privateKeyObject: KeyObject,
  publicKeyObject: KeyObject,
): Buffer {
  const privateKey = getKeyObjectHandle(privateKeyObject, kConsumePrivate);
  const publicKey = getKeyObjectHandle(publicKeyObject, kConsumePublic);

  const privType = privateKeyObject.asymmetricKeyType;
  const pubType = publicKeyObject.asymmetricKeyType;
  if (
    privType !== undefined && pubType !== undefined && privType !== pubType
  ) {
    throw new ERR_CRYPTO_INCOMPATIBLE_KEY(
      "key types for Diffie-Hellman",
      `${privType} and ${pubType}`,
    );
  }

  try {
    const bytes = op_node_diffie_hellman(privateKey, publicKey);
    return Buffer.from(bytes);
  } catch (err) {
    const e = err as Error & { code?: string };
    if (e && typeof e.message === "string") {
      if (
        StringPrototypeIncludes(e.message, "mismatching domain parameters")
      ) {
        e.code = "ERR_OSSL_MISMATCHING_DOMAIN_PARAMETERS";
      } else if (
        StringPrototypeIncludes(e.message, "failed during derivation")
      ) {

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use a matching pair: generate one key pair (e.g. generateKeyPairSync('x25519')) and pass its privateKey plus the peer's same-type public key
  2. Log privateKeyObject.asymmetricKeyType and publicKeyObject.asymmetricKeyType before the call and fix whichever side is wrong
  3. Verify PEM/DER files were loaded with createPrivateKey/createPublicKey and not swapped

Example fix

// before
const secret = crypto.diffieHellman({ privateKey: rsaPriv, publicKey: ecPub });

// after
const secret = crypto.diffieHellman({ privateKey: ecPriv, publicKey: ecPub });
Defensive patterns

Strategy: type-guard

Validate before calling

if (privateKeyObject.asymmetricKeyType !== publicKeyObject.asymmetricKeyType) {
  throw new TypeError(
    `key types must match: ${privateKeyObject.asymmetricKeyType} vs ${publicKeyObject.asymmetricKeyType}`,
  );
}
const secret = crypto.diffieHellman({ privateKey: privateKeyObject, publicKey: publicKeyObject });

Type guard

const isMatchingDHPair = (priv: crypto.KeyObject, pub: crypto.KeyObject): boolean =>
  priv.asymmetricKeyType === pub.asymmetricKeyType &&
  ['ec', 'x25519', 'ed25519', 'dh'].includes(String(priv.asymmetricKeyType));

Try / catch

catch (e) { if ((e as NodeJS.ErrnoException).code === 'ERR_CRYPTO_INCOMPATIBLE_KEY') { /* log both key types, re-key the offending side */ } throw e; }

Prevention

When it happens

Trigger: crypto.diffieHellman({ privateKey: createPrivateKey(rsaPem), publicKey: createPublicKey(ecPem) }); or an 'x25519' private key with an 'ec' (NIST) public key, or 'dh' with 'ec'.

Common situations: Key-management code that grabs whatever KeyObject is at hand; protocols that upgraded one side from RSA/ECDH to X25519 while the other side still sends the old key type; config files pointing privateKey and publicKey at PEMs of different algorithms.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/459f2fa2822aac90. Report an issue: GitHub.