golang/go · error

rsa: requested hash function unavailable: {hash}

Error message

rsa: requested hash function unavailable: {hash}

What it means

Returned by PrivateKey.Decrypt when opts is *rsa.OAEPOptions and opts.Hash.Available() is false. crypto.Hash.Available() reports whether the hash function is linked into the binary; it returns false if the corresponding package (e.g. crypto/sha512) was never imported, which is common when using a hash solely by its identifier. The Decrypt path refuses to proceed because OAEP needs to instantiate the hash to build the MGF and label digest.

Source

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

	if pssOpts, ok := opts.(*PSSOptions); ok {
		return SignPSS(rand, priv, pssOpts.Hash, digest, pssOpts)
	}

	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

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Blank-import the hash package in your main package: import _ "crypto/sha512".
  2. Use a hash that is unconditionally available in your binary (crypto.SHA256 is pulled in by most stacks).
  3. Before calling Decrypt, guard with if !opts.Hash.Available() { ... } and surface a clearer error.

Example fix

// before: SHA512 not linked
import (
    "crypto"
    "crypto/rsa"
)
pt, err := priv.Decrypt(rand.Reader, ct, &rsa.OAEPOptions{Hash: crypto.SHA512})

// after
import (
    "crypto"
    "crypto/rsa"
    _ "crypto/sha512"
)
pt, err := priv.Decrypt(rand.Reader, ct, &rsa.OAEPOptions{Hash: crypto.SHA512})
Defensive patterns

Strategy: validation

Validate before calling

opts := &rsa.OAEPOptions{Hash: crypto.SHA512}
if !opts.Hash.Available() {
    return errors.New("hash " + opts.Hash.String() + " not linked; import its package")
}
return priv.Decrypt(rand.Reader, ct, opts)

Prevention

When it happens

Trigger: Pass &rsa.OAEPOptions{Hash: crypto.SHA512} to Decrypt in a binary that never imports crypto/sha512 (not even blank-imported); reference crypto.SHA3_256/SHAKE without importing crypto/sha3; cross-compile a stripped binary where the hash package was tree-shaken.

Common situations: Main package uses rsa.OAEPOptions{Hash: crypto.SHA256} but only because another dependency pulled in crypto/sha256 — removing that dependency suddenly breaks OAEP decryption; using a hash constant obtained from configuration or a remote protocol without ensuring the implementation is present.

Related errors


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