{"record":{"id":"93f59897c73779bc","repo":"golang/go","slug":"crypto-rsa-prime-factor-is-nil","errorCode":null,"errorMessage":"crypto/rsa: prime factor is nil","messagePattern":"crypto/rsa: prime factor is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/rsa/rsa.go","lineNumber":645,"sourceCode":"}\n\nfunc (priv *PrivateKey) precomputeLegacy() (PrecomputedValues, error) {\n\tvar precomputed PrecomputedValues\n\n\tk, err := rsa.NewPrivateKeyWithoutCRT(priv.N.Bytes(), priv.E, priv.D.Bytes())\n\tif err != nil {\n\t\treturn precomputed, err\n\t}\n\tprecomputed.fips = k\n\n\tif len(priv.Primes) < 2 {\n\t\treturn precomputed, nil\n\t}\n\n\t// Ensure the Mod and ModInverse calls below don't panic.\n\tfor _, prime := range priv.Primes {\n\t\tif prime == nil {\n\t\t\treturn precomputed, errors.New(\"crypto/rsa: prime factor is nil\")\n\t\t}\n\t\tif prime.Cmp(bigOne) <= 0 {\n\t\t\treturn precomputed, errors.New(\"crypto/rsa: prime factor is <= 1\")\n\t\t}\n\t}\n\n\tprecomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne)\n\tprecomputed.Dp.Mod(priv.D, precomputed.Dp)\n\n\tprecomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne)\n\tprecomputed.Dq.Mod(priv.D, precomputed.Dq)\n\n\tprecomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0])\n\tif precomputed.Qinv == nil {\n\t\treturn precomputed, errors.New(\"crypto/rsa: prime factors are not relatively prime\")\n\t}\n\n\tr := new(big.Int).Mul(priv.Primes[0], priv.Primes[1])","sourceCodeStart":627,"sourceCodeEnd":663,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/rsa/rsa.go#L627-L663","documentation":"Thrown in the legacy precompute path (after the FIPS key is built) when iterating priv.Primes and finding any nil element. This loop runs for keys with >=2 primes to compute Dp/Dq/Qinv and additional CRT values, guarding the Mod and ModInverse calls from a nil receiver.","triggerScenarios":"Sign/Decrypt/Validate on a multi-prime or 2-prime key where any entry of priv.Primes is nil. Distinct from errors 521/522 because it covers primes beyond index 1 as well (multi-prime RSA).","commonSituations":"rsa.GenerateMultiPrimeKey result with a corrupted Primes slice; deserialized key where some prime entries failed to decode; test code that built a >2-prime key but left a middle entry nil.","solutions":["Regenerate the key with rsa.GenerateKey or rsa.GenerateMultiPrimeKey.","After load, call priv.Validate() to surface nil primes before use.","Inspect priv.Primes for nil entries if you must construct manually: every element must be non-nil.","Re-parse from an authoritative PKCS#1 encoding."],"exampleFix":"// before\npriv.Primes = []*big.Int{p, q, nil, r} // index 2 nil\nerr := priv.Validate()\n\n// after\npriv.Primes = []*big.Int{p, q, r} // all non-nil\nerr := priv.Validate()","handlingStrategy":"validation","validationCode":"func checkAllPrimesNonNil(priv *rsa.PrivateKey) error {\n    for i, p := range priv.Primes {\n        if p == nil {\n            return fmt.Errorf(\"rsa: prime[%d] is nil\", i)\n        }\n    }\n    return priv.Validate()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["For multi-prime keys, verify every element of Primes is non-nil before use.","Generate multi-prime keys only with rsa.GenerateMultiPrimeKey.","Run priv.Validate() after load; it exercises the full precompute path.","Treat imported multi-prime keys as untrusted and validate thoroughly."],"tags":["crypto","rsa","key-validation","multi-prime","go"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}