{"record":{"id":"8e8f859a6e433656","repo":"denoland/deno","slug":"invalid-key-type-8e8f85","errorCode":null,"errorMessage":"Invalid key type","messagePattern":"Invalid key type","errorType":"exception","errorClass":"DOMException","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/crypto/keys.ts","lineNumber":1036,"sourceCode":"\n    if (format === \"pem\") {\n      return op_node_export_public_key_pem(this[kHandle], type);\n    } else {\n      return Buffer.from(op_node_export_public_key_der(this[kHandle], type));\n    }\n  }\n}\n\nfunction _validateAsymmetricKeyAlgorithm(\n  keyObject: AsymmetricKeyObject,\n  algName: string,\n) {\n  const keyType = keyObject.asymmetricKeyType;\n\n  if (keyType === \"ed25519\" || keyType === \"x25519\") {\n    const expectedAlg = keyType === \"ed25519\" ? \"Ed25519\" : \"X25519\";\n    if (algName !== expectedAlg) {\n      throw new DOMException(\"Invalid key type\", \"DataError\");\n    }\n  } else if (keyType === \"ed448\" || keyType === \"x448\") {\n    const expectedAlg = keyType === \"ed448\" ? \"Ed448\" : \"X448\";\n    if (algName !== expectedAlg) {\n      throw new DOMException(\"Invalid key type\", \"DataError\");\n    }\n  }\n}\n\nfunction _validateEcNamedCurve(\n  keyObject: AsymmetricKeyObject,\n  algorithm: object,\n) {\n  const details = keyObject.asymmetricKeyDetails;\n  const alg = algorithm as { namedCurve?: string };\n  if (alg.namedCurve && details?.namedCurve) {\n    const curveMap: Record<string, string> = {\n      \"prime256v1\": \"P-256\",","sourceCodeStart":1018,"sourceCodeEnd":1054,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/crypto/keys.ts#L1018-L1054","documentation":"_validateAsymmetricKeyAlgorithm throws DOMException DataError 'Invalid key type' when a KeyObject whose asymmetricKeyType is 'ed25519' or 'x25519' is converted via toCryptoKey() with an algorithm name that is not exactly 'Ed25519' or 'X25519' respectively. WebCrypto gives these curves dedicated algorithm names, separate from the ECDSA/ECDH named-curve namespace, and the polyfill enforces the 1:1 mapping.","triggerScenarios":"generateKeyPairSync('ed25519').privateKey.toCryptoKey('ECDSA', true, ['sign']); or generateKeyPairSync('x25519').privateKey.toCryptoKey('Ed25519', true, []) — any keyType/algorithm-name mismatch in the Edwards/Montgomery family.","commonSituations":"Algorithm chosen from config while keys are generated elsewhere; generic sign/verify code that assumes ECDSA for every curve; confusing the signature curve (Ed25519) with the key-exchange curve (X25519) during JWT/EdDSA work.","solutions":["Match the algorithm name to the key type: ed25519 -> 'Ed25519', x25519 -> 'X25519'","Derive the algorithm name from keyObject.asymmetricKeyType instead of hardcoding it","If you intended ECDSA/ECDH with P-curves, generate an 'ec' key pair instead of an ed25519/x25519 one"],"exampleFix":"// before\nconst ck = privateKey.toCryptoKey('ECDSA', true, ['sign']); // key is ed25519 -> throws\n\n// after\nconst name = privateKey.asymmetricKeyType === 'ed25519' ? 'Ed25519' : 'X25519';\nconst ck = privateKey.toCryptoKey(name, true, ['sign']);","handlingStrategy":"type-guard","validationCode":"const ALG_BY_TYPE: Record<string, string> = {\n  ed25519: 'Ed25519', x25519: 'X25519', ed448: 'Ed448', x448: 'X448',\n};\nconst algName = typeof algorithm === 'string' ? algorithm : algorithm.name;\nconst expected = ALG_BY_TYPE[keyObject.asymmetricKeyType as string];\nif (expected && algName !== expected) {\n  algorithm = typeof algorithm === 'string' ? expected : { ...algorithm, name: expected };\n}","typeGuard":"function algorithmMatchesKeyType(keyObject: KeyObject, algName: string): boolean {\n  const t = keyObject.asymmetricKeyType;\n  if (t === 'ed25519' || t === 'x25519' || t === 'ed448' || t === 'x448') {\n    return algName.toLowerCase() === t; // 'Ed25519' vs 'ed25519'\n  }\n  return true; // other types are not checked here\n}","tryCatchPattern":"try {\n  ck = keyObject.toCryptoKey(algorithm, extractable, usages);\n} catch (e) {\n  if (e instanceof DOMException && e.name === 'DataError' && e.message === 'Invalid key type') {\n    // re-derive the algorithm name from keyObject.asymmetricKeyType and retry\n  } else throw e;\n}","preventionTips":["Always derive the WebCrypto algorithm name from asymmetricKeyType for the 25519/448 families","Keep signature keys (ed25519/ed448) and exchange keys (x25519/x448) in separate code paths","Add a regression test per curve family in generic wrappers"],"tags":["crypto","webcrypto","ed25519","x25519","key-management"],"backgroundTag":"key-algorithm-mismatch","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}