hyperledger/fabric · error

%s TLS certificate has invalid ASN1 structure %s

Error message

%s TLS certificate has invalid ASN1 structure %s

What it means

parseCertificateFromBytes decodes a PEM-encoded TLS certificate and calls x509.ParseCertificate. When the PEM block exists but its DER bytes are not a valid ASN.1 DER certificate, the Go standard library parse fails and Hyperledger Fabric wraps that err (plus the raw PEM bytes) into an errors.Errorf. This signals malformed certificate data supplied via channel config, not a network or trust issue.

Source

Thrown at orderer/consensus/etcdraft/util.go:266

		}
	}

	if err := MetadataHasDuplication(metadata); err != nil {
		return err
	}

	return nil
}

func parseCertificateFromBytes(cert []byte) (*x509.Certificate, error) {
	pemBlock, _ := pem.Decode(cert)
	if pemBlock == nil {
		return &x509.Certificate{}, errors.Errorf("no PEM data found in cert[% x]", cert)
	}

	certificate, err := x509.ParseCertificate(pemBlock.Bytes)
	if err != nil {
		return nil, errors.Errorf("%s TLS certificate has invalid ASN1 structure %s", err, string(pemBlock.Bytes))
	}

	return certificate, nil
}

func parseCertificateListFromBytes(certs [][]byte) ([]*x509.Certificate, error) {
	var certificateList []*x509.Certificate

	for _, cert := range certs {
		certificate, err := parseCertificateFromBytes(cert)
		if err != nil {
			return certificateList, err
		}

		certificateList = append(certificateList, certificate)
	}

	return certificateList, nil

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Regenerate or re-export the certificate as a valid PEM/DER X.509 cert (openssl x509 -in cert.pem -text -noout must succeed) and re-run configtxgen
  2. Confirm the field points to the certificate, not the private key (-----BEGIN CERTIFICATE----- vs -----BEGIN PRIVATE KEY-----)
  3. Decode the failing bytes from the wrapped message and inspect them; fix base64 corruption/truncation
  4. If certs come from an MSP folder, ensure tls/ca.crt and tlscacerts files are intact and correctly mounted

Example fix

// before: key mistakenly used as cert in configtx.yaml
client_tls_cert: "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0t..."
// after: base64 of a real CERTIFICATE PEM
client_tls_cert: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0t..."
Defensive patterns

Strategy: validation

Validate before calling

// validate before placing into config / calling the API
func validateTLSCertBytes(certPEM []byte) error {
    block, _ := pem.Decode(certPEM)
    if block == nil {
        return fmt.Errorf("no PEM data")
    }
    if _, err := x509.ParseCertificate(block.Bytes); err != nil {
        return fmt.Errorf("invalid ASN1 cert: %w", err)
    }
    return nil
}
// run: validateTLSCertBytes(tlsCertBytes) before channel config update

Type guard

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

Prevention

When it happens

Trigger: etcdraft channel config update where a consenter's client_tls_cert or server_tls_cert is not a valid DER-encoded X.509 certificate (e.g. a key file, empty/garbage PEM payload, or truncated base64) — raised via validateConsenterTLSCerts, parseCertificateListFromBytes, or TestVerifyConfigMetadata paths such as VerifyConfigMetadata/ValidateConsensusMetadata.

Common situations: Ops paste the node's TLS private key instead of the certificate into configtx.yaml; the cert file was copied with corrupted/missing lines; an intermediate tool re-encoded the PEM incorrectly; a generated cert was replaced with a CSR or a PKCS#12 blob.

Understand the failure class

Related errors


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