Repository navigation
Distrusted CA keys and opt-in CRL revocation (CRYPTO-REVIEW-004 P0 + P1b) - #28
Open
khalid-offset wants to merge 2 commits into
Open
khalid-offset wants to merge 2 commits into
khalid-offset wants to merge 2 commits into
Conversation
eMudhra's eight P-384 intermediate CAs (Oct 2026) have private keys below 256. v0.4.0 rejected chains through them only because Go 1.27.3 drops them inside crypto/x509, and the report said just "no valid chains built". - refdata: hand-curated distrust list (distrust.json), matched by SPKI and certificate SHA-256; first incident is eMudhra (8 keys, 16 certificates, verified against the published certificates; a test re-derives each key from its private value). - pki: Paths builds signature-valid paths without policy filtering; Validate takes the list, keeps the path through a listed key and names it (StoreResult.Listed) instead of losing it. - eval: CERT.DISTRUSTED-KEY (critical) on served chains and on host, file and imported certificates; a finding, not a gate: every other rule still runs. eval/13. - Root stores and CT log list refreshed from CCADB/Google (2026-10-23): Mozilla removed emSign ECC Root CA - G3, ECC C3 and Root CA - C1.
…-004 P1b) With --revocation (tls scan, serve), the revocation stage fetches the CRL each certificate on the served path names and checks it against its own issuer, up to the root (stopping at a served copy of a known anchor). Revocation is a status beside trust, never a gate. - pki.JudgeCRL (pure): issuer name, issuer signature, dates, delta, indirect and IDP scope (user/CA-only, partial reasons, partitions). - internal/revocation: guarded fetcher. http only, no credentials, 16 MiB, timeouts, re-checked redirects, no env proxy; loopback, link-local, private and metadata addresses refused unless --revocation-private; cache until nextUpdate. - Report.CRLLookups and CertResult.CRL; rules REV.REVOKED, REV.CRL-BAD-SIGNATURE, REV.CRL-STALE, REV.UNKNOWN (not-checked when lookups are off). A current CRL for the leaf makes revocation known. - OpenSSL-made fixtures (testing/pki/make-crl.sh), FuzzJudgeCRL in CI. - UI: CRL tile and table, Settings and Help; fixed contradictory pass texts (CERT.PARTIAL-TRUST, OCSP.REVOKED) and the hygiene note. - OCSP responders are still never contacted.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Response to the eMudhra CA key compromise (Oct 2026). Eight eMudhra P-384 intermediate CAs had private keys below 256. Full analysis and plan:
docs/product/CRYPTO-REVIEW-004-emudhra-weak-ca-keys.md.The rule throughout: CipherHorizon evaluates, it doesn't gate. A distrusted key or a revoked certificate is reported as a finding on a fully evaluated chain. Every other check still runs.
P0: distrusted keys, on any Go version
internal/refdata/distrust.jsonis matched by key hash (SPKI SHA-256) and by certificate SHA-256. Its first entry is the 8 eMudhra keys and their 16 certificates (emSign originals and Sectigo cross-signs). These were checked against the published certificates, and a test re-derives each key from its private value.pki.Pathsbuilds chains whose signatures check out, with no policy filtering. Go 1.27.3+ silently drops chains through these keys, and older Go versions accept them. We now report the chain, the listed certificate and the reason either way, instead of "x509: no valid chains built".CERT.DISTRUSTED-KEY(critical). It fires on served chains and on certificates found on hosts, in files and in imports. Evaluation version:eval/13.P1b: opt-in CRL revocation, up the served chain
--revocationturns it on fortls scanandserve. When off, the new checks read "not checked", never "passed".pki.JudgeCRLchecks the issuer name and signature, the dates, delta and indirect CRLs, and issuing-distribution-point scope (user-only, CA-only, partial reasons, partitions).internal/revocation).--revocation-privateis set.REV.REVOKED(critical),REV.CRL-BAD-SIGNATURE(high),REV.CRL-STALE(medium),REV.UNKNOWN(low).CERT.PARTIAL-TRUSTandOCSP.REVOKEDpass texts, and the score's "not measured" note.Testing
pki(OpenSSL-made CRL fixtures fromtesting/pki/make-crl.sh),revocation(address policy, cache, caps, redirects),tlsprobe(chain walk with a fake fetcher), andeval(every new rule, plus "not checked" when lookups are off).CERT.DISTRUSTED-KEYand keeps the full path, on both Go 1.27.0 and 1.27.3.FuzzJudgeCRLtarget is added to the CI fuzz job.go test ./...andgolangci-lintboth pass.--revocation):REV.REVOKED(G3B, cACompromise, on emSign Root TLS CA - G3's CRL) andCERT.DISTRUSTED-KEY.Not in this PR
P1 (weak-key tests: tiny EC private keys, ROCA, batch GCD), P2 (which hosts in the estate are still exposed), P3 (scheduled CCADB/OneCRL refresh). No release cut.