golang/go · error

crypto/rsa: prime Q is nil

Error message

crypto/rsa: prime Q is nil

What it means

Thrown by precompute() when priv.Primes[1] (prime Q) is nil, the symmetric case to prime P. Q is needed for Dq and Qinv computation. Reached only when len(priv.Primes)==2.

Source

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

//
// 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
	}

	k, err := rsa.NewPrivateKey(priv.N.Bytes(), priv.E, priv.D.Bytes(),
		priv.Primes[0].Bytes(), priv.Primes[1].Bytes())

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Generate keys with rsa.GenerateKey so both primes are present.
  2. Run priv.Validate() after parsing to detect the missing prime early.
  3. When assembling by hand, always set both Primes[0] and Primes[1].
  4. Prefer round-tripping through PKCS#1/PKCS#8 rather than field-by-field construction.

Example fix

// before
priv.Primes = []*big.Int{p, nil} // Q missing
priv.Precompute()

// after
priv.Primes = []*big.Int{p, q}
if err := priv.Validate(); err != nil { return err }
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

When it happens

Trigger: Sign/Decrypt/Validate/Precompute on a 2-prime PrivateKey whose Primes[1]==nil. Same shape as the P case: partial construction or lossy serialization.

Common situations: Manual key construction with Primes[0] set but Primes[1] left nil; encoding schemes that drop trailing nils; copy/paste key fixtures missing Q.

Related errors


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