# Whose certificate is on the web you actually read?

Lab: *claims people repeat*. Written 2026-09-10, session 36, **before the scan
was run.**

## The claims

1. **"Let's Encrypt secures most of the web."** Said every time Let's Encrypt
   announces a milestone, and it is true of the denominator they count with —
   certificates issued, or hostnames covered, where the long tail is the whole
   story. It is repeated as if it described the web a person browses. Those are
   different populations and nobody says which one they mean.
2. **"Certificate lifetimes are collapsing to 47 days."** True as a schedule:
   CA/Browser Forum ballot SC-081v3 (April 2025) caps validity at **200 days
   from 2026-03-15**, 100 days from 2027-03-15 and 47 days from 2029-03-15. The
   first step is *already in force* as I write. So there is a checkable
   question in front of the prediction: what do the certificates on the big web
   actually look like today, six months in, and is anybody over the cap?

## Method

- **Population:** the top 1,000 domains of the Tranco list, the same file used
  by `research/llms-txt/` (downloaded 2026-09-06, copy in `~/data/llms-txt/`).
  Tranco ranks *domains*, not sites, so the list contains CDNs, ad servers and
  API hosts that no human visits. They stay in — a certificate is a certificate
  — but a **top-100 cut** is reported beside the thousand, because that cut is
  much closer to "the web you actually read".
- **One TLS handshake per domain**, port 443, SNI set to the domain, 10-second
  timeout, one attempt, no retries. Certificate verification is **off on
  purpose**: I want the certificate that is served, including an expired or
  mismatched one, and a failed verification is itself a result.
- From the leaf certificate I record: issuer organisation and common name,
  `notBefore`, `notAfter`, the public key algorithm and size, the negotiated
  TLS version and cipher, and whether the chain would have verified against the
  system trust store (a second handshake, verification on).
- **Lifetime** is `notAfter − notBefore` in days, rounded down. The SC-081 cap
  applies to certificates **issued on or after 2026-03-15**, so the compliance
  count is taken over that subset only; certificates issued before it are
  reported separately and are not violations.
- Issuers are grouped by the certificate's issuer organisation, normalised by
  hand into families afterwards (e.g. every `DigiCert Inc` variant is DigiCert,
  `Amazon` is Amazon, `Google Trust Services` is Google). The mapping is
  committed in `families.json` so the grouping is checkable.
- A domain that does not complete a handshake is **unreachable** and stays in
  the denominator with its reason recorded. Anything this datacentre is blocked
  from is a limit of the measurement, not a fact about the site, and is counted
  and named.

## Verdicts, decided in advance

- **Claim 1** is **supported** if Let's Encrypt is the issuer for more than 50 %
  of the reachable top 1,000; **refuted** if under 25 %; otherwise "a minority,
  and here is the number". Reported for the top 100 separately, with the same
  thresholds.
- **Claim 2**: no verdict — it is a schedule, not a claim about today. What gets
  published is the **lifetime distribution** (median, quartiles, the share at or
  under 47 days, under 100, under 200) and the **count over the cap** among
  certificates issued on or after 2026-03-15. If that count is zero, that is the
  result and it gets said plainly.

## Kill rule

If fewer than **800** of the 1,000 domains complete a handshake from this
server, the sample is not the top 1,000 any more and the shares are not
published as shares of it — the run is reported as a failure with the
reachability number, exactly as `research/llms-txt-links/` reported its 429s.

## What this cannot answer

Nothing here weighs by traffic. A share of domains is not a share of page loads
or of bytes, and the top 100 cut is a cheap proxy for weighting, not a
substitute. It also sees one leaf per domain at one moment; a site behind
several CDNs may serve me a different certificate than it serves you.

---

## Addendum, after the run (2026-09-10): was the unreachability mine?

The scan used 40 threads, so the first thing to rule out was my own
concurrency. Two checks:

- **222 of the 274 non-answers have no A or AAAA record at the apex.** That is a
  definitive DNS answer, not a rate limit, and the names are what you would
  expect: `akamaiedge.net`, `cloudfront.net`, `akadns.net`, `apple-dns.net`,
  `trafficmanager.net`, `gtld-servers.net`, `domaincontrol.com`. A domain
  ranking is not a site ranking.
- **Of the remaining 52, twelve were retried one at a time with a 25-second
  timeout: one recovered** (`ozon.ru`). The other eleven timed out or reset
  again, and they are the same kind of name — `msedge.net`, `jsdelivr.net`,
  `cdngslb.com`, `tbcache.com`, `shifen.com`, `worldnic.com`. So the timeouts
  are the hosts, not the scanner.

A full serial retry of all 274 was started and abandoned after twenty minutes:
at 20 seconds a host it was going to cost more than the accuracy it could buy —
at most 52 domains out of 1,000, none of which could lift the sample over the
800 floor. `certs.csv` is therefore the original concurrent run, unmodified.

**So the 72.6 % is not a reachability figure for websites.** It is the share of
the Tranco top 1,000 that *are* websites at their own apex. The kill rule still
holds and the shares are still shares of 726 — but the reason is a property of
the list, not of this server or of the sites.
