{"record":{"id":"94a74c2279bdece8","repo":"grafana/k6","slug":"keys-have-different-curves-curve1-and-curve2","errorCode":null,"errorMessage":"keys have different curves {curve1} and {curve2}","messagePattern":"keys have different curves (.+?) and (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/webcrypto/elliptic_curve.go","lineNumber":729,"sourceCode":"\t\treturn nil, fmt.Errorf(\"unable to convert ECDH public key to ECDSA public key, curve: %s\", crv.Params().Name)\n\t}\n\n\treturn &ecdsa.PublicKey{\n\t\tCurve: crv,\n\t\tX:     x,\n\t\tY:     y,\n\t}, nil\n}\n\nfunc ensureKeysUseSameCurve(k1, k2 CryptoKey) error {\n\tecAlg1, ok1 := k1.Algorithm.(EcKeyAlgorithm)\n\tecAlg2, ok2 := k2.Algorithm.(EcKeyAlgorithm)\n\tif !ok1 || !ok2 {\n\t\treturn errors.New(\"keys are not valid elliptic curve keys\")\n\t}\n\n\tif ecAlg1.NamedCurve != ecAlg2.NamedCurve {\n\t\treturn errors.New(\"keys have different curves \" + string(ecAlg1.NamedCurve) + \" and \" + string(ecAlg2.NamedCurve))\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":711,"sourceCodeEnd":734,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/webcrypto/elliptic_curve.go#L711-L734","documentation":"The second check in ensureKeysUseSameCurve (internal/js/modules/k6/webcrypto/elliptic_curve.go:728) compares the NamedCurve of the two ECDH keys passed to deriveBits/deriveKey. ECDH mathematically requires both keys to be on the same curve; mixing curves (message includes both, e.g. \"keys have different curves P-256 and P-384\") returns this error before any bits are derived.","triggerScenarios":"`crypto.subtle.deriveBits({ name: 'ECDH', public: pub384 }, priv256, 256)` — private key generated on P-256 while the peer public key (imported from JWK/raw or generated) is on P-384 or P-521.","commonSituations":"Hard-coded curve in the script ('P-256') while the server/peer publishes keys on P-384; keys imported from different environments (prod vs staging) with different crypto policies; copying example keys from docs generated on another curve.","solutions":["Make the namedCurve identical on both sides — regenerate or re-import so both use the same curve","Determine the peer's curve first (from its JWK crv or SPKI parameters) and generate your ECDH key with the same namedCurve","Centralize the curve choice in one constant used by both generateKey and importKey paths"],"exampleFix":"// before\nconst mine = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'P-256' }, true, ['deriveBits']);\nconst peerPub = await crypto.subtle.importKey('jwk', serverJwk, { name: 'ECDH', namedCurve: 'P-384' }, true, []);\nawait crypto.subtle.deriveBits({ name: 'ECDH', public: peerPub }, mine.privateKey, 256);\n\n// after (match the peer's curve)\nconst peerPub = await crypto.subtle.importKey('jwk', serverJwk, { name: 'ECDH', namedCurve: 'P-384' }, true, []);\nconst mine = await crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'P-384' }, true, ['deriveBits']);\nawait crypto.subtle.deriveBits({ name: 'ECDH', public: peerPub }, mine.privateKey, 256);","handlingStrategy":"validation","validationCode":"const curveOf = (k) => k.algorithm.namedCurve;\nif (curveOf(privKey) !== curveOf(publicKey)) {\n  throw new Error(`curve mismatch: ${curveOf(privKey)} vs ${curveOf(publicKey)} — regenerate on the same curve`);\n}","typeGuard":"const sameCurve = (a, b) => a.algorithm?.namedCurve != null && a.algorithm.namedCurve === b.algorithm?.namedCurve;","tryCatchPattern":"try {\n  bits = await crypto.subtle.deriveBits({ name: 'ECDH', public: peerPub }, priv, 256);\n} catch (e) {\n  if (String(e.message).includes('different curves')) throw new Error(`ECDH keys must share one curve (${e.message})`);\n  throw e;\n}","preventionTips":["Use a single CURVE constant for generateKey and every importKey of peer keys","Read the peer JWK crv (or SPKI parameters) and align your key's namedCurve to it","Validate curve equality in a shared deriveKey() wrapper used across the script"],"tags":["webcrypto","ecdh","key-management","validation"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}