lax509

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 14, 2025 License: Apache-2.0 Imports: 11 Imported by: 0

README

lax509

This is a minimalist fork of crypto/x509.

[!WARNING] This library is not safe to use for applications outside of this repository.

[!WARNING] This fork will not be kept in synced with upstream. It will not be updated, unless required by a security vulnerability or a critical functionality issue.

To be or not to be

As specified by RFC6962 §3.1, CT logs MUST validate submitted chains to ensure that they link up to roots they accept. crypto/x509 implements this, and also runs additional common chain validation checks. However, these additional checks:

  • Do not allow chains to contain precertificate or preissuer intermediates.
  • Would block non-compliant certificates signed by production roots from being accepted, thereby preventing them from becoming discoverable.

The slings and arrows of outrageous fortune

The fork in this directory implements chain verification requirements from RFC6962 §3.1 and disables some additional checks, such as:

  • Handling of critical extensions: CT precertificates are identified by a critical extension defined in RFC6962 §3.1, which the crypto/x509 library, by design, does not process. A non-processed critical extension would fail certificate validation. This check is disabled to allow precertificate in the logs.
  • Cert expiry: notBefore and notAfter certificate checks are handled at submission time, based on the notBeforeLimit and notAfterLimit log parameters. Therefore, not only we do not need to check them again at certificate verification time, but we specifically want to accept all certificates within the [notBeforeLimit, notAfterLimit] range, even if they have expired.
  • CA name restrictions: an intermediate or root certificate can restrict the domains it may issue certificates for. This check is disabled to make such issuances discoverable.
  • Chain length: this check is confused by chains including preissuer intermediates.
  • Extended Key Usage: this would ensure that all the EKUs of a child certificate are also held by its parents. However, the EKU identifying preissuer intermediate certs in RFC6962 §3.1 does not need to be set in the issuing certificate, so this check would not pass for chains using a preissuer intermediate. Also, see https://github.com/golang/go/issues/24590.
  • Policy graph validation: chains that violate policy validation should be discoverable through CT logs.

To take arms against a sea of troubles

These additional constraints can be disabled:

  • Negative serial numbers are not allowed starting from go1.23. To allow them, set x509negativeserial=1 in the GODEBUG environment variable, either in your terminal at build time or with //go:debug x509negativeserial=1 at the top of your main file.
  • SHA-1 based signing algorithms are not allowed by default. Set AcceptSHA1 to true in the lax509 VerifyOptions to allow them, which can be done by setting the accept_sha1_signing_algorithms TesseraCT flag. This is a temporary solution to accept chains issued by Chrome's Merge Delay Monitor Root until it stops using SHA-1 based signatures.

No more; and by a sleep to say we end

We've identified that the following root certificates and chains do not validate with this library, while they would have validated with the old CTFE library used by RFC6962 logs.

If you find any other such chain, get in touch!

Roots
Chains

Chains that use SHA-1 based signing algorithms such as sha1WithRSAEncryption are not accepted by default. See To take arms against a sea of troubles to allow these chains in.

This signing algorithm has been rejected by crypto/x509 since 2020, major CT-enforcing user agents (Chrome, Apple, Firefox, Android, Microsoft) and CCADB have been working on deprecating SHA1, for more than 10 years.

It should not be used. However, it is known to be used by chains issued by these roots:

Given the importance of Chrome's Merge Delay Monitor Root for the CT ecosystem, we recommend configuring TesseraCT to allow SHA-1 based signature algorithms for the time being.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Verify

func Verify(c *x509.Certificate, opts VerifyOptions) (chains [][]*x509.Certificate, err error)

Verify attempts to verify c by building one or more chains from c to a certificate in opts.Roots, using certificates in opts.Intermediates if needed. If successful, it returns one or more chains where the first element of the chain is c and the last element is from opts.Roots.

If opts.Roots is nil, the platform verifier might be used, and verification details might differ from what is described below. If system roots are unavailable the returned error will be of type SystemRootsError.

Name constraints in the intermediates will be applied to all names claimed in the chain, not just opts.DNSName. Thus it is invalid for a leaf to claim example.com if an intermediate doesn't permit it, even if example.com is not the name being validated. Note that DirectoryName constraints are not supported.

Name constraint validation follows the rules from RFC 5280, with the addition that DNS name constraints may use the leading period format defined for emails and URIs. When a constraint has a leading period it indicates that at least one additional label must be prepended to the constrained name to be considered valid.

Extended Key Usage values are enforced nested down a chain, so an intermediate or root that enumerates EKUs prevents a leaf from asserting an EKU not in that list. (While this is not specified, it is common practice in order to limit the types of certificates a CA can issue.)

Certificates that use SHA1WithRSA and ECDSAWithSHA1 signatures are not supported, and will not be used to build chains.

Certificates other than c in the returned chains should not be modified.

WARNING: this function doesn't do any revocation checking.

Types

type CertPool

type CertPool struct {
	// contains filtered or unexported fields
}

CertPool is a set of certificates.

func NewCertPool

func NewCertPool() *CertPool

NewCertPool returns a new, empty CertPool.

func (*CertPool) AddCert

func (s *CertPool) AddCert(cert *x509.Certificate)

AddCert adds a certificate to a pool.

func (*CertPool) AddCertWithConstraint

func (s *CertPool) AddCertWithConstraint(cert *x509.Certificate, constraint func([]*x509.Certificate) error)

AddCertWithConstraint adds a certificate to the pool with the additional constraint. When Certificate.Verify builds a chain which is rooted by cert, it will additionally pass the whole chain to constraint to determine its validity. If constraint returns a non-nil error, the chain will be discarded. constraint may be called concurrently from multiple goroutines.

func (*CertPool) AppendCertsFromPEM

func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool)

AppendCertsFromPEM attempts to parse a series of PEM encoded certificates. It appends any certificates found to s and reports whether any certificates were successfully parsed.

On many Linux systems, /etc/ssl/cert.pem will contain the system wide set of root CAs in a format suitable for this function.

func (*CertPool) Clone

func (s *CertPool) Clone() *CertPool

Clone returns a copy of s.

func (*CertPool) Equal

func (s *CertPool) Equal(other *CertPool) bool

Equal reports whether s and other are equal.

func (*CertPool) Subjects

func (s *CertPool) Subjects() [][]byte

Subjects returns a list of the DER-encoded subjects of all of the certificates in the pool. Deprecated in the original package: https://pkg.go.dev/crypto/x509#CertPool.Subjects. Undeprecated here since it's still used by some tests.

type UnknownAuthorityError

type UnknownAuthorityError struct {
	Cert *x509.Certificate
	// contains filtered or unexported fields
}

UnknownAuthorityError results when the certificate issuer is unknown

func (UnknownAuthorityError) Error

func (e UnknownAuthorityError) Error() string

type VerifyOptions

type VerifyOptions struct {
	// Intermediates is an optional pool of certificates that are not trust
	// anchors, but can be used to form a chain from the leaf certificate to a
	// root certificate.
	Intermediates *CertPool
	// Roots is the set of trusted root certificates the leaf certificate needs
	// to chain up to. If nil, the system roots or the platform verifier are used.
	Roots *CertPool
	// KeyUsages specifies which Extended Key Usage values are acceptable. A
	// chain is accepted if it allows any of the listed values. An empty list
	// means ExtKeyUsageServerAuth. To accept any key usage, include ExtKeyUsageAny.
	KeyUsages []x509.ExtKeyUsage
	// AcceptSHA1 specifies whether cert chains using SHA-1 based signing algorithms
	// are allowed.
	// CAUTION: This is a temporary solution and it will eventually be removed.
	// DO NOT depend on it.
	AcceptSHA1 bool
}

VerifyOptions contains parameters for Certificate.Verify.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL