hyperledger/fabric · error

identity doesn't match the computed pkiID

Error message

identity doesn't match the computed pkiID

What it means

After classification and validation succeed, Put recomputes the PKI-ID from the certificate via mcs.GetPKIidOfCert and requires it to byte-equal the supplied pkiID. A mismatch means the caller associated an identity with the wrong PKI-ID — a integrity check protecting the identity store against spoofed key/identity pairs.

Source

Thrown at gossip/identity/identity.go:122

	if pkiID == nil {
		return errors.New("PKIID is nil")
	}
	if identity == nil {
		return errors.New("identity is nil")
	}

	expirationDate, err := is.mcs.Expiration(identity)
	if err != nil {
		return errors.Wrap(err, "failed classifying identity")
	}

	if err := is.mcs.ValidateIdentity(identity); err != nil {
		return err
	}

	id := is.mcs.GetPKIidOfCert(identity)
	if !bytes.Equal(pkiID, id) {
		return errors.New("identity doesn't match the computed pkiID")
	}

	is.Lock()
	defer is.Unlock()
	// Check if identity already exists.
	// If so, no need to overwrite it.
	if _, exists := is.pkiID2Cert[string(pkiID)]; exists {
		return nil
	}

	var expirationTimer *time.Timer
	if !expirationDate.IsZero() {
		if time.Now().After(expirationDate) {
			return errors.New("gossipping peer identity expired")
		}
		// Identity would be wiped out a millisecond after its expiration date
		timeToLive := time.Until(expirationDate.Add(time.Millisecond))
		expirationTimer = time.AfterFunc(timeToLive, func() {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Always derive pkiID via mcs.GetPKIidOfCert(identity) for the exact identity being registered instead of trusting caller-supplied values
  2. Verify the peer's identity source (message fields) isn't mixing identities from different peers
  3. Check for version skew in crypto libraries that changes PKI-ID derivation between components

Example fix

// before
err := mapper.Put(msg.PkiId, identity) // pkiID taken from message

// after
pkiID := mapper.GetPKIidOfCert(identity) // via mcs
err := mapper.Put(pkiID, identity)
Defensive patterns

Strategy: validation

Validate before calling

computed := mcs.GetPKIidOfCert(identity)
if !bytes.Equal(computed, pkiID) {
    return errors.New("refusing to put: identity/pkiID mismatch")
}
err := mapper.Put(pkiID, identity)

Type guard

func pkiIDMatches(mcs api.MessageCryptoService, pkiID common.PKIidType, id api.PeerIdentityType) bool {
    return bytes.Equal(pkiID, mcs.GetPKIidOfCert(id))
}

Try / catch

if err := mapper.Put(pkiID, identity); err != nil && strings.Contains(err.Error(), "doesn't match the computed pkiID") {
    logger.Warning("identity/pkiID mismatch — possible tampering or stale identity")
    return
}

Prevention

When it happens

Trigger: Calling Put with a (pkiID, identity) pair where pkiID was taken from a different peer's message, hand-crafted, or computed with a different hash/cert than the one in identity.

Common situations: Manually wiring identities in tests; processing tampered or mis-routed gossip messages; PKI-ID derivation changes after a Fabric/crypto library upgrade.

Related errors


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