denoland/deno · error · ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY
ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY
ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY
Error message
Public key is not valid for specified curve
What it means
computeSecret() on an ECDH instance throws ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY when the instance's private key (#privbuf) is null — that is, the shared-secret computation cannot even start because this side has no private key. Despite the name, nothing about the peer's public key has been checked yet; the error fires before the op runs.
Source
Thrown at ext/node/polyfills/internal/crypto/diffiehellman.ts:1449
// compressed first byte is 02 (even) or 03 (odd)
// hybrid first byte is 06 (even) or 07 (odd)
result[0] = compressedBuf[0] + 4;
}
if (outputEncoding && outputEncoding !== "buffer") {
// deno-lint-ignore deno-internal/prefer-primordials -- Buffer.prototype.toString(encoding) has no primordial
return result.toString(outputEncoding);
}
return result;
}
computeSecret(
otherPublicKey: ArrayBufferView | string,
inputEncoding?: any,
outputEncoding?: any,
): Buffer | string {
if (this.#privbuf === null) {
throw new ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY();
}
let otherBuf: Buffer;
if (typeof otherPublicKey === "string") {
otherBuf = Buffer.from(otherPublicKey, inputEncoding);
} else {
const parts = getViewParts(otherPublicKey);
otherBuf = Buffer.from(parts.ab, parts.off, parts.len);
}
const secretBuf = Buffer.alloc(this.#curve.sharedSecretSize);
try {
op_node_ecdh_compute_secret(
this.#curve.name,
this.#privbuf,
this.#pubbuf,
otherBuf,View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Call ecdh.generateKeys() before computeSecret() when you are generating a new key pair
- If you already have a private key, call ecdh.setPrivateKey(priv) — it derives the public key automatically
- If migrating legacy setPublicKey-based code, replace it: set both keys via setPrivateKey, or generate fresh keys and exchange them
Example fix
// before
const ecdh = crypto.createECDH('prime256v1');
ecdh.setPublicKey(theirPub);
const secret = ecdh.computeSecret(peerPub);
// after
const ecdh = crypto.createECDH('prime256v1');
ecdh.setPrivateKey(myPriv);
const secret = ecdh.computeSecret(peerPub); Defensive patterns
Strategy: validation
Validate before calling
// createECDH objects expose no key until generated; initialize eagerly.
function makeEcdh(curve: string, priv?: Buffer) {
const ecdh = crypto.createECDH(curve);
if (priv) ecdh.setPrivateKey(priv); else ecdh.generateKeys();
return ecdh; // privbuf is guaranteed non-null
}
const secret = makeEcdh('prime256v1').computeSecret(peerPub); Try / catch
catch (e) { if ((e as NodeJS.ErrnoException).code === 'ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY' && !keysInitialized) { /* initialize keys and retry once */ } throw e; } Prevention
- Never hand out a createECDH() result without first calling generateKeys() or setPrivateKey()
- Encapsulate ECDH construction in a factory that guarantees key state
- Drop setPublicKey-based legacy flows; setPrivateKey derives the public key
When it happens
Trigger: const ecdh = crypto.createECDH('prime256v1'); ecdh.computeSecret(peerPub); — generateKeys() or setPrivateKey() was never called. Calling setPublicKey() alone does not help: it sets #pubbuf but leaves #privbuf null.
Common situations: Old Node.js examples that used the (deprecated) setPublicKey flow to import a key pair; stateful servers that reuse an ECDH object after a reset; forgetting that a fresh createECDH() object has no key material until generateKeys() runs.
Related errors
- Failed to get ECDH private key
- Failed to get ECDH public key
- operation not supported for this keytype
- ERR_CRYPTO_ECDH_INVALID_FORMAT
- Invalid EC curve name
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/840749b3f87aae6c.
Report an issue: GitHub.