{"record":{"id":"a7150f0c2a6c89cb","repo":"golang/go","slug":"crypto-rsa-prime-factors-are-not-relatively-prime","errorCode":null,"errorMessage":"crypto/rsa: prime factors are not relatively prime","messagePattern":"crypto/rsa: prime factors are not relatively prime","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/rsa/rsa.go","lineNumber":660,"sourceCode":"\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])\n\tprecomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2)\n\tfor i := 2; i < len(priv.Primes); i++ {\n\t\tprime := priv.Primes[i]\n\t\tvalues := &precomputed.CRTValues[i-2]\n\n\t\tvalues.Exp = new(big.Int).Sub(prime, bigOne)\n\t\tvalues.Exp.Mod(priv.D, values.Exp)\n\n\t\tvalues.R = new(big.Int).Set(r)\n\t\tvalues.Coeff = new(big.Int).ModInverse(r, prime)\n\t\tif values.Coeff == nil {\n\t\t\treturn precomputed, errors.New(\"crypto/rsa: prime factors are not relatively prime\")\n\t\t}\n\n\t\tr.Mul(r, prime)","sourceCodeStart":642,"sourceCodeEnd":678,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/rsa/rsa.go#L642-L678","documentation":"Thrown when big.Int.ModInverse(priv.Primes[1], priv.Primes[0]) (Q mod P) returns nil, meaning P and Q are not coprime. A valid RSA key requires gcd(P,Q)==1 so that Qinv exists; non-coprime primes make CRT decryption ambiguous. This indicates an invalid or corrupted key.","triggerScenarios":"Sign/Decrypt/Validate on a 2-prime key where P and Q share a common factor (e.g., P==Q, or P divides Q). Reached after the prime nil/<=1 guards pass.","commonSituations":"Key generated by a broken/non-conformant generator; P and Q accidentally set equal; adversarial key injection; a test key reused for both primes.","solutions":["Regenerate the key with rsa.GenerateKey, which guarantees distinct random primes.","Call priv.Validate() to catch mathematical inconsistency (it checks the P*Q==N relationship).","If importing keys, verify P != Q and gcd(P,Q)==1 before trusting them.","Treat any key failing this check as untrusted and discard it."],"exampleFix":"// before\npriv.Primes = []*big.Int{p, p} // P == Q, not coprime\nerr := priv.Validate()\n\n// after\npriv, err := rsa.GenerateKey(rand.Reader, 2048) // distinct random primes\nif err != nil { return err }","handlingStrategy":"validation","validationCode":"import \"math/big\"\n\nfunc checkCoprimePQ(priv *rsa.PrivateKey) error {\n    if len(priv.Primes) < 2 { return priv.Validate() }\n    p, q := priv.Primes[0], priv.Primes[1]\n    if new(big.Int).GCD(nil, nil, p, q).Cmp(big.NewInt(1)) != 0 {\n        return errors.New(\"rsa: P and Q not coprime\")\n    }\n    return priv.Validate()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate keys with rsa.GenerateKey to guarantee distinct random primes.","Run priv.Validate() to catch P*Q==N inconsistency and coprimality issues.","Never reuse a prime for both P and Q, even in tests.","Treat keys failing coprimality as corrupted or adversarial."],"tags":["crypto","rsa","key-validation","math","go"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}