grafana/k6 · error
keys are not valid elliptic curve keys
Error message
keys are not valid elliptic curve keys
What it means
ensureKeysUseSameCurve (internal/js/modules/k6/webcrypto/elliptic_curve.go:721) validates the two keys used in ECDH deriveBits/deriveKey. It first asserts both CryptoKeys carry an EcKeyAlgorithm; if either does not — e.g. one of them is an AES, HMAC, or otherwise non-elliptic key — it returns "keys are not valid elliptic curve keys" before any curve comparison happens.
Source
Thrown at internal/js/modules/k6/webcrypto/elliptic_curve.go:725
}
x, y := elliptic.Unmarshal(crv, k.Bytes()) //nolint:staticcheck // we need to use the Unmarshal function
if x == nil {
return nil, fmt.Errorf("unable to convert ECDH public key to ECDSA public key, curve: %s", crv.Params().Name)
}
return &ecdsa.PublicKey{
Curve: crv,
X: x,
Y: y,
}, nil
}
func ensureKeysUseSameCurve(k1, k2 CryptoKey) error {
ecAlg1, ok1 := k1.Algorithm.(EcKeyAlgorithm)
ecAlg2, ok2 := k2.Algorithm.(EcKeyAlgorithm)
if !ok1 || !ok2 {
return errors.New("keys are not valid elliptic curve keys")
}
if ecAlg1.NamedCurve != ecAlg2.NamedCurve {
return errors.New("keys have different curves " + string(ecAlg1.NamedCurve) + " and " + string(ecAlg2.NamedCurve))
}
return nil
}
View on GitHub (pinned to 93accf6570)
Solutions
- Ensure both keys are ECDH keys: the base key generated with { name: 'ECDH', namedCurve: ... } and public being the peer's ECDH public key
- Log key.algorithm and key.type before deriving to confirm what each variable holds
- Regenerate both keys as a matched ECDH pair if provenance is unclear
Example fix
// before
const aesKey = await crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, true, ['encrypt']);
const bits = await crypto.subtle.deriveBits(
{ name: 'ECDH', public: aesKey }, ecdhPrivateKey, 256);
// after
const peerPub = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'P-256' }, true, []);
const bits = await crypto.subtle.deriveBits(
{ name: 'ECDH', public: peerPub.publicKey }, ecdhPrivateKey, 256); Defensive patterns
Strategy: validation
Validate before calling
const isEcdhKey = (k) => k && k.algorithm && k.algorithm.name === 'ECDH' && k.algorithm.namedCurve;
if (!isEcdhKey(baseKey) || !isEcdhKey(params.public)) {
throw new TypeError('both keys passed to deriveBits/deriveKey must be ECDH keys');
} Type guard
const isEcdhCryptoKey = (k) => !!k && typeof k === 'object' && k.algorithm?.name === 'ECDH' && !!k.algorithm.namedCurve;
Try / catch
try {
bits = await crypto.subtle.deriveBits({ name: 'ECDH', public: peerPub }, priv, 256);
} catch (e) {
if (String(e.message).includes('not valid elliptic curve keys')) throw new TypeError('a non-ECDH key was passed to the ECDH derivation');
throw e;
} Prevention
- Store keys in typed variables (ecdhPriv, peerPub) instead of generic key maps
- Assert key.algorithm.name before every derive call in crypto helpers
- Generate the peer public key import with an explicit ECDH algorithm identifier
When it happens
Trigger: `crypto.subtle.deriveBits({ name: 'ECDH', public: someKey }, baseKey, 256)` where someKey or baseKey is not an elliptic-curve key — for example an AES-GCM key passed as `public`, or a non-ECDH private key as the base key.
Common situations: Variable mix-ups where a symmetric key is passed where the peer's ECDH public key belongs; key-management maps that return the wrong entry; refactors that swap argument order in deriveBits/deriveKey calls.
Related errors
- keys have different curves {curve1} and {curve2}
- invalid ECDH curve
- key (k) is required
- invalid elliptic curve {k}
- curve not supported for converting to ECDSA key
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/57c000acc089affe.
Report an issue: GitHub.