golang/go · error
crypto/rsa: public exponent too small or negative
Error message
crypto/rsa: public exponent too small or negative
What it means
Thrown by checkPublicKey when the public exponent E < 2. The exponent must be an odd integer >= 3 to be invertible modulo λ(N) (E=1 makes every signature/message identical, E<=0 is meaningless). This guard rejects degenerate exponents before checking oddness and the FIPS bounds (2^16 < e < 2^256).
Source
Thrown at src/crypto/internal/fips140/rsa/rsa.go:344
func checkPublicKey(pub *PublicKey) (fipsApproved bool, err error) {
fipsApproved = true
if pub.N == nil {
return false, errors.New("crypto/rsa: missing public modulus")
}
if pub.N.Nat().IsOdd() == 0 {
return false, errors.New("crypto/rsa: public modulus is even")
}
// FIPS 186-5, Section 5.1: "This standard specifies the use of a modulus
// whose bit length is an even integer and greater than or equal to 2048
// bits."
if pub.N.BitLen() < 2048 {
fipsApproved = false
}
if pub.N.BitLen()%2 == 1 {
fipsApproved = false
}
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")
}View on GitHub (pinned to b6b368adc5)
Solutions
- Set E to 65537 (the conventional value) when constructing the PublicKey, or parse it via x509.
- Guard with an E >= 3 and odd check before any RSA operation.
- Regenerate the key pair; rsa.GenerateKey sets E = 65537 by default.
Example fix
// before
pub := &rsa.PublicKey{N: n} // E zero-valued to 0
// after
pub := &rsa.PublicKey{N: n, E: 65537}
if pub.E < 3 || pub.E&1 == 0 {
return errors.New("invalid RSA public exponent")
} Defensive patterns
Strategy: validation
Validate before calling
if pub.E < 3 || pub.E&1 == 0 {
return fmt.Errorf("invalid RSA public exponent: %d", pub.E)
} Type guard
func validPublicExponent(e int) bool { return e >= 3 && e&1 == 1 } Try / catch
err := op(pub)
if err != nil && strings.Contains(err.Error(), "public exponent too small or negative") {
return err // set E = 65537 or regenerate
} Prevention
- Set E = 65537 when building a PublicKey, or parse via x509.
- Never leave E at its zero value.
- Guard E >= 3 and odd before any RSA operation.
When it happens
Trigger: checkPublicKey tests pub.E < 2 during any RSA operation that validates the public key. Fires for E = 0, 1, or negative values.
Common situations: A zero-value rsa.PublicKey with E == 0 used before population. A parse failure that left E unset. A custom builder that copied the wrong field into E. Negative E from a signed-int conversion bug.
Related errors
- crypto/rsa: missing public modulus
- crypto/rsa: public modulus is even
- ecdsa: invalid uncompressed public key
- input overflows the modulus
- input overflows the modulus size
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/d201c33f7cb8923c.
Report an issue: GitHub.