denoland/deno · error · TypeError

ERR_CRYPTO_INVALID_DIGEST

ERR_CRYPTO_INVALID_DIGEST

Error message

Invalid digest: ${hashAlgorithm}

What it means

When generating an 'rsa-pss' key pair, the PSS parameters are validated: if options.hashAlgorithm is provided it must be a string present in crypto.getHashes(), otherwise createJob throws ERR_CRYPTO_INVALID_DIGEST (ext/node/polyfills/internal/crypto/keygen.ts:439-444). The same rule applies one branch later to mgf1HashAlgorithm (with an 'MGF1' suffix on the error). These digests become the signing-digest constraints baked into the PSS key, so they must be real hash algorithms.

Source

Thrown at ext/node/polyfills/internal/crypto/keygen.ts:442

          );
        }
      }

      const {
        hash,
        mgf1Hash,
        hashAlgorithm,
        mgf1HashAlgorithm,
        saltLength,
      } = options;

      if (saltLength !== undefined) {
        validateInt32(saltLength, "options.saltLength", 0);
      }
      if (hashAlgorithm !== undefined) {
        validateString(hashAlgorithm, "options.hashAlgorithm");
        if (!getHashes().includes(hashAlgorithm)) {
          throw new ERR_CRYPTO_INVALID_DIGEST(hashAlgorithm);
        }
      }
      if (mgf1HashAlgorithm !== undefined) {
        validateString(mgf1HashAlgorithm, "options.mgf1HashAlgorithm");
        if (!getHashes().includes(mgf1HashAlgorithm)) {
          throw new ERR_CRYPTO_INVALID_DIGEST(mgf1HashAlgorithm, "MGF1");
        }
      }
      if (hash !== undefined) {
        process.emitWarning(
          '"options.hash" is deprecated, ' +
            'use "options.hashAlgorithm" instead.',
          "DeprecationWarning",
          "DEP0154",
        );
        validateString(hash, "options.hash");
        if (hashAlgorithm && hash !== hashAlgorithm) {
          throw new ERR_INVALID_ARG_VALUE("options.hash", hash);

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use canonical lowercase names: hashAlgorithm: 'sha256' (or sha384/sha512).
  2. Validate both hashAlgorithm and mgf1HashAlgorithm against crypto.getHashes() before generating.
  3. Derive the hash name from the JOSE alg with an explicit mapping: PS256 -> 'sha256', PS384 -> 'sha384', PS512 -> 'sha512'.

Example fix

// before
crypto.generateKeyPairSync('rsa-pss', {
  modulusLength: 2048,
  hashAlgorithm: 'SHA256', // not found in getHashes()
});

// after
crypto.generateKeyPairSync('rsa-pss', {
  modulusLength: 2048,
  hashAlgorithm: 'sha256',
  mgf1HashAlgorithm: 'sha256',
});
Defensive patterns

Strategy: validation

Validate before calling

const PSS_HASH = { PS256: 'sha256', PS384: 'sha384', PS512: 'sha512' };
const hash = PSS_HASH[joseAlg] ?? cfg.hashAlgorithm?.toLowerCase();
if (hash != null && !crypto.getHashes().includes(hash)) {
  throw new Error(`rsa-pss hash '${hash}' not available; use sha256/sha384/sha512`);
}
crypto.generateKeyPairSync('rsa-pss', { modulusLength: 2048, hashAlgorithm: hash });

Type guard

function isPssHash(name) {
  return ['sha256', 'sha384', 'sha512'].includes(String(name).toLowerCase());
}

Try / catch

try {
  crypto.generateKeyPairSync('rsa-pss', { modulusLength, hashAlgorithm: cfg.hash });
} catch (e) {
  if (e.code === 'ERR_CRYPTO_INVALID_DIGEST') {
    return crypto.generateKeyPairSync('rsa-pss', { modulusLength, hashAlgorithm: 'sha256' });
  }
  throw e;
}

Prevention

When it happens

Trigger: generateKeyPairSync('rsa-pss', { modulusLength: 2048, hashAlgorithm: 'sha100' }); hashAlgorithm: 'SHA256' or 'sha-256' spellings not matching getHashes() entries; mgf1HashAlgorithm set to a digest the runtime does not expose (throws the sibling error); values taken from a JWT 'alg' string.

Common situations: Algorithm names from JOSE/JWT config ('PS256' does not name a hash; you need 'sha256'); mixed-casing from config files; switching runtimes where the exposed hash list differs; migrating RSA-PSS settings between OpenSSL CLI flags and node:crypto options.

Related errors


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