golang/go · error

rsa: requested hash function unavailable: {mgfHash}

Error message

rsa: requested hash function unavailable: {mgfHash}

What it means

Returned by PrivateKey.Decrypt when opts is *rsa.OAEPOptions, opts.MGFHash is non-zero, and opts.MGFHash.Available() is false. Same root cause as error 503 but for the mask-generation function hash: the package that implements opts.MGFHash is not linked into the binary, so MGF1 cannot be constructed. Note that if MGFHash == 0 the code silently reuses opts.Hash, so this error fires only when MGFHash is explicitly set.

Source

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

	return SignPKCS1v15(rand, priv, opts.HashFunc(), digest)
}

// Decrypt decrypts ciphertext with priv. If opts is nil or of type
// *[PKCS1v15DecryptOptions] then PKCS #1 v1.5 decryption is performed. Otherwise
// opts must have type *[OAEPOptions] and OAEP decryption is done.
func (priv *PrivateKey) Decrypt(rand io.Reader, ciphertext []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error) {
	if opts == nil {
		return DecryptPKCS1v15(rand, priv, ciphertext)
	}

	switch opts := opts.(type) {
	case *OAEPOptions:
		if !opts.Hash.Available() {
			return nil, errors.New("rsa: requested hash function unavailable: " + opts.Hash.String())
		}
		if opts.MGFHash != 0 && !opts.MGFHash.Available() {
			return nil, errors.New("rsa: requested hash function unavailable: " + opts.MGFHash.String())
		}
		if opts.MGFHash == 0 {
			return decryptOAEP(opts.Hash.New(), opts.Hash.New(), priv, ciphertext, opts.Label)
		} else {
			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 {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Blank-import the package that backs MGFHash (e.g. import _ "crypto/sha512" for SHA-384/512).
  2. Omit MGFHash (leave it zero) so Decrypt reuses opts.Hash — only do this when protocol allows a single hash.
  3. Validate opts.MGFHash.Available() before calling Decrypt and fail with a domain-specific error.

Example fix

// before
opts := &rsa.OAEPOptions{Hash: crypto.SHA256, MGFHash: crypto.SHA384}
pt, err := priv.Decrypt(rand.Reader, ct, opts) // err: requested hash function unavailable

// after
import _ "crypto/sha512" // provides SHA-384 / SHA-512
Defensive patterns

Strategy: validation

Validate before calling

opts := &rsa.OAEPOptions{Hash: crypto.SHA256, MGFHash: crypto.SHA384}
if opts.MGFHash != 0 && !opts.MGFHash.Available() {
    return errors.New("MGF hash " + opts.MGFHash.String() + " not linked")
}
return priv.Decrypt(rand.Reader, ct, opts)

Prevention

When it happens

Trigger: Construct &rsa.OAEPOptions{Hash: crypto.SHA256, MGFHash: crypto.SHA384} without importing crypto/sha512 (which provides SHA384); set MGFHash to a hash identifier obtained from a JOSE/JWT header whose algorithm is not compiled in.

Common situations: Multi-hash OAEP profiles (e.g. some Smartcard / PIV / Federal PKI deployments use SHA-256 message + SHA-512 MGF); algorithm agility where the MGF hash comes from configuration.

Related errors


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