denoland/deno · error · Error

Invalid digest: ${algorithm}

Error message

Invalid digest: ${algorithm}

What it means

Thrown by the Sign class constructor in Deno's node:crypto polyfill (ext/node/polyfills/internal/crypto/sig.ts:159) when createHash(algorithm) fails, i.e. the digest name passed to new crypto.Sign(algorithm) is not a supported hash. The polyfill throws a plain Error ('Invalid digest: <name>') matching Node's message; in Node itself this carries code ERR_CRYPTO_INVALID_DIGEST. Note the name is lowercased before hashing, so case is not the issue — the algorithm itself must exist (e.g. 'sha1', 'sha256', 'sha512', 'blake2b512').

Source

Thrown at ext/node/polyfills/internal/crypto/sig.ts:159

  constructor(algorithm: string, _options?: any) {
    validateString(algorithm, "algorithm");

    ensureSignProtoSetup();
    const W = getWritable();
    FunctionPrototypeCall(W, this, {
      write(chunk, enc, callback) {
        this.update(chunk, enc);
        callback();
      },
    });

    algorithm = StringPrototypeToLowerCase(algorithm);

    this.#digestType = algorithm;
    try {
      this.hash = createHash(this.#digestType);
    } catch {
      throw new Error(`Invalid digest: ${algorithm}`);
    }
  }

  sign(
    privateKey: any,
    encoding?: any,
  ): Buffer | string {
    if (!privateKey) {
      throw new ERR_CRYPTO_SIGN_KEY_REQUIRED();
    }

    const res = prepareAsymmetricKey(privateKey, kConsumePrivate);

    // Options specific to RSA
    const rsaPadding = getPadding(privateKey);

    // Options specific to RSA-PSS
    const pssSaltLength = getSaltLength(privateKey);

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use node:crypto digest names: 'sha256' not 'sha-256' (see crypto.getHashes() output).
  2. Validate user-supplied algorithm names against crypto.getHashes() before constructing Sign/Verify.
  3. For Ed25519/Ed448 where Node allows a null digest, pass the digest used for the standard flow — with this polyfill supply a valid hash name or restructure to key-object signing per Node docs.

Example fix

// before
const s = new crypto.Sign('SHA-256');

// after
const s = new crypto.Sign('sha256');
// or guard: if (!crypto.getHashes().includes(algo.toLowerCase())) throw new Error('bad algo');
Defensive patterns

Strategy: validation

Validate before calling

const algo = String(rawAlgo).toLowerCase().replace(/-/g, ''); // 'SHA-256' -> 'sha256'
if (!crypto.getHashes().includes(algo)) throw new Error(`unsupported digest: ${rawAlgo}`);
const signer = new crypto.Sign(algo);

Type guard

const isSupportedDigest = (a) => crypto.getHashes().includes(String(a).toLowerCase().replace(/-/g, ''));

Try / catch

try { signer = new crypto.Sign(algo); } catch (e) { if (/^Invalid digest:/.test(e.message)) { signer = new crypto.Sign('sha256'); /* or reject input */ } else throw e; }

Prevention

When it happens

Trigger: new crypto.Sign('sha-256') (hyphenated WebCrypto-style name — use 'sha256'), 'SHA512' works but 'sha-3', 'md6', or a typo like 'sha2256' do not. Also passing null (allowed in Node for Ed25519) is not accepted by this string-validated constructor path.

Common situations: Reusing algorithm identifiers from WebCrypto/SubtleCrypto ('SHA-256') in node:crypto sign/verify flows; env-configurable algorithm names with a typo; assuming an exotic digest is available because OpenSSL lists it.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/5ea4b78096fb359b. Report an issue: GitHub.