golang/go · error

crypto/rsa: use of primes of different sizes is not allowed

Error message

crypto/rsa: use of primes of different sizes is not allowed in FIPS 140-only mode

What it means

Thrown by checkFIPS140OnlyPrivateKey when FIPS 140-only mode (GODEBUG=fips140=only) is active and a private key carries two primes whose bit lengths differ, or where one of Primes[0]/Primes[1] is nil. FIPS 140-3 requires the two RSA primes to be of equal length, so the standard library refuses to use such a key for any private-key operation under that mode. The check is applied during key validation/import paths (e.g. via NewPrivateKey / Precompute / Validate) in FIPS-only builds.

Source

Thrown at src/crypto/rsa/fips.go:469

	}
	if pub.E&1 == 0 {
		return errors.New("crypto/rsa: use of even public exponent is not allowed in FIPS 140-only mode")
	}
	return nil
}

func checkFIPS140OnlyPrivateKey(priv *PrivateKey) error {
	if !fips140only.Enforced() {
		return nil
	}
	if err := checkFIPS140OnlyPublicKey(&priv.PublicKey); err != nil {
		return err
	}
	if len(priv.Primes) != 2 {
		return errors.New("crypto/rsa: use of multi-prime keys is not allowed in FIPS 140-only mode")
	}
	if priv.Primes[0] == nil || priv.Primes[1] == nil || priv.Primes[0].BitLen() != priv.Primes[1].BitLen() {
		return errors.New("crypto/rsa: use of primes of different sizes is not allowed in FIPS 140-only mode")
	}
	return nil
}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Regenerate the key with rsa.GenerateKey(rand.Reader, 2048) (or 3072/4096) — it always produces equal-length primes.
  2. If you must keep an existing key, rebuild the binary without GODEBUG=fips140=only (drop the fips140=only setting) so non-approved keys are tolerated.
  3. Re-import the key via crypto/x509.ParsePKCS1PrivateKey / ParsePKCS8PrivateKey and then validate with priv.Validate() before use; replace the key if validation surfaces prime problems.
  4. Audit upstream key sources (HSM, KMS, JWK export) to ensure they emit equal-bit-length primes.

Example fix

// before: loading a key with mismatched prime lengths under FIPS-only
priv, _ := x509.ParsePKCS1PrivateKey(raw) // raw has |p| != |q| bits
plaintext, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, priv, ct, nil) // err: primes of different sizes

// after: regenerate a FIPS-compatible key
priv, _ := rsa.GenerateKey(rand.Reader, 2048)
Defensive patterns

Strategy: validation

Validate before calling

// Run before using a private key under FIPS-only mode.
func checkFIPSKey(priv *rsa.PrivateKey) error {
    if len(priv.Primes) != 2 || priv.Primes[0] == nil || priv.Primes[1] == nil {
        return errors.New("key must have exactly two non-nil primes for FIPS-only")
    }
    if priv.Primes[0].BitLen() != priv.Primes[1].BitLen() {
        return errors.New("primes must be equal bit length for FIPS-only")
    }
    return nil
}

Prevention

When it happens

Trigger: Load a legacy PKCS#1/PKCS#8 RSA key whose p and q differ in length while GODEBUG=fips140=only is set; or manually construct a PrivateKey with Primes[0].BitLen() != Primes[1].BitLen(); or feed a key where one prime slice element is nil into a private-key operation under FIPS-only mode.

Common situations: Migrating an old keyring generated by non-Go tooling (e.g. OpenSSL with a stripped leading zero in one prime, or hand-tuned keys) into a FIPS-only Go service; loading test fixtures crafted for non-FIPS builds; reading keys from PEM/DER that came from hardware tokens that emit asymmetric primes.

Related errors


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