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
- Use rsa.NewPrivateKey / NewPrivateKeyWithoutCRT (FIPS module) or x509.ParsePKCS1PrivateKey to build keys — they reject incomplete inputs upstream with clearer errors.
- If you only have N, e, d, obtain p and q from the source (re-export the full CRT material from your KMS/HSM).
- 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
- Parse keys with x509.ParsePKCS1PrivateKey / ParsePKCS8PrivateKey rather than building literals.
- Treat d-only keys as unsupported; request full CRT material from the KMS.
- Run Validate() at load time, not lazily during request handling.
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
- crypto/rsa: invalid prime
- crypto/rsa: p * q != n
- crypto/rsa: invalid CRT exponent
- crypto/rsa: invalid CRT coefficient
- crypto/rsa: d does not match dP
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/662dafddcc0fe776.
Report an issue: GitHub.