golang/go · error
crypto/rsa: prime P is nil
Error message
crypto/rsa: prime P is nil
What it means
Thrown by precompute() when priv.Primes[0] (prime P) is nil, reached only when len(priv.Primes)==2. P is required to compute the CRT values (Dp, Qinv); a nil P makes CRT signing impossible. The guard prevents a nil-pointer dereference in subsequent big.Int operations.
Source
Thrown at src/crypto/rsa/rsa.go:594
}
// precompute calculates the PrecomputedValues for priv and returns them.
//
// It does NOT modify priv and is safe for concurrent use.
func (priv *PrivateKey) precompute() (PrecomputedValues, error) {
var precomputed PrecomputedValues
if priv.N == nil {
return precomputed, errors.New("crypto/rsa: missing public modulus")
}
if priv.D == nil {
return precomputed, errors.New("crypto/rsa: missing private exponent")
}
if len(priv.Primes) != 2 {
return priv.precomputeLegacy()
}
if priv.Primes[0] == nil {
return precomputed, errors.New("crypto/rsa: prime P is nil")
}
if priv.Primes[1] == nil {
return precomputed, errors.New("crypto/rsa: prime Q is nil")
}
// If the CRT values are already set, use them.
if priv.Precomputed.Dp != nil && priv.Precomputed.Dq != nil && priv.Precomputed.Qinv != nil {
k, err := rsa.NewPrivateKeyWithPrecomputation(priv.N.Bytes(), priv.E, priv.D.Bytes(),
priv.Primes[0].Bytes(), priv.Primes[1].Bytes(),
priv.Precomputed.Dp.Bytes(), priv.Precomputed.Dq.Bytes(), priv.Precomputed.Qinv.Bytes())
if err != nil {
return precomputed, err
}
precomputed = priv.Precomputed
precomputed.fips = k
precomputed.CRTValues = make([]CRTValue, 0)
return precomputed, nil
}View on GitHub (pinned to b6b368adc5)
Solutions
- Use rsa.GenerateKey (or rsa.GenerateMultiPrimeKey) so Primes is always populated correctly.
- After parsing, call priv.Validate() to catch missing primes before any private operation.
- When constructing manually, set priv.Primes[0] and priv.Primes[1] to valid *big.Int primes.
- Re-derive a key from a complete PKCS#1/PKCS#8 encoding rather than assembling fields by hand.
Example fix
// before
priv := &rsa.PrivateKey{
PublicKey: rsa.PublicKey{N: n, E: e},
D: d,
Primes: []*big.Int{nil, q}, // P missing
}
err := priv.Validate() // -> prime P is nil
// after
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil { return err }
// or: priv.Primes = []*big.Int{p, q} with both non-nil Defensive patterns
Strategy: validation
Validate before calling
func checkPrimesFilled(priv *rsa.PrivateKey) error {
if len(priv.Primes) != 2 {
return fmt.Errorf("rsa: expected 2 primes, got %d", len(priv.Primes))
}
if priv.Primes[0] == nil || priv.Primes[1] == nil {
return errors.New("rsa: prime P or Q is nil")
}
return priv.Validate()
} Prevention
- Never construct *rsa.PrivateKey by hand with a pre-allocated Primes slice left nil.
- Prefer rsa.GenerateKey; only assemble manually if you also set every prime.
- Run priv.Validate() after deserialization to detect nil primes before Sign/Decrypt.
- Encode keys via PKCS#1/PKCS#8 and re-parse rather than field-level marshaling.
When it happens
Trigger: Sign/Decrypt/Validate/Precompute on a 2-prime PrivateKey whose Primes slice has length 2 but Primes[0]==nil. Happens with hand-built keys, partially zero-value structs, or deserialization that allocated the slice but left entries nil.
Common situations: Constructing rsa.PrivateKey{Primes: make([]*big.Int, 2)} without filling it; JSON/encoding round-trips that omitted zero/big.Int fields; test fixtures that set N and D but forgot Primes.
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/eda22c9e337c205a.
Report an issue: GitHub.