golang/go · error

crypto/rsa: hashed message length does not match hash…

Error message

crypto/rsa: hashed message length does not match hash function

What it means

After resolving the hash function name in PKCS#1 v1.5 signing/verification, the library checks that len(hashed) matches the expected digest size for that hash (e.g., 32 bytes for SHA-256, 64 for SHA-512). A mismatch means the caller did not actually hash the message with the claimed algorithm, and signing it would produce a structurally invalid signature.

Solutions

  1. Ensure the hash parameter matches the algorithm used to produce the digest
  2. Let the library hash for you by using SignPKCS1v15 with a hash.Hash instance writing the message, if the API supports it
  3. Verify len(hashed) == hashSize(hashName) before calling the function

Example fix

// before
h := sha512.Sum512(msg)
sig, err := rsa.SignPKCS1v15(rand, key, crypto.SHA256, h[:]) // wrong hash declared

// after
h := sha256.Sum256(msg)
sig, err := rsa.SignPKCS1v15(rand, key, crypto.SHA256, h[:])
Defensive patterns

Strategy: validation

Validate before calling

func validateDigestLength(hash crypto.Hash, digest []byte) error {
    expected := 0
    switch hash {
    case crypto.SHA224: expected = 28
    case crypto.SHA256: expected = 32
    case crypto.SHA384: expected = 48
    case crypto.SHA512: expected = 64
    default: return fmt.Errorf("unsupported hash %v", hash)
    }
    if len(digest) != expected {
        return fmt.Errorf("digest length %d does not match %v (%d)", len(digest), hash, expected)
    }
    return nil
}

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

Try / catch

sig, err := rsa.SignPKCS1v15(rand, key, hashAlg, hashed)
if err != nil {
    return fmt.Errorf("PKCS#1 v1.5 signing failed (check hash/digest match): %w", err)
}

Prevention

When it happens

Trigger: Calling SignPKCS1v15 or VerifyPKCS1v15 where the hash parameter names SHA-256 but hashed is not 32 bytes, or names SHA-512 but hashed is not 64 bytes, etc.

Common situations: Hashing with a different algorithm than declared (e.g., SHA-384 but passing it as SHA-256); passing a truncated or padded digest; double-hashing or passing the raw message instead of its digest; using a wrong hash.Hash instance to produce the digest.

Related errors


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

Appendix: source

Thrown at src/crypto/internal/fips140/rsa/pkcs1v15.go:76

	em, err := pkcs1v15ConstructEM(&priv.pub, hash, hashed)
	if err != nil {
		return nil, err
	}

	return decrypt(priv, em, withCheck)
}

func pkcs1v15ConstructEM(pub *PublicKey, hash string, hashed []byte) ([]byte, error) {
	// Special case: "" is used to indicate that the data is signed directly.
	var prefix []byte
	if hash != "" {
		var ok bool
		prefix, ok = hashPrefixes[hash]
		if !ok {
			return nil, errors.New("crypto/rsa: unsupported hash function")
		}
		if len(hashed) != hashSize(hash) {
			return nil, errors.New("crypto/rsa: hashed message length does not match hash function")
		}
	}

	// EM = 0x00 || 0x01 || PS || 0x00 || T
	k := pub.Size()
	if k < len(prefix)+len(hashed)+2+8+1 {
		return nil, ErrMessageTooLong
	}
	em := make([]byte, k)
	em[1] = 1
	for i := 2; i < k-len(prefix)-len(hashed)-1; i++ {
		em[i] = 0xff
	}
	copy(em[k-len(prefix)-len(hashed):], prefix)
	copy(em[k-len(hashed):], hashed)
	return em, nil
}

View on GitHub (pinned to b6b368adc5)