denoland/deno · error · Error
invalid curve
Error message
invalid curve
What it means
The ECDH constructor (diffiehellman.ts:1381) looks the curve up by exact name in the built-in elliptic curve list — the same names crypto.getCurves() returns (OpenSSL-style). A miss throws the plain Error 'invalid curve'. WebCrypto-style names like 'P-256' do not match; the OpenSSL name for that curve is 'prime256v1'.
Source
Thrown at ext/node/polyfills/internal/crypto/diffiehellman.ts:1381
): Buffer | string {
if (encoding === undefined || encoding === "buffer") {
return buffer;
}
// deno-lint-ignore deno-internal/prefer-primordials -- Buffer.prototype.toString(encoding) has no primordial
return buffer.toString(encoding);
}
class ECDHImpl {
#curve: any; // the selected curve
#privbuf: Buffer | null = null; // the private key
#pubbuf: Buffer | null = null; // the public key
constructor(curve: string) {
validateString(curve, "curve");
const c = ArrayPrototypeFind(ellipticCurves, (x) => x.name == curve);
if (c == undefined) {
throw new Error("invalid curve");
}
this.#curve = c;
}
static convertKey(
key: any,
curve: string,
inputEncoding?: any,
outputEncoding?: any,
format?: any,
): Buffer | string {
validateString(curve, "curve");
const buf = getArrayBufferOrView(key, "key", inputEncoding);
let compress: boolean;
if (format) {
if (format === "compressed") {View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Use OpenSSL-style names: 'prime256v1' (P-256), 'secp384r1' (P-384), 'secp521r1' (P-521), 'secp256k1'
- Check membership with crypto.getCurves().includes(curve) before constructing
- Translate WebCrypto names once at the edge: P-256 -> prime256v1, P-384 -> secp384r1, P-521 -> secp521r1
- For X25519/X448, use crypto.diffieHellman({ privateKey, publicKey }) with KeyObjects instead of ECDH
Example fix
// before
const ecdh = createECDH('P-256'); // invalid curve
// after
const ecdh = createECDH('prime256v1'); // same curve, OpenSSL name Defensive patterns
Strategy: validation
Validate before calling
import { getCurves } from 'node:crypto';
const WEBCRYPTO_TO_OPENSSL = { 'P-256': 'prime256v1', 'P-384': 'secp384r1', 'P-521': 'secp521r1' };
function normalizeCurveName(c) {
const n = WEBCRYPTO_TO_OPENSSL[c] ?? c;
if (!getCurves().includes(n)) throw new RangeError(`unsupported curve: ${c}`);
return n;
} Type guard
import { getCurves } from 'node:crypto';
function isSupportedCurve(c) { return getCurves().includes(c); } Try / catch
try { ecdh = createECDH(curve); } catch (e) { if (e.message === 'invalid curve') { throw new Error(`curve '${curve}' not supported; see crypto.getCurves()`); } else throw e; } Prevention
- Translate WebCrypto/JOSE curve names to OpenSSL names at the system boundary
- Offer users a curated list from crypto.getCurves() instead of free-text curve input
- Use crypto.diffieHellman with X25519/X448 KeyObjects instead of ECDH for those curves
When it happens
Trigger: new ECDH('P-256') or createECDH('P-384') — WebCrypto/JWS names; typos like 'secp233k1'; 'curve25519'/'x25519' which are not ECDH curves here (X25519 goes through crypto.diffieHellman with KeyObjects); names from other stacks like 'NIST P-256'.
Common situations: Porting WebCrypto/JWT (ES256) code that uses 'P-256'; curve names pulled from RFC/JOSE registries; stale docs or renamed curves in newer OpenSSL versions.
Related errors
- ERR_CRYPTO_ECDH_INVALID_FORMAT
- Invalid EC curve name
- Failed to convert Buffer to EC_POINT
- ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY
- Invalid key pair
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/5654be91d5e4b660.
Report an issue: GitHub.