{"record":{"id":"db8871a5b9932e21","repo":"hyperledger/fabric","slug":"identity-doesn-t-match-the-computed-pkiid","errorCode":null,"errorMessage":"identity doesn't match the computed pkiID","messagePattern":"identity doesn't match the computed pkiID","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gossip/identity/identity.go","lineNumber":122,"sourceCode":"\tif pkiID == nil {\n\t\treturn errors.New(\"PKIID is nil\")\n\t}\n\tif identity == nil {\n\t\treturn errors.New(\"identity is nil\")\n\t}\n\n\texpirationDate, err := is.mcs.Expiration(identity)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed classifying identity\")\n\t}\n\n\tif err := is.mcs.ValidateIdentity(identity); err != nil {\n\t\treturn err\n\t}\n\n\tid := is.mcs.GetPKIidOfCert(identity)\n\tif !bytes.Equal(pkiID, id) {\n\t\treturn errors.New(\"identity doesn't match the computed pkiID\")\n\t}\n\n\tis.Lock()\n\tdefer is.Unlock()\n\t// Check if identity already exists.\n\t// If so, no need to overwrite it.\n\tif _, exists := is.pkiID2Cert[string(pkiID)]; exists {\n\t\treturn nil\n\t}\n\n\tvar expirationTimer *time.Timer\n\tif !expirationDate.IsZero() {\n\t\tif time.Now().After(expirationDate) {\n\t\t\treturn errors.New(\"gossipping peer identity expired\")\n\t\t}\n\t\t// Identity would be wiped out a millisecond after its expiration date\n\t\ttimeToLive := time.Until(expirationDate.Add(time.Millisecond))\n\t\texpirationTimer = time.AfterFunc(timeToLive, func() {","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/gossip/identity/identity.go#L104-L140","documentation":"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.","triggerScenarios":"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.","commonSituations":"Manually wiring identities in tests; processing tampered or mis-routed gossip messages; PKI-ID derivation changes after a Fabric/crypto library upgrade.","solutions":["Always derive pkiID via mcs.GetPKIidOfCert(identity) for the exact identity being registered instead of trusting caller-supplied values","Verify the peer's identity source (message fields) isn't mixing identities from different peers","Check for version skew in crypto libraries that changes PKI-ID derivation between components"],"exampleFix":"// before\nerr := mapper.Put(msg.PkiId, identity) // pkiID taken from message\n\n// after\npkiID := mapper.GetPKIidOfCert(identity) // via mcs\nerr := mapper.Put(pkiID, identity)","handlingStrategy":"validation","validationCode":"computed := mcs.GetPKIidOfCert(identity)\nif !bytes.Equal(computed, pkiID) {\n    return errors.New(\"refusing to put: identity/pkiID mismatch\")\n}\nerr := mapper.Put(pkiID, identity)","typeGuard":"func pkiIDMatches(mcs api.MessageCryptoService, pkiID common.PKIidType, id api.PeerIdentityType) bool {\n    return bytes.Equal(pkiID, mcs.GetPKIidOfCert(id))\n}","tryCatchPattern":"if err := mapper.Put(pkiID, identity); err != nil && strings.Contains(err.Error(), \"doesn't match the computed pkiID\") {\n    logger.Warning(\"identity/pkiID mismatch — possible tampering or stale identity\")\n    return\n}","preventionTips":["Always derive pkiID via mcs.GetPKIidOfCert(identity) for the same identity you register","Never trust pki-id fields from messages without recomputing them","Watch for crypto library/Fabric version skew affecting PKI-ID derivation","Treat mismatch errors as security signals, not transient failures"],"tags":["gossip","hyperledger-fabric","identity","crypto"],"backgroundTag":"pkiid-identity-mismatch","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}