golang/go · error

crypto/rsa: public exponent is even

Error message

crypto/rsa: public exponent is even

What it means

Returned by checkPublicKey when the RSA public exponent E is even. RSA correctness requires e to be invertible modulo lambda(pq); since p and q are prime (odd), p-1 and q-1 are even, so e must be odd to be coprime. An even exponent has no inverse mod lambda(pq) and breaks encryption/decryption. The check pub.E&1 == 0 is a hard failure (returns false, err), unlike the FIPS-approval flags.

Source

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

	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")
	}
	return fipsApproved, nil
}

// Encrypt performs the RSA public key operation.
func Encrypt(pub *PublicKey, plaintext []byte) ([]byte, error) {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Set E to the de-facto standard 65537 (0x10001) on the PublicKey; this is odd and FIPS-approved.
  2. If you loaded the key from PEM/DER, re-decode it and inspect pub.E in hex; a wrong endianness or truncated field is the usual cause of an even E.
  3. If you must use a small exponent for research, use 3 or 17 (both odd) — but note small exponents are not FIPS-approved and are flagged separately.
  4. Add a unit assertion that pub.E&1 == 1 before passing the key into the crypto API.

Example fix

// before
pub := &rsa.PublicKey{N: n, E: 65536} // even -> error
// after
pub := &rsa.PublicKey{N: n, E: 65537} // 0x10001, odd
Defensive patterns

Strategy: validation

Validate before calling

func validPublicExponent(e int) bool {
    return e >= 2 && e&1 == 1 && e <= 1<<31-1
}
// before RSA ops:
if !validPublicExponent(pub.E) {
    return fmt.Errorf("invalid RSA exponent E=%d", pub.E)
}

Prevention

When it happens

Trigger: Constructing a rsa.PublicKey (or fips140/rsa.PublicKey) with an even E value (e.g. 2, 4, 6, 65536) and calling any API that runs checkPublicKey: Encrypt, encrypt, signature verification, key validation. Even one zero low bit triggers it.

Common situations: Hardcoded test fixtures with a non-standard exponent; key material imported from a malformed PEM/DER where E was decoded incorrectly; custom key generators that pick E=3 (odd, fine) but accidentally compute a wrong E; big-endian/little-endian swap of E turning 0x10001 into an even value.

Related errors


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