{"record":{"id":"0b017d5d13125da8","repo":"denoland/deno","slug":"unsupported-key-usage-for-a-pbkdf2-key","errorCode":null,"errorMessage":"Unsupported key usage for a PBKDF2 key","messagePattern":"Unsupported key usage for a PBKDF2 key","errorType":"exception","errorClass":"DOMException","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/crypto/keys.ts","lineNumber":772,"sourceCode":"      );\n    }\n\n    if (algName === \"PBKDF2\") {\n      if (extractable) {\n        throw new DOMException(\n          \"PBKDF2 keys are not extractable\",\n          \"SyntaxError\",\n        );\n      }\n      if (\n        usages.length > 0 &&\n        ArrayPrototypeSome(\n          usages,\n          (u: string) =>\n            !ArrayPrototypeIncludes([\"deriveKey\", \"deriveBits\"], u),\n        )\n      ) {\n        throw new DOMException(\n          \"Unsupported key usage for a PBKDF2 key\",\n          \"SyntaxError\",\n        );\n      }\n    } else if (algName === \"HKDF\") {\n      if (extractable) {\n        throw new DOMException(\n          \"HKDF keys are not extractable\",\n          \"SyntaxError\",\n        );\n      }\n      if (\n        usages.length > 0 &&\n        ArrayPrototypeSome(\n          usages,\n          (u: string) =>\n            !ArrayPrototypeIncludes([\"deriveKey\", \"deriveBits\"], u),\n        )","sourceCodeStart":754,"sourceCodeEnd":790,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/crypto/keys.ts#L754-L790","documentation":"Thrown by SecretKeyObject.toCryptoKey() when the algorithm is 'PBKDF2' and the usages array is non-empty and contains any entry other than 'deriveKey' or 'deriveBits'. WebCrypto restricts PBKDF2 keys to key-derivation inputs only, so entries like 'encrypt' or 'sign' are rejected with a SyntaxError DOMException. Note the guard only fires for non-empty arrays — an empty usages array is accepted for PBKDF2 in this polyfill.","triggerScenarios":"createSecretKey(pw).toCryptoKey('PBKDF2', false, ['encrypt', 'deriveBits']) — any usage outside ['deriveKey','deriveBits'] while at least one usage is present.","commonSituations":"Reusing an HMAC usages array (['sign','verify']) for a PBKDF2 import; generic wrappers that pass the union of all possible usages; migrating code between subtle.importKey and KeyObject conversion where the same rule applies.","solutions":["Use only 'deriveKey' and/or 'deriveBits' in the usages array","Pass an empty usages array [] — the PBKDF2 branch accepts it","Do encryption/signing with the key you derive via crypto.subtle.deriveBits/deriveKey, never with the PBKDF2 key itself"],"exampleFix":"// before\nconst key = createSecretKey(pw).toCryptoKey('PBKDF2', false, ['sign', 'verify']); // throws\n\n// after\nconst key = createSecretKey(pw).toCryptoKey('PBKDF2', false, ['deriveBits']);\nconst aesKey = await crypto.subtle.deriveKey({ name: 'PBKDF2' }, key, { name: 'AES-GCM', length: 256 }, false, ['encrypt']);","handlingStrategy":"validation","validationCode":"const ALLOWED = ['deriveKey', 'deriveBits'];\nconst usages = requestedUsages.filter((u) => ALLOWED.includes(u));\nconst key = secretKeyObject.toCryptoKey('PBKDF2', false, usages);","typeGuard":"const isDerivationUsage = (u: string): boolean =>\n  u === 'deriveKey' || u === 'deriveBits';","tryCatchPattern":"try {\n  key = secretKeyObject.toCryptoKey('PBKDF2', false, usages);\n} catch (e) {\n  if (e instanceof DOMException && e.name === 'SyntaxError' && /Unsupported key usage/.test(e.message)) {\n    key = secretKeyObject.toCryptoKey('PBKDF2', false, ['deriveBits']);\n  } else throw e;\n}","preventionTips":["Never reuse sign/verify or encrypt/decrypt usage arrays for derivation keys","Filter usage arrays per algorithm family before import","Derive first, then apply the derived key to the real operation"],"tags":["crypto","webcrypto","pbkdf2","key-usage","node-compat"],"backgroundTag":"webcrypto-invalid-key-usage","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}