hyperledger/fabric · error

identity in signature header does not match expected identit

Error message

identity in signature header does not match expected identity

What it means

The IdentifierHeader inside a consenter signature must carry the same identity number as the identity that supposedly produced the signature (identityID, derived from the signature verification with the node's channel membership). This error means the signature's declared consenter ID does not match the identity that actually signed — a signature attributed to the wrong consenter, or a node using the wrong TLS/channel identity.

Source

Thrown at orderer/consensus/smartbft/verifier.go:399

	// BlockHeader          []byte
	// OrdererBlockMetadata []byte

	// Ensure block header is equal
	if !bytes.Equal(prop.Header, sig.BlockHeader) {
		v.Logger.Errorf("Expected block header %s but got %s", base64.StdEncoding.EncodeToString(prop.Header),
			base64.StdEncoding.EncodeToString(sig.BlockHeader))
		return errors.Errorf("mismatched block header")
	}

	// Ensure signature header matches the identity
	sigHdr := &cb.IdentifierHeader{}
	if err := proto.Unmarshal(sig.IdentifierHeader, sigHdr); err != nil {
		return errors.Wrap(err, "malformed signature header")
	}
	if identityID != uint64(sigHdr.Identifier) {
		v.Logger.Warnf("Expected identity %d but got %d", identityID,
			sigHdr.Identifier)
		return errors.Errorf("identity in signature header does not match expected identity")
	}

	// Ensure orderer block metadata's consenter MD matches the proposal
	ordererMD := &cb.OrdererBlockMetadata{}
	if err := proto.Unmarshal(sig.OrdererBlockMetadata, ordererMD); err != nil {
		return errors.Wrap(err, "malformed orderer metadata in signature")
	}

	if !bytes.Equal(ordererMD.ConsenterMetadata, prop.Metadata) {
		v.Logger.Warnf("Expected consenter metadata %s but got %s in proposal",
			base64.StdEncoding.EncodeToString(ordererMD.ConsenterMetadata), base64.StdEncoding.EncodeToString(prop.Metadata))
		return errors.Errorf("consenter metadata in OrdererBlockMetadata doesn't match proposal")
	}

	block, err := ProposalToBlock(prop)
	if err != nil {
		v.Logger.Warnf("got malformed proposal: %v", err)
		return err

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure all consenters have processed the latest channel config so identity-to-ID mappings agree, and restart nodes whose mapping is stale.
  2. Verify each ordering node's TLS certificates and local MSP match its configured consenter entry.
  3. Trigger a view change after any channel membership change so signatures are regenerated with correct identifiers.
  4. Check for membership churn (nodes added/removed) around the time of the error and re-verify the consenter list ordering.

Example fix

// before: mapping skew after membership change
identityID = 3 (from cert); sigHdr.Identifier = 2 -> error
// after: all nodes agree on identity mapping
identityID = 3; sigHdr.Identifier = 3
Defensive patterns

Strategy: validation

Validate before calling

sigHdr := &cb.IdentifierHeader{}
if err := proto.Unmarshal(sig.IdentifierHeader, sigHdr); err != nil { return err }
if identityID != uint64(sigHdr.Identifier) {
    // membership mapping is stale; refresh channel config before trusting signatures
    return fmt.Errorf("identity %d != header id %d", identityID, sigHdr.Identifier)
}

Try / catch

if err := verifySig(sig); err != nil && strings.Contains(err.Error(), "identity in signature header") {
    refreshMembershipMapping()
    return err
}

Prevention

When it happens

Trigger: VerifyConsenterSig -> verifySignatureIsBoundToProposal: identityID != uint64(sigHdr.Identifier). Triggered when a signature arrives claiming to be from consenter N but its certificate/identity resolves to a different slot number, or the IdentifierHeader was built with a stale/wrong self ID.

Common situations: Consenter order changed in the channel config (e.g. a node removed/added) while another node cached the old identity-to-slot mapping; a node restarted with the wrong TLS keypair/certificate; configuration change not yet propagated to all nodes; a misbehaving node signing with another's ID.

Related errors


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