golang/go · error

crypto/rsa: invalid options for Decrypt

Error message

crypto/rsa: invalid options for Decrypt

What it means

Returned by PrivateKey.Decrypt when opts is not nil and is not one of the two recognized concrete types (*rsa.OAEPOptions or *rsa.PKCS1v15DecryptOptions). The crypto.DecrypterOpts interface allows arbitrary types, but this RSA implementation only supports those two; anything else falls into the default switch case. Note it is the pointer types that are matched — passing a non-pointer OAEPOptions value will also hit this path.

Source

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

			return decryptOAEP(opts.Hash.New(), opts.MGFHash.New(), priv, ciphertext, opts.Label)
		}

	case *PKCS1v15DecryptOptions:
		if l := opts.SessionKeyLen; l > 0 {
			plaintext = make([]byte, l)
			if _, err := io.ReadFull(rand, plaintext); err != nil {
				return nil, err
			}
			if err := DecryptPKCS1v15SessionKey(rand, priv, ciphertext, plaintext); err != nil {
				return nil, err
			}
			return plaintext, nil
		} else {
			return DecryptPKCS1v15(rand, priv, ciphertext)
		}

	default:
		return nil, errors.New("crypto/rsa: invalid options for Decrypt")
	}
}

type PrecomputedValues struct {
	Dp, Dq *big.Int // D mod (P-1) (or mod Q-1)
	Qinv   *big.Int // Q^-1 mod P

	// CRTValues is used for the 3rd and subsequent primes. Due to a
	// historical accident, the CRT for the first two primes is handled
	// differently in PKCS #1 and interoperability is sufficiently
	// important that we mirror this.
	//
	// Deprecated: These values are still filled in by Precompute for
	// backwards compatibility but are not used. Multi-prime RSA is very rare,
	// and is implemented by this package without CRT optimizations to limit
	// complexity.
	CRTValues []CRTValue

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Pass &rsa.OAEPOptions{...} or &rsa.PKCS1v15DecryptOptions{...} — note the address-of operator.
  2. Pass nil to default to PKCS#1 v1.5 decryption.
  3. If you hold a generic crypto.DecrypterOpts, type-switch before calling Decrypt and translate unknown types rather than forwarding them.

Example fix

// before: passed by value
pt, err := priv.Decrypt(rand.Reader, ct, rsa.OAEPOptions{Hash: crypto.SHA256})

// after: passed by pointer
pt, err := priv.Decrypt(rand.Reader, ct, &rsa.OAEPOptions{Hash: crypto.SHA256})
Defensive patterns

Strategy: type-guard

Type guard

func isKnownRSAOpts(opts crypto.DecrypterOpts) bool {
    if opts == nil { return true }
    switch opts.(type) {
    case *rsa.OAEPOptions, *rsa.PKCS1v15DecryptOptions:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Pass a custom type implementing crypto.DecrypterOpts to priv.Decrypt; pass rsa.OAEPOptions{} by value instead of &rsa.OAEPOptions{}; pass an interface wrapping a third-party options struct.

Common situations: Generic crypto code that accepts crypto.DecrypterOpts from a caller and forwards it without narrowing; copy-paste mistake omitting the & on OAEPOptions.

Related errors


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