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
- Use E = 65537 (0x10001) — well within int32 and universally supported.
- 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.
- Fix the ASN.1/DER decoder so the E INTEGER is read as a single small integer rather than a full bignum.
- 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
- Use E = 65537 exclusively.
- Sanity-check the decoded E value after ASN.1 parsing; it should fit in a uint32 with room to spare.
- Reject keys whose E reads as a multi-word bignum — that is almost always a decoder bug.
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
- crypto/rsa: public exponent is even
- crypto/rsa: missing public modulus
- crypto/rsa: invalid PSS salt length
- crypto/rsa: missing public modulus
- crypto/rsa: public modulus is even
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/6947e8f293db8278.
Report an issue: GitHub.