golang/go · error

crypto/rsa: missing primes

Error message

crypto/rsa: missing primes

What it means

Returned by PrivateKey.Validate when len(priv.Primes) < 2. The RSA implementation requires at least the two classical primes p and q; a key that only carries D (a 'CRT-less' or d-only key) cannot be validated by this routine because the CRT-based consistency checks need p and q. The doc comment also notes that such keys cannot be encoded by x509.MarshalPKCS1PrivateKey, so they are rejected early.

Source

Thrown at src/crypto/rsa/rsa.go:244

}

// CRTValue contains the precomputed Chinese remainder theorem values.
type CRTValue struct {
	Exp   *big.Int // D mod (prime-1).
	Coeff *big.Int // R·Coeff ≡ 1 mod Prime.
	R     *big.Int // product of primes prior to this (inc p and q).
}

// Validate performs basic sanity checks on the key.
// It returns nil if the key is valid, or else an error describing a problem.
//
// It runs faster on valid keys if run after [PrivateKey.Precompute].
func (priv *PrivateKey) Validate() error {
	// We can operate on keys based on d alone, but they can't be encoded with
	// [crypto/x509.MarshalPKCS1PrivateKey], which unfortunately doesn't return
	// an error, so we need to reject them here.
	if len(priv.Primes) < 2 {
		return errors.New("crypto/rsa: missing primes")
	}
	// If Precomputed.fips is set and consistent, then the key has been
	// validated by [rsa.NewPrivateKey] or [rsa.NewPrivateKeyWithoutCRT].
	if priv.precomputedIsConsistent() {
		return nil
	}
	if priv.Precomputed.fips != nil {
		return errors.New("crypto/rsa: precomputed values are inconsistent with the key")
	}
	_, err := priv.precompute()
	return err
}

func (priv *PrivateKey) precomputedIsConsistent() bool {
	if priv.Precomputed.fips == nil {
		return false
	}
	N, e, d, P, Q, dP, dQ, qInv := priv.Precomputed.fips.Export()

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Use rsa.NewPrivateKey / NewPrivateKeyWithoutCRT (FIPS module) or x509.ParsePKCS1PrivateKey to build keys — they reject incomplete inputs upstream with clearer errors.
  2. If you only have N, e, d, obtain p and q from the source (re-export the full CRT material from your KMS/HSM).
  3. Skip Validate() only if you can guarantee correctness by other means and never need MarshalPKCS1PrivateKey.

Example fix

// before: key reconstructed with only D
priv := &rsa.PrivateKey{
    PublicKey: rsa.PublicKey{N: n, E: e},
    D:         d,
}
err := priv.Validate() // err: missing primes

// after: include primes
priv.Primes = []*big.Int{p, q}
err := priv.Validate()
Defensive patterns

Strategy: validation

Validate before calling

if priv == nil || len(priv.Primes) < 2 {
    return errors.New("RSA private key must include at least two primes")
}
return priv.Validate()

Prevention

When it happens

Trigger: Build a PrivateKey struct with D set but Primes empty or with one prime; call Validate() (directly or transitively via Precompute then Validate) on that key; partially parse a key file that omitted primes.

Common situations: Loading JWK / PEM that only exposes 'd' (some cloud KMS export formats omit CRT params); constructing a key in tests for sign-only use without realizing Validate needs both primes; deserializing a corrupt key.

Related errors


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