hyperledger/fabric · error

pem decoding failed

Error message

pem decoding failed

What it means

VerifySignature expects the identity argument to be a PEM-encoded block containing a certificate. pem.Decode returning nil means the bytes are not valid PEM (missing -----BEGIN header, base64 corruption, or already-DER input), so it fails fast with this error.

Source

Thrown at orderer/common/cluster/util.go:716

func GetTLSSessionBinding(ctx context.Context, bindingPayload []byte) ([]byte, error) {
	peerInfo, ok := peer.FromContext(ctx)
	if !ok {
		return nil, errors.New("failed extracting stream context")
	}
	connState := peerInfo.AuthInfo.(credentials.TLSInfo).State

	tlsBinding, err := exportKM(connState, KeyingMaterialLabel, bindingPayload)
	if err != nil {
		return nil, errors.Wrap(err, "failed exporting keying material")
	}

	return tlsBinding, nil
}

func VerifySignature(identity, msgHash, signature []byte) error {
	block, _ := pem.Decode(identity)
	if block == nil {
		return errors.New("pem decoding failed")
	}

	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return errors.Wrap(err, "key extraction failed")
	}

	pubKey, isECDSA := cert.PublicKey.(*ecdsa.PublicKey)
	if !isECDSA {
		return errors.New("not valid public key")
	}

	validSignature := ecdsa.VerifyASN1(pubKey, msgHash, signature)

	if !validSignature {
		return errors.New("signature invalid")
	}
	return nil

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure the identity input is the PEM certificate (-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----)
  2. If you have DER bytes, PEM-encode them (pem.EncodeToMemory with Type CERTIFICATE) before calling
  3. Check the configured cert path actually points to the signer/identity certificate, not the key or CA bundle with extra non-PEM text
  4. Validate with openssl x509 -in cert.pem that the file parses

Example fix

// before
err := VerifySignature(derBytes, msgHash, sig) // derBytes are raw DER
// after
pemBytes := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
err := VerifySignature(pemBytes, msgHash, sig)
Defensive patterns

Strategy: validation

Validate before calling

blk, _ := pem.Decode(identityPEM)
if blk == nil || blk.Type != "CERTIFICATE" {
    return errors.New("identity must be a PEM-encoded certificate")
}

Type guard

func isPEMCertificate(data []byte) bool {
    blk, _ := pem.Decode(data)
    return blk != nil && blk.Type == "CERTIFICATE"
}

Try / catch

err := cluster.VerifySignature(identityPEM, hash, sig)
if err != nil && strings.Contains(err.Error(), "pem decoding failed") {
    return fmt.Errorf("identity is not PEM: check file at MSP path; %w", err)
}

Prevention

When it happens

Trigger: Passing raw DER bytes, an empty slice, a truncated file, or a non-certificate PEM (e.g. a private key or CSR) as the identity parameter to VerifySignature.

Common situations: Certificates read from MSP config that were stored DER-encoded; a config file path pointing to the wrong file; copying a certificate without its BEGIN/END lines; loading a key file instead of the cert file.

Related errors


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