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

  1. Use keys produced by rsa.GenerateKey, which always yields odd N.
  2. On import, reject N whose least-significant bit is 0.
  3. 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

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


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