hyperledger/fabric · error

claimed TLS cert hash is %v but actual TLS cert hash is %v

Error message

claimed TLS cert hash is %v but actual TLS cert hash is %v

What it means

The claimed TLS cert hash in the message does not match the hash of the actual TLS certificate on the gRPC connection. This is the core anti-replay binding check: it proves the signed message came over this specific TLS channel.

Source

Thrown at common/deliver/binding.go:59

	}
}

// mutualTLSBinding enforces the client to send its TLS cert hash in the message,
// and then compares it to the computed hash that is derived
// from the gRPC context.
// In case they don't match, or the cert hash is missing from the request or
// there is no TLS certificate to be excavated from the gRPC context,
// an error is returned.
func mutualTLSBinding(ctx context.Context, claimedTLScertHash []byte) error {
	if len(claimedTLScertHash) == 0 {
		return errors.Errorf("client didn't include its TLS cert hash")
	}
	actualTLScertHash := util.ExtractCertificateHashFromContext(ctx)
	if len(actualTLScertHash) == 0 {
		return errors.Errorf("client didn't send a TLS certificate")
	}
	if !bytes.Equal(actualTLScertHash, claimedTLScertHash) {
		return errors.Errorf("claimed TLS cert hash is %v but actual TLS cert hash is %v", claimedTLScertHash, actualTLScertHash)
	}
	return nil
}

// noopBinding is a BindingInspector that always returns nil
func noopBinding(_ context.Context, _ []byte) error {
	return nil
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Recompute the TLS cert hash from the certificate actually presented on the current connection and resend
  2. Restart/reconnect the client after certificate rotation so the hash matches the new cert
  3. Verify the client hashes the same cert file configured for the TLS handshake
Defensive patterns

Strategy: validation

Validate before calling

actualHash := util.ExtractCertificateHashFromContext(ctx)
if !bytes.Equal(actualHash, claimedTLScertHash) {
    return errors.New("stale TLS cert hash: reconnect and recompute")
}

Try / catch

if err := inspector(ctx, msg); err != nil {
    if strings.Contains(err.Error(), "claimed TLS cert hash is") {
        return reconnectAndResend() // hash mismatch: rebind to current TLS channel
    }
    return err
}

Prevention

When it happens

Trigger: A client sends a cert hash computed from one certificate while connecting with another (stale cached hash, cert rotated mid-session, or a forged/misrouted request).

Common situations: Certificate rotation without refreshing the client-side cached hash; multiple TLS certs on disk and the client hashes the wrong one; connection reused across identity switches.

Understand the failure class

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/44da542d57189ca7. Report an issue: GitHub.