denoland/deno · error · NodeError

ERR_OSSL_DH_MODULUS_TOO_SMALL

ERR_OSSL_DH_MODULUS_TOO_SMALL

Error message

modulus too small

What it means

When DiffieHellman is constructed with a numeric prime length instead of prime material, lengths below 2 throw ERR_OSSL_DH_MODULUS_TOO_SMALL ('modulus too small') at diffiehellman.ts:180, mirroring OpenSSL's floor for DH prime generation. Only 0 and 1 are rejected here — but such sizes are cryptographically worthless anyway.

Source

Thrown at ext/node/polyfills/internal/crypto/diffiehellman.ts:180

      if (isArrayBufferView(sizeOrKey) || isAnyArrayBuffer(sizeOrKey)) {
        if (isArrayBufferView(sizeOrKey)) {
          const parts = getViewParts(sizeOrKey as ArrayBufferView);
          this.#prime = Buffer.from(parts.ab, parts.off, parts.len);
        } else {
          this.#prime = Buffer.from(
            sizeOrKey,
            0,
            ArrayBufferPrototypeGetByteLength(sizeOrKey as ArrayBuffer),
          );
        }
      } else {
        this.#prime = toBuf(sizeOrKey as string, keyEncoding as string);
      }
    } else {
      // The supplied parameter is our primeLength, generate a suitable prime.
      this.#primeLength = sizeOrKey as number;
      if (this.#primeLength < 2) {
        throw new NodeError(
          "ERR_OSSL_DH_MODULUS_TOO_SMALL",
          "modulus too small",
        );
      }

      this.#prime = Buffer.from(
        TypedArrayPrototypeGetBuffer(
          op_node_gen_prime(this.#primeLength, false, null, null),
        ),
      );
    }

    if (!generator) {
      generator = DH_GENERATOR;
    }

    if (typeof generator === "number") {
      validateInt32(generator, "generator");

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Pass a real bit length — 2048 or 3072 in production (values < 2 throw here, but anything small is insecure)
  2. Validate the configured size (integer, >= 2048) in one place before constructing
  3. Check bits-vs-bytes mix-ups: the constructor takes bits

Example fix

// before
new DiffieHellman(Number(process.env.DH_BITS ?? 0)); // 0 -> modulus too small

// after
const bits = Number(process.env.DH_BITS ?? 2048);
if (!Number.isInteger(bits) || bits < 2048) throw new Error('DH_BITS must be an integer >= 2048');
new DiffieHellman(bits);
Defensive patterns

Strategy: validation

Validate before calling

function assertDhBits(n) {
  if (!Number.isInteger(n) || n < 2) throw new RangeError('DH prime length must be an integer >= 2');
  if (n < 2048) console.warn('DH primes below 2048 bits are insecure');
}

Prevention

When it happens

Trigger: new DiffieHellman(0) or new DiffieHellman(1); createDiffieHellman(Number(cfg.dhBits)) where cfg.dhBits is unset/NaN/0; byte-length values (16, 32) confused with bit lengths after arithmetic errors produce small numbers.

Common situations: Bit-size env var missing so Number(undefined) -> NaN or a 0 default; test fixtures with toy sizes; unit mix-ups between bits and bytes in config.

Understand the failure class

Related errors


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