golang/go · error

crypto/rsa: public exponent too large

Error message

crypto/rsa: public exponent too large

What it means

Returned by checkPublicKey when pub.E exceeds 2^31-1 (max int32). The Go implementation requires E to fit in a 32-bit int so behavior is identical whether the platform int is 32 or 64 bits (see the linked imperialviolet note on RSAE). FIPS 186-5 allows e < 2^256, but Go deliberately caps tighter than the standard for cross-platform determinism. This is a hard error, not a soft FIPS flag.

Source

Thrown at src/crypto/internal/fips140/rsa/rsa.go:361

	if pub.E < 2 {
		return false, errors.New("crypto/rsa: public exponent too small or negative")
	}
	// e needs to be coprime with p-1 and q-1, since it must be invertible
	// modulo λ(pq). Since p and q are prime, this means e needs to be odd.
	if pub.E&1 == 0 {
		return false, errors.New("crypto/rsa: public exponent is even")
	}
	// FIPS 186-5, Section 5.5(e): "The exponent e shall be an odd, positive
	// integer such that 2¹⁶ < e < 2²⁵⁶."
	if pub.E <= 1<<16 {
		fipsApproved = false
	}
	// We require pub.E to fit into a 32-bit integer so that we
	// do not have different behavior depending on whether
	// int is 32 or 64 bits. See also
	// https://www.imperialviolet.org/2012/03/16/rsae.html.
	if pub.E > 1<<31-1 {
		return false, errors.New("crypto/rsa: public exponent too large")
	}
	return fipsApproved, nil
}

// Encrypt performs the RSA public key operation.
func Encrypt(pub *PublicKey, plaintext []byte) ([]byte, error) {
	fips140.RecordNonApproved()
	if _, err := checkPublicKey(pub); err != nil {
		return nil, err
	}
	return encrypt(pub, plaintext)
}

func encrypt(pub *PublicKey, plaintext []byte) ([]byte, error) {
	m, err := bigmod.NewNat().SetBytes(plaintext, pub.N)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Use E = 65537 (0x10001) — well within int32 and universally supported.
  2. If the key was loaded from disk/network, dump pub.E and verify it equals 65537 (or another small odd value); a huge E means the parser is wrong.
  3. Fix the ASN.1/DER decoder so the E INTEGER is read as a single small integer rather than a full bignum.
  4. Reject keys with E > 2^31-1 at the trust boundary before calling into the crypto package.

Example fix

// before
pub := &rsa.PublicKey{N: n, E: 1 << 31} // too large -> error
// after
pub := &rsa.PublicKey{N: n, E: 65537}
Defensive patterns

Strategy: validation

Validate before calling

func exponentFitsInt32(e int) bool { return e >= 2 && e <= 1<<31-1 }
if !exponentFitsInt32(pub.E) {
    return errors.New("RSA exponent out of int32 range; key parsing likely broken")
}

Prevention

When it happens

Trigger: Passing a PublicKey whose E field holds a value > 2147483647 into any RSA API that calls checkPublicKey. Common with keys parsed from arbitrary bignum ASN.1 where E was decoded as a large integer, or with deliberately adversarial/fuzzed key material.

Common situations: A DER parser bug that misreads the ASN.1 INTEGER for E and produces a multi-word value; adversarial test vectors from a fuzzer; importing a key that was never meant to be used as RSA (e.g. a DSA/EC parameter mislabeled).

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/6947e8f293db8278. Report an issue: GitHub.