{"record":{"id":"2f978aa4424bb3ba","repo":"hyperledger/fabric","slug":"failed-to-pem-decode-identity-bytes-s","errorCode":null,"errorMessage":"failed to PEM decode identity bytes: %s","messagePattern":"failed to PEM decode identity bytes: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/crypto/sanitize.go","lineNumber":45,"sourceCode":"\tif err := proto.Unmarshal(identity, sID); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed unmarshaling identity %s\", string(identity))\n\t}\n\n\tfinalPEM, err := SanitizeX509Cert(sID.IdBytes)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tsID.IdBytes = finalPEM\n\n\treturn proto.Marshal(sID)\n}\n\n// SanitizeX509Cert sanitizes an X.509 certificate to ensure that the ECDSA signature uses a \"low-S\" value.\nfunc SanitizeX509Cert(initialPEM []byte) ([]byte, error) {\n\tder, _ := pem.Decode(initialPEM)\n\tif der == nil {\n\t\treturn nil, errors.Errorf(\"failed to PEM decode identity bytes: %s\", string(initialPEM))\n\t}\n\tcert, err := x509.ParseCertificate(der.Bytes)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed parsing certificate %s\", string(initialPEM))\n\t}\n\n\tr, s, err := utils.UnmarshalECDSASignature(cert.Signature)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed unmarshaling ECDSA signature on identity: %s\", string(initialPEM))\n\t}\n\n\t// We assume that the consenter and the CA use the same signature scheme.\n\tcurveOrderUsedByCryptoGen := cert.PublicKey.(*ecdsa.PublicKey).Curve.Params().N\n\thalfOrder := new(big.Int).Rsh(curveOrderUsedByCryptoGen, 1)\n\t// Low S, nothing to do here!\n\tif s.Cmp(halfOrder) != 1 {\n\t\treturn initialPEM, nil\n\t}","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/crypto/sanitize.go#L27-L63","documentation":"SanitizeX509Cert expects the input to be a PEM block containing a certificate. pem.Decode returned nil, meaning the bytes are not valid PEM (wrong format, binary DER, or empty), so the error includes the raw input string.","triggerScenarios":"Calling SanitizeX509Cert (directly or via SanitizeIdentity, ConfigureNodeCerts, IsChannelMember) with DER-encoded certificates, double-encoded PEM, empty bytes, or text that merely looks like a certificate.","commonSituations":"Storing certs DER-encoded then feeding them to fabric's sanitizer; copy-paste losing the BEGIN/END lines or adding stray whitespace/BOM; config pointing at the wrong file (key instead of cert); IdBytes populated with a hash rather than PEM.","solutions":["Ensure the input is PEM: starts with '-----BEGIN CERTIFICATE-----' and ends with the END line","If you have DER, convert to PEM (openssl x509 -inform DER -outform PEM) before calling","Verify file paths/config so the certificate, not the private key or another artifact, is loaded","Strip extraneous whitespace/BOM and re-export the certificate cleanly"],"exampleFix":"// before\nsanitized, _ := crypto.SanitizeX509Cert(derBytes)\n// after\npemBytes := pem.EncodeToMemory(&pem.Block{Type: \"CERTIFICATE\", Bytes: derBytes})\nsanitized, err := crypto.SanitizeX509Cert(pemBytes)","handlingStrategy":"validation","validationCode":"func isPEMCertificate(b []byte) bool {\n    blk, _ := pem.Decode(b)\n    return blk != nil && blk.Type == \"CERTIFICATE\"\n}","typeGuard":null,"tryCatchPattern":"out, err := crypto.SanitizeX509Cert(pemBytes)\nif err != nil && strings.Contains(err.Error(), \"failed to PEM decode\") {\n    // re-encode DER to PEM or fix the file path before retrying\n}","preventionTips":["Keep certs PEM-encoded everywhere; convert DER at the edge","Check that config points to certificate files, not key files","Verify BEGIN/END lines survive copy-paste and file transfers"],"tags":["x509","pem","certificate","hyperledger-fabric"],"backgroundTag":"pem-decode-failed","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"}