hyperledger/fabric · error

failed unmarshaling ECDSA signature on identity: %s

Error message

failed unmarshaling ECDSA signature on identity: %s

What it means

SanitizeX509Cert extracts the certificate's ECDSA signature and unmarshals the r,s integers. If cert.Signature is not a valid ASN.1 ECDSA signature pair, this wrapped error is returned. The sanitizer normalizes high-S signatures, so it must be able to parse the signature first.

Source

Thrown at common/crypto/sanitize.go:54

	sID.IdBytes = finalPEM

	return proto.Marshal(sID)
}

// SanitizeX509Cert sanitizes an X.509 certificate to ensure that the ECDSA signature uses a "low-S" value.
func SanitizeX509Cert(initialPEM []byte) ([]byte, error) {
	der, _ := pem.Decode(initialPEM)
	if der == nil {
		return nil, errors.Errorf("failed to PEM decode identity bytes: %s", string(initialPEM))
	}
	cert, err := x509.ParseCertificate(der.Bytes)
	if err != nil {
		return nil, errors.Wrapf(err, "failed parsing certificate %s", string(initialPEM))
	}

	r, s, err := utils.UnmarshalECDSASignature(cert.Signature)
	if err != nil {
		return nil, errors.Wrapf(err, "failed unmarshaling ECDSA signature on identity: %s", string(initialPEM))
	}

	// We assume that the consenter and the CA use the same signature scheme.
	curveOrderUsedByCryptoGen := cert.PublicKey.(*ecdsa.PublicKey).Curve.Params().N
	halfOrder := new(big.Int).Rsh(curveOrderUsedByCryptoGen, 1)
	// Low S, nothing to do here!
	if s.Cmp(halfOrder) != 1 {
		return initialPEM, nil
	}
	// Else it's high-S, so shift it below half the order.
	s.Sub(curveOrderUsedByCryptoGen, s)

	var newCert certificate
	_, err = asn1.Unmarshal(cert.Raw, &newCert)
	if err != nil {
		return nil, errors.Wrapf(err, "failed unmarshaling certificate")
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure all node/CA certificates are ECDSA-signed (fabric's sanitizer assumes ECDSA keys — see the type assertion to *ecdsa.PublicKey)
  2. Re-issue certificates from a standards-compliant CA with proper DER ECDSA signatures
  3. Check the wrapped inner error to confirm whether the signature is malformed or of the wrong algorithm
  4. Verify the certificate wasn't truncated/re-encoded by intermediate tooling
Defensive patterns

Strategy: validation

Validate before calling

blk, _ := pem.Decode(certPEM)
cert, err := x509.ParseCertificate(blk.Bytes)
if err == nil {
    if _, ok := cert.PublicKey.(*ecdsa.PublicKey); !ok {
        return errors.New("certificate must be ECDSA-signed for fabric sanitization")
    }
}

Try / catch

out, err := crypto.SanitizeX509Cert(certPEM)
if err != nil && strings.Contains(err.Error(), "failed unmarshaling ECDSA signature") {
    // likely non-ECDSA cert; re-issue from CA with ECDSA
}

Prevention

When it happens

Trigger: Sanitizing a certificate whose signature is not ECDSA (e.g. RSA or Ed25519 certs), or whose signature bytes are corrupted/non-standard ASN.1.

Common situations: Fabric deployment using RSA certificates where the sanitizer assumes ECDSA; certificates issued by a non-conformant CA encoding signatures differently; corrupted cert payloads in gossip or identity messages.

Related errors


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