golang/go · error

crypto/rsa: input must be hashed with given hash

Error message

crypto/rsa: input must be hashed with given hash

What it means

In RSASSA-PSS encoding (emsa_pss_encode), the mHash (message digest) must be exactly hLen bytes, where hLen is hash.Size() for the hash function passed to SignPSS. This check ensures the caller actually hashed the message with the specified algorithm before PSS padding is applied. A length mismatch indicates a protocol or caller error.

Source

Thrown at src/crypto/internal/fips140/rsa/pkcs1v22.go:86

		incCounter(&counter)
	}
}

func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) {
	// See RFC 8017, Section 9.1.1.

	hLen := hash.Size()
	sLen := len(salt)
	emLen := (emBits + 7) / 8

	// 1.  If the length of M is greater than the input limitation for the
	//     hash function (2^61 - 1 octets for SHA-1), output "message too
	//     long" and stop.
	//
	// 2.  Let mHash = Hash(M), an octet string of length hLen.

	if len(mHash) != hLen {
		return nil, errors.New("crypto/rsa: input must be hashed with given hash")
	}

	// 3.  If emLen < hLen + sLen + 2, output "encoding error" and stop.

	if emLen < hLen+sLen+2 {
		return nil, ErrMessageTooLong
	}

	em := make([]byte, emLen)
	psLen := emLen - sLen - hLen - 2
	db := em[:psLen+1+sLen]
	h := em[psLen+1+sLen : emLen-1]

	// 4.  Generate a random octet string salt of length sLen; if sLen = 0,
	//     then salt is the empty string.
	//
	// 5.  Let
	//       M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt;

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Ensure the hash.Hash passed to SignPSS is the same one used to compute the digest
  2. Verify len(hashed) == hash.Size() before calling SignPSS
  3. Use a helper that both hashes and signs in one step to avoid the mismatch

Example fix

// before
hash := sha512.New()
hash.Write(msg)
digest := sha256.Sum256(msg) // wrong hash!
sig, err := rsa.SignPSS(rand, key, hash, digest[:], nil)

// after
hash := sha256.New()
hash.Write(msg)
sig, err := rsa.SignPSS(rand, key, crypto.SHA256, hash.Sum(nil), nil)
Defensive patterns

Strategy: validation

Validate before calling

func validatePSSDigest(hash crypto.Hash, digest []byte) error {
    if len(digest) != hash.Size() {
        return fmt.Errorf("PSS digest length %d != %v size %d", len(digest), hash, hash.Size())
    }
    return nil
}

if err := validatePSSDigest(hashAlg, digest); err != nil { return err }
sig, err := rsa.SignPSS(rand, key, hashAlg, digest, nil)

Try / catch

sig, err := rsa.SignPSS(rand, key, hashAlg, hashed, nil)
if err != nil {
    return fmt.Errorf("PSS signing failed (check hash/digest match): %w", err)
}

Prevention

When it happens

Trigger: Calling rsa.SignPSS with a hashed slice whose length does not equal hash.Size() — e.g., passing a 32-byte SHA-256 digest but with a SHA-512 hash.Hash instance, or passing a truncated digest.

Common situations: Mismatch between the hash.Hash instance and the actual digest bytes (common when refactoring hash algorithms); passing a pre-computed digest from a different hash function; accidentally passing the raw message instead of its hash.

Related errors


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