{"record":{"id":"7053a798eda5c5a1","repo":"golang/go","slug":"crypto-rsa-missing-private-exponent","errorCode":null,"errorMessage":"crypto/rsa: missing private exponent","messagePattern":"crypto/rsa: missing private exponent","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/rsa/rsa.go","lineNumber":588,"sourceCode":"\t\t// We don't have a way to report errors, so just leave Precomputed.fips\n\t\t// nil. Validate will re-run precompute and report its error.\n\t\tpriv.Precomputed.fips = nil\n\t\treturn\n\t}\n\tpriv.Precomputed = precomputed\n}\n\n// precompute calculates the PrecomputedValues for priv and returns them.\n//\n// It does NOT modify priv and is safe for concurrent use.\nfunc (priv *PrivateKey) precompute() (PrecomputedValues, error) {\n\tvar precomputed PrecomputedValues\n\n\tif priv.N == nil {\n\t\treturn precomputed, errors.New(\"crypto/rsa: missing public modulus\")\n\t}\n\tif priv.D == nil {\n\t\treturn precomputed, errors.New(\"crypto/rsa: missing private exponent\")\n\t}\n\tif len(priv.Primes) != 2 {\n\t\treturn priv.precomputeLegacy()\n\t}\n\tif priv.Primes[0] == nil {\n\t\treturn precomputed, errors.New(\"crypto/rsa: prime P is nil\")\n\t}\n\tif priv.Primes[1] == nil {\n\t\treturn precomputed, errors.New(\"crypto/rsa: prime Q is nil\")\n\t}\n\n\t// If the CRT values are already set, use them.\n\tif priv.Precomputed.Dp != nil && priv.Precomputed.Dq != nil && priv.Precomputed.Qinv != nil {\n\t\tk, err := rsa.NewPrivateKeyWithPrecomputation(priv.N.Bytes(), priv.E, priv.D.Bytes(),\n\t\t\tpriv.Primes[0].Bytes(), priv.Primes[1].Bytes(),\n\t\t\tpriv.Precomputed.Dp.Bytes(), priv.Precomputed.Dq.Bytes(), priv.Precomputed.Qinv.Bytes())\n\t\tif err != nil {\n\t\t\treturn precomputed, err","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/rsa/rsa.go#L570-L606","documentation":"Thrown by rsa.PrivateKey.precompute() when priv.D (the private exponent) is nil. precompute() runs lazily during Sign, Decrypt, Validate, or Precompute, so a PrivateKey missing D is unusable for any private operation. The check is an early guard before any math touches D.","triggerScenarios":"Calling SignASN1/Sign, DecryptASN1/Decrypt, Validate(), or Precompute() on an *rsa.PrivateKey whose D field is nil. Typically a key built by hand, parsed from incomplete DER/PEM, or a PublicKey accidentally stored where a PrivateKey is expected.","commonSituations":"Loading a public-key-only PEM (BEGIN PUBLIC KEY) into an x509.ParsePKCS1PrivateKey path; constructing PrivateKey{PublicKey:...} without setting D; truncated or corrupted key file; marshaling/unmarshaling that dropped D.","solutions":["Verify the source PEM/DER is a private key (BEGIN RSA/RSA PRIVATE KEY or PKCS8) and parse it with the matching x509 parser.","Call priv.Validate() right after parsing to surface malformation before use.","Ensure D is populated when constructing keys manually: priv.D must be a non-nil *big.Int.","If only a public key is available, do not call Sign/Decrypt; use the PublicKey for verification only."],"exampleFix":"// before\nblock, _ := pem.Decode(data)\npriv, _ := x509.ParsePKCS1PublicKey(block.Bytes) // public key only\nsig, err := rsa.SignASN1(rand, priv, hash, digest) // D is nil -> error\n\n// after\nblock, _ := pem.Decode(data)\npriv, err := x509.ParsePKCS1PrivateKey(block.Bytes)\nif err != nil { return err }\nif err := priv.Validate(); err != nil { return err }\nsig, err := rsa.SignASN1(rand, priv, hash, digest)","handlingStrategy":"validation","validationCode":"// Validate an RSA private key before any private operation.\nfunc mustRSAPrivate(priv *rsa.PrivateKey) error {\n    if priv == nil || priv.D == nil {\n        return errors.New(\"rsa: private key missing D (public key only?)\")\n    }\n    return priv.Validate()\n}\n\n// usage:\nif err := mustRSAPrivate(priv); err != nil { return err }","typeGuard":"func isRSAPrivateKey(v any) bool {\n    k, ok := v.(*rsa.PrivateKey)\n    return ok && k != nil && k.D != nil && k.N != nil\n}","tryCatchPattern":null,"preventionTips":["Parse keys with the x509 function matching the PEM block type; never feed a public key into a private-key parser.","Call priv.Validate() immediately after parsing to catch missing fields before first use.","When constructing keys manually, populate N, D, E, and Primes together or use rsa.GenerateKey.","Unit-test key loading with a fixture that has D stripped to ensure your error path triggers."],"tags":["crypto","rsa","key-validation","go"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}