golang/go · critical
crypto/rsa: public modulus is even
Error message
crypto/rsa: public modulus is even
What it means
Thrown by checkPublicKey when N is even (N.Nat().IsOdd() == 0). RSA modulus N = p*q where p,q are odd primes, so N is always odd; an even N is either 2-smooth (trivially factorable) or corrupted, and cannot be a valid RSA modulus.
Source
Thrown at src/crypto/internal/fips140/rsa/rsa.go:332
//
// See section 3 of https://crypto.stanford.edu/~dabo/papers/RSA-survey.pdf
// for more details about attacks on small d values.
//
// Likewise, the leakage of the magnitude of d is not adaptive.
if priv.d.BitLenVarTime() <= N.BitLen()/2 {
return errors.New("crypto/rsa: d too small")
}
return nil
}
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")
}View on GitHub (pinned to b6b368adc5)
Solutions
- Use keys produced by rsa.GenerateKey, which always yields odd N.
- On import, reject N whose least-significant bit is 0.
- Re-serialize and re-parse to rule out byte-order corruption.
Example fix
// before
// N built or parsed such that it is even
// after
if n.Bit(0) == 0 {
return errors.New("RSA modulus must be odd")
}
pub := &rsa.PublicKey{N: n, E: 65537} Defensive patterns
Strategy: validation
Validate before calling
if n.Bit(0) == 0 {
return errors.New("RSA modulus must be odd")
} Type guard
func modulusOdd(n *big.Int) bool { return n.Bit(0) == 1 } Try / catch
err := op(pub)
if err != nil && strings.Contains(err.Error(), "public modulus is even") {
return err // regenerate; N is corrupt or invalid
} Prevention
- Use keys from rsa.GenerateKey, which always yields odd N.
- Reject even N on import.
- Re-serialize/re-parse to rule out byte corruption.
When it happens
Trigger: checkPublicKey tests N.Nat().IsOdd() == 0 during any RSA operation that validates the public key. Fires when the low bit of N is 0.
Common situations: N constructed as an even number in a test/fixture. A byte-corrupted N whose low bit flipped to 0. A custom key builder that multiplied 2 into N. Mis-parsed big-endian bytes dropping the leading odd byte.
Related errors
- crypto/rsa: missing public modulus
- crypto/rsa: public exponent too small or negative
- crypto/rsa: |p - q| too small
- crypto/rsa: d too small
- cipher: message authentication failed
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/450fa27811224965.
Report an issue: GitHub.