hyperledger/fabric · error
failed unmarshaling certificate
Error message
failed unmarshaling certificate
What it means
When a certificate has a high-S ECDSA signature, the sanitizer re-encodes the whole certificate with the normalized low-S signature. It does this by ASN.1-unmarshaling cert.Raw into a local certificate struct; if that fails, 'failed unmarshaling certificate' is wrapped and returned.
Source
Thrown at common/crypto/sanitize.go:70
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")
}
newSig, err := utils.MarshalECDSASignature(r, s)
if err != nil {
return nil, errors.Wrapf(err, "failed marshaling ECDSA signature")
}
newCert.SignatureValue = asn1.BitString{Bytes: newSig, BitLength: len(newSig) * 8}
newCert.Raw = nil
newRaw, err := asn1.Marshal(newCert)
if err != nil {
return nil, errors.Wrapf(err, "failed marshaling new certificate")
}
finalPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: newRaw})
return finalPEM, nil
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Re-issue the certificate so the CA signs it with low-S directly (fix CA's RFC6979/low-S configuration)
- Compare the failing cert's DER with openssl asn1parse to find the non-standard encoding
- Convert the cert to canonical DER before use (re-encode via Go's x509 or openssl)
- Upgrade the fabric version, as asn1 handling of exotic encodings has improved over releases
Defensive patterns
Strategy: try-catch
Validate before calling
func hasHighS(cert *x509.Certificate) (bool, error) {
r, s, err := utils.UnmarshalECDSASignature(cert.Signature)
if err != nil { return false, err }
half := new(big.Int).Rsh(cert.PublicKey.(*ecdsa.PublicKey).Curve.Params().N, 1)
return s.Cmp(half) == 1, nil
} Try / catch
out, err := crypto.SanitizeX509Cert(certPEM)
if err != nil && strings.Contains(err.Error(), "failed unmarshaling certificate") {
// cert is high-S and non-canonical DER; re-issue from CA
} Prevention
- Configure CAs to emit low-S signatures (RFC6979 deterministic k) so sanitization is a no-op
- Check unusual certs with openssl asn1parse before deploying
- Prefer recent fabric releases with robust ASN.1 handling
When it happens
Trigger: A high-S certificate whose raw DER cannot be re-parsed by encoding/asn1 into the sanitizer's certificate struct — e.g. non-standard extensions/encodings that break strict ASN.1 parsing.
Common situations: Certificates from CAs emitting non-canonical DER (e.g. weird OPTIONAL fields, zero-length encodings); intermediate tooling re-encoding certificates non-strictly; very old/uncommon CA software.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- failed parsing certificate %s
- failed unmarshaling ECDSA signature on identity: %s
- failed marshaling ECDSA signature
- unmarshalling of the certificate failed
- parseCertificate failed
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/d9a588a45c4678a9.
Report an issue: GitHub.