{"record":{"id":"e3d6a71ff8fc7d16","repo":"denoland/deno","slug":"err-crypto-invalid-digest-e3d6a7","errorCode":"ERR_CRYPTO_INVALID_DIGEST","errorMessage":"Invalid digest: ${digest}","messagePattern":"Invalid digest: (.+?)","errorType":"exception","errorClass":"NodeTypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/crypto/pbkdf2.ts","lineNumber":95,"sourceCode":"  password: any,\n  salt: any,\n  iterations: number,\n  keylen: number,\n  digest: string,\n): Buffer {\n  ({ password, salt, iterations, keylen, digest } = check(\n    password,\n    salt,\n    iterations,\n    keylen,\n    digest,\n  ));\n\n  digest = StringPrototypeToLowerCase(digest);\n\n  const DK = new Uint8Array(keylen);\n  if (!op_node_pbkdf2(password, salt, iterations, digest, DK)) {\n    throw new ERR_CRYPTO_INVALID_DIGEST(digest);\n  }\n\n  return Buffer.from(DK);\n}\n\n/**\n * @param iterations Needs to be higher or equal than zero\n * @param keylen  Needs to be higher or equal than zero but less than max allocation size (2^30)\n * @param digest Algorithm to be used for encryption\n */\nfunction pbkdf2(\n  password: any,\n  salt: any,\n  iterations: number,\n  keylen: number,\n  digest: string,\n  callback: (err: Error | null, derivedKey?: Buffer) => void,\n) {","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/crypto/pbkdf2.ts#L77-L113","documentation":"After pbkdf2 lowercases the digest string and forwards it to the native op, a digest the crypto backend does not recognize makes op_node_pbkdf2 return false and the JS layer throws ERR_CRYPTO_INVALID_DIGEST. digest must be a string naming a known digest algorithm (e.g., 'sha256', 'sha384', 'sha512', 'md5'); note the argument is validated as a string earlier, so this error is specifically about unknown names, not wrong types.","triggerScenarios":"crypto.pbkdf2Sync(pw, salt, 100000, 32, 'sha5123') — a misspelled, empty, or unsupported digest name reaches the native digest lookup and fails; same for the async crypto.pbkdf2 form.","commonSituations":"Digest names copied from another library's enum or a WebCrypto constant that does not map to a native name; typos in configuration ('sha356', 'sha-2'); an optional digest config field left as empty string and defaulted through.","solutions":["Use a canonical lowercase name such as 'sha256', 'sha384' or 'sha512'","Validate digest against crypto.getHashes() before calling pbkdf2","Set an explicit default digest in your config layer instead of letting it fall through to undefined/''"],"exampleFix":"// before\nconst dk = crypto.pbkdf2Sync(pw, salt, iterations, 32, cfg.hash); // cfg.hash = 'sha356' -> throws\n\n// after\nconst digest = crypto.getHashes().includes(cfg.hash) ? cfg.hash : 'sha256';\nconst dk = crypto.pbkdf2Sync(pw, salt, iterations, 32, digest);","handlingStrategy":"validation","validationCode":"if (typeof digest !== 'string' || !crypto.getHashes().includes(digest)) {\n  throw new Error(`unsupported pbkdf2 digest: ${String(digest)}`);\n}\ncrypto.pbkdf2Sync(password, salt, iterations, keylen, digest);","typeGuard":"function isSupportedDigest(name: string): boolean {\n  return crypto.getHashes().includes(name);\n}","tryCatchPattern":"try {\n  crypto.pbkdf2Sync(password, salt, iterations, keylen, digest);\n} catch (e) {\n  if (e?.code === 'ERR_CRYPTO_INVALID_DIGEST') {\n    crypto.pbkdf2Sync(password, salt, iterations, keylen, 'sha256'); // explicit fallback\n  } else throw e;\n}","preventionTips":["Pin the digest to a constant ('sha256'/'sha512') instead of accepting it from config","Validate digest names against crypto.getHashes() at startup","Guard optional config fields from defaulting to empty strings"],"tags":["crypto","pbkdf2","hash","node-compat"],"backgroundTag":"unsupported-hash-algorithm","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}