{"record":{"id":"f4ed5cdb98233fa2","repo":"hyperledger/fabric","slug":"public-keys-do-not-match","errorCode":null,"errorMessage":"public keys do not match","messagePattern":"public keys do not match","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"common/crypto/expiration.go","lineNumber":104,"sourceCode":"\n\tinfo(\"The %s certificate will expire on %s\", certRole, expirationTime)\n\n\tif timeLeftUntilExpiration < oneWeek {\n\t\tdays := timeLeftUntilExpiration / (time.Hour * 24)\n\t\thours := (timeLeftUntilExpiration - (days * time.Hour * 24)) / time.Hour\n\t\twarn(\"The %s certificate expires within %d days and %d hours\", certRole, days, hours)\n\t\treturn\n\t}\n\n\ttimeLeftUntilOneWeekBeforeExpiration := timeLeftUntilExpiration - oneWeek\n\n\tsched(timeLeftUntilOneWeekBeforeExpiration, func() {\n\t\twarn(\"The %s certificate will expire within one week\", certRole)\n\t})\n}\n\n// ErrPubKeyMismatch is used by CertificatesWithSamePublicKey to indicate the two public keys mismatch\nvar ErrPubKeyMismatch = errors.New(\"public keys do not match\")\n\n// LogNonPubKeyMismatchErr logs an error which is not an ErrPubKeyMismatch error\nfunc LogNonPubKeyMismatchErr(log func(template string, args ...any), err error, cert1DER, cert2DER []byte) {\n\tcert1PEM := &pem.Block{Type: \"CERTIFICATE\", Bytes: cert1DER}\n\tcert2PEM := &pem.Block{Type: \"CERTIFICATE\", Bytes: cert2DER}\n\tlog(\"Failed determining if public key of %s matches public key of %s: %s\",\n\t\tstring(pem.EncodeToMemory(cert1PEM)),\n\t\tstring(pem.EncodeToMemory(cert2PEM)),\n\t\terr)\n}\n\n// CertificatesWithSamePublicKey returns nil if both byte slices\n// are valid DER encoding of certificates with the same public key.\nfunc CertificatesWithSamePublicKey(der1, der2 []byte) error {\n\tcert1canonized, err := publicKeyFromCertificate(der1)\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/crypto/expiration.go#L86-L122","documentation":"ErrPubKeyMismatch is returned by CertificatesWithSamePublicKey when two certificates compared for key-equivalence do not share the same public key. It's a sentinel error used to distinguish a benign mismatch from actual comparison failures.","triggerScenarios":"Calling CertificatesWithSamePublicKey (or TestCertificatesWithSamePublicKey) with two DER certificates whose public keys differ; the function compares parsed public keys and returns this sentinel when they are not equal.","commonSituations":"Certificate rotation replaced a cert with a new key while gossip/tls code expected key-material reuse; comparing certs from different CAs/identities; remediation logic for CVE-2020-7919 style key-collision checks where keys genuinely differ.","solutions":["Treat the sentinel as expected behavior — re-issue or fetch the certificate that actually reuses the same public key","Log via LogNonPubKeyMismatchErr only for other errors; skip handling for this one (errors.Is(err, ErrPubKeyMismatch))","Verify you loaded the intended certificate files (wrong file/path mixups are common)","If key reuse is required (e.g. after CA migration), re-sign the CSR of the original key instead of using a new key"],"exampleFix":"// before\nif err != nil { log.Fatal(err) }\n// after\nif errors.Is(err, crypto.ErrPubKeyMismatch) {\n    // benign: certs use different keys\n    return\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isPubKeyMismatch(err error) bool { return errors.Is(err, crypto.ErrPubKeyMismatch) }","tryCatchPattern":"if err != nil {\n    if errors.Is(err, crypto.ErrPubKeyMismatch) {\n        // benign mismatch, continue\n    } else {\n        crypto.LogNonPubKeyMismatchErr(log, err, der1, der2)\n    }\n}","preventionTips":["Use errors.Is against the sentinel instead of string matching","Route all non-mismatch errors through LogNonPubKeyMismatchErr","Track certificate rotations so key-reuse expectations stay accurate"],"tags":["hyperledger-fabric","x509","certificate","public-key"],"backgroundTag":"public-key-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"}