grpc/grpc-go · error

extractCRLIssuer: invalid ASN.1 encoding

Error message

extractCRLIssuer: invalid ASN.1 encoding

What it means

Returned by extractCRLIssuer (crl.go:417) when it cannot navigate the expected ASN.1 structure of the CRL bytes (outer SEQUENCE, inner SEQUENCE, skip version INTEGER, skip signatureAlg SEQUENCE, then read the issuer Name element). It uses cryptobyte ReadASN1/Skip calls in sequence; if any returns false the bytes are malformed or not a CRL. The function needs the raw issuer DN which pkix.CertificateList cannot reliably re-marshal.

Source

Thrown at security/advancedtls/crl.go:417

	return crlBytes
}

// extractCRLIssuer extracts the raw ASN.1 encoding of the CRL issuer. Due to the design of
// pkix.CertificateList and pkix.RDNSequence, it is not possible to reliably marshal the
// parsed Issuer to its original raw encoding.
func extractCRLIssuer(crlBytes []byte) ([]byte, error) {
	if bytes.HasPrefix(crlBytes, crlPemPrefix) {
		crlBytes = crlPemToDer(crlBytes)
	}
	der := cryptobyte.String(crlBytes)
	var issuer cryptobyte.String
	// This doubled der.ReadASN1 is intentional, it modifies the input buffer
	if !der.ReadASN1(&der, cbasn1.SEQUENCE) ||
		!der.ReadASN1(&der, cbasn1.SEQUENCE) ||
		!der.SkipOptionalASN1(cbasn1.INTEGER) ||
		!der.SkipASN1(cbasn1.SEQUENCE) ||
		!der.ReadASN1Element(&issuer, cbasn1.SEQUENCE) {
		return nil, errors.New("extractCRLIssuer: invalid ASN.1 encoding")
	}
	return issuer, nil
}

// parseRevocationList comes largely from here
// x509.go:
// https://github.com/golang/go/blob/e2f413402527505144beea443078649380e0c545/src/crypto/x509/x509.go#L1669-L1690
// We must first convert PEM to DER to be able to use the new
// x509.ParseRevocationList instead of the deprecated x509.ParseCRL
func parseRevocationList(crlBytes []byte) (*x509.RevocationList, error) {
	if bytes.HasPrefix(crlBytes, crlPemPrefix) {
		crlBytes = crlPemToDer(crlBytes)
	}
	crl, err := x509.ParseRevocationList(crlBytes)
	if err != nil {
		return nil, err
	}
	return crl, nil

View on GitHub (pinned to 03255a9237)

Solutions

  1. Re-download the CRL and verify it parses independently: `openssl crl -in crl.der -inform DER -noout -text` (or `-inform PEM`).
  2. Ensure you pass raw DER or a proper '-----BEGIN X509 CRL-----' PEM block; extractCRLIssuer only auto-strips the X509 CRL PEM prefix.
  3. Check the byte length and magic bytes against a known-good CRL; log the first bytes to detect HTML/text payloads.

Example fix

// before: feeding a truncated/garbage byte slice -> invalid ASN.1 encoding
// after: validate with x509 first, then pass to advancedtls
//   if _, err := x509.ParseRevocationList(rawDER); err != nil {
//       return fmt.Errorf("not a valid CRL, re-download: %w", err)
//   }
Defensive patterns

Strategy: validation

Validate before calling

import "crypto/x509"

func isValidCRLDER(b []byte) error {
    if _, err := x509.ParseRevocationList(b); err != nil {
        return fmt.Errorf("bytes are not a valid CRL: %w", err)
    }
    return nil
}

// call before extractCRLIssuer / advancedtls CRL ingestion

Prevention

When it happens

Trigger: Passing corrupt, truncated, or non-CRL bytes (e.g. a certificate, a plain text error page, or a partial download) to a code path that calls extractCRLIssuer to obtain the CRL issuer. Also triggered by a PEM block whose decoded payload is not a valid CertificateList.

Common situations: A CRL download over HTTP that returned an HTML error page or was truncated; passing a DER certificate instead of a CRL; encoding/decoding mismatch (double base64, wrong PEM type); network proxy mangling the payload.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/892656517f6b6fd5. Report an issue: GitHub.