auth0/node-jsonwebtoken · error

secretOrPrivateKey has a minimum key size of 2048 bits for $

Error message

secretOrPrivateKey has a minimum key size of 2048 bits for ${header.alg}

What it means

For RS/PS algorithms, jwt.sign() performs a post-signature length check: an RSA signature shorter than 256 bytes implies a modulus smaller than 2048 bits, which the library rejects as insecure. This protects against weak keys; it can be bypassed with the allowInsecureKeySizes option (or is unnecessary on Node 15+, which enforces key size at crypto level).

Source

Thrown at sign.js:249

    jws.createSign({
      header: header,
      privateKey: secretOrPrivateKey,
      payload: payload,
      encoding: encoding
    }).once('error', callback)
      .once('done', function (signature) {
        // TODO: Remove in favor of the modulus length check before signing once node 15+ is the minimum supported version
        if(!options.allowInsecureKeySizes && /^(?:RS|PS)/.test(header.alg) && signature.length < 256) {
          return callback(new Error(`secretOrPrivateKey has a minimum key size of 2048 bits for ${header.alg}`))
        }
        callback(null, signature);
      });
  } else {
    let signature = jws.sign({header: header, payload: payload, secret: secretOrPrivateKey, encoding: encoding});
    // TODO: Remove in favor of the modulus length check before signing once node 15+ is the minimum supported version
    if(!options.allowInsecureKeySizes && /^(?:RS|PS)/.test(header.alg) && signature.length < 256) {
      throw new Error(`secretOrPrivateKey has a minimum key size of 2048 bits for ${header.alg}`)
    }
    return signature
  }
};

View on GitHub (pinned to b924272f29)

Solutions

  1. Generate a new RSA key of at least 2048 bits: openssl genrsa -out key.pem 2048 (4096 preferred)
  2. Set options.allowInsecureKeySizes: true only for legacy/testing, never in production
  3. On Node 15+, rely on native enforcement — upgrade the key regardless, since Node will also reject short keys
  4. Rotate the key pair and update all verifiers with the new public key

Example fix

// before
openssl genrsa -out key.pem 1024
jwt.sign(payload, key, { algorithm: 'RS256' });
// after
openssl genrsa -out key.pem 2048
jwt.sign(payload, key, { algorithm: 'RS256' });
Defensive patterns

Strategy: validation

Validate before calling

const { createPublicKey } = require('crypto');
function rsaKeyBitsOk(pem) {
  const key = createPublicKey(pem);
  const bits = key.asymmetricKeyDetails?.modulusLength;
  return bits === undefined || bits >= 2048;
}
if (!rsaKeyBitsOk(privateKey)) throw new Error('RSA key must be >= 2048 bits');

Type guard

function hasSufficientRsaModulus(keyObj) {
  const bits = keyObj?.asymmetricKeyDetails?.modulusLength;
  return bits === undefined || bits >= 2048;
}

Try / catch

try {
  return jwt.sign(payload, key, { algorithm: 'RS256' });
} catch (err) {
  if (/minimum key size of 2048/.test(err.message)) {
    throw new Error('Refusing to sign with weak RSA key; regenerate at 2048+ bits');
  }
  throw err;
}

Prevention

When it happens

Trigger: jwt.sign(payload, smallRsaKeyPem, { algorithm: 'RS256' }) with a 1024-bit (or smaller) RSA key; verification-side equivalents where the private key used was generated with -b 1024.

Common situations: Old RSA keys generated years ago at 1024 bits; test fixtures with tiny keys; OpenSSL defaults changed over versions so legacy automation still emits 1024-bit keys; copying sample keys from old tutorials.

Related errors


AI-assisted analysis of auth0/node-jsonwebtoken@b924272f29 (2026-09-02). Data as JSON: /api/errors/a6d995fb15916676. Report an issue: GitHub.