grpc/grpc-go · error

authority key identifier extension missing

Error message

authority key identifier extension missing

What it means

Returned by parseCRLExtensions after iterating all extensions of the CRL: certList.authorityKeyID is still empty. RFC 5280 5.2.1 mandates the AuthorityKeyIdentifier extension in conforming CRLs; grpc-go relies on it to correlate the CRL to the issuing certificate's SubjectKeyId during signature verification. Without it, the CRL cannot be validated and is rejected.

Solutions

  1. Regenerate the CRL with the AuthorityKeyIdentifier extension included (default for conformant CA tooling).
  2. If using OpenSSL, ensure the CA cert has a subjectKeyIdentifier so the generated CRL includes AKID.
  3. Switch CA software or request the operator include the AKID extension on the CRL.
Defensive patterns

Strategy: validation

Validate before calling

// Require the AuthorityKeyIdentifier extension on any CRL we install.
func crlHasAKID(crlDER []byte) (bool, error) {
    l, err := x509.ParseRevocationList(crlDER)
    if err != nil { return false, err }
    for _, ext := range l.Extensions {
        if ext.Id.Equal(oidAuthorityKeyIdentifier) { return true, nil }
    }
    return false, nil
}

Try / catch

On parse failure citing missing AKID, retain the previous CRL and alert. Coordinate with the CA to reissue a conformant CRL.

Prevention

When it happens

Trigger: A CRL was parsed successfully but contained no AuthorityKeyIdentifier extension (oid 2.5.29.35). Triggered when loading a CRL via the advancedtls CRL provider.

Common situations: Non-conformant CA that omits AKID from CRLs (older OpenSSL versions, lightweight CAs, test CAs). CRL generated by minimal tooling that skips optional-but-expected extensions. Stripped-down CRL used in a constrained environment.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/c1ad59e448ac4dfb. Report an issue: GitHub.

Appendix: source

Thrown at security/advancedtls/crl.go:360

			}

			if dp.OnlyContainsUserCerts || dp.OnlyContainsCACerts || dp.OnlyContainsAttributeCerts {
				return nil, errors.New("CRL only contains some certificate types")
			}
			if dp.IndirectCRL {
				return nil, errors.New("indirect CRLs unsupported")
			}
			if dp.OnlySomeReasons.BitLength != 0 {
				return nil, errors.New("onlySomeReasons unsupported")
			}

		case ext.Critical:
			return nil, fmt.Errorf("unsupported critical extension: %v", ext.Id)
		}
	}

	if len(certList.authorityKeyID) == 0 {
		return nil, errors.New("authority key identifier extension missing")
	}
	return certList, nil
}

func verifyCRL(crl *CRL, chain []*x509.Certificate) error {
	// RFC5280, 6.3.3 (f) Obtain and validate the certification path for the issuer of the complete CRL
	// We intentionally limit our CRLs to be signed with the same certificate path as the certificate
	// so we can use the chain from the connection.

	for _, c := range chain {
		// Use the key where the subject and KIDs match.
		// This departs from RFC4158, 3.5.12 which states that KIDs
		// cannot eliminate certificates, but RFC5280, 5.2.1 states that
		// "Conforming CRL issuers MUST use the key identifier method, and MUST
		// include this extension in all CRLs issued."
		// So, this is much simpler than RFC4158 and should be compatible.
		if bytes.Equal(c.SubjectKeyId, crl.authorityKeyID) && bytes.Equal(c.RawSubject, crl.rawIssuer) {
			// RFC5280, 6.3.3 (f) Key usage and cRLSign bit.

View on GitHub (pinned to 0c51461d27)