{"id":51578766,"url":"https://github.com/systemslibrarian/crypto-lab-pki-chain","last_synced_at":"2026-07-11T03:32:25.595Z","repository":{"id":366206084,"uuid":"1208919932","full_name":"systemslibrarian/crypto-lab-pki-chain","owner":"systemslibrarian","description":"Browser-based PKI demo — X.509 certificate chains, trust store validation, CA compromise cascades, Certificate Transparency with Merkle inclusion proofs, and post-quantum migration to ML-DSA.","archived":false,"fork":false,"pushed_at":"2026-06-28T02:04:58.000Z","size":93,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-28T02:18:50.331Z","etag":null,"topics":["browser-demo","certificate-chain","certificate-transparency","crypto-lab","cryptography","ecdsa","merkle-tree","p-256","pki","webcrypto","x509"],"latest_commit_sha":null,"homepage":"https://systemslibrarian.github.io/crypto-lab-pki-chain/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/systemslibrarian.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-12T23:03:40.000Z","updated_at":"2026-06-28T02:05:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/systemslibrarian/crypto-lab-pki-chain","commit_stats":null,"previous_names":["systemslibrarian/crypto-lab-pki-chain"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/systemslibrarian/crypto-lab-pki-chain","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-pki-chain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-pki-chain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-pki-chain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-pki-chain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/systemslibrarian","download_url":"https://codeload.github.com/systemslibrarian/crypto-lab-pki-chain/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-pki-chain/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35350133,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-11T02:00:05.354Z","response_time":104,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser-demo","certificate-chain","certificate-transparency","crypto-lab","cryptography","ecdsa","merkle-tree","p-256","pki","webcrypto","x509"],"created_at":"2026-07-11T03:32:25.074Z","updated_at":"2026-07-11T03:32:25.584Z","avatar_url":"https://github.com/systemslibrarian.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# crypto-lab-pki-chain\n\n## What It Is\n\nThis browser-native lab demonstrates Public Key Infrastructure (PKI) certificate chain trust using real WebCrypto ECDSA P-256 signatures. A Root CA signs an Intermediate CA certificate, which in turn signs a Leaf certificate; every signature is verified in-browser using `crypto.subtle`. The demo also covers Certificate Transparency (CT) — an append-only Merkle log where certificates are submitted and inclusion proofs are generated and verified using SHA-256. The security model is hierarchical trust: all authenticity flows from one trusted root anchor, and any forged or revoked link invalidates all descendants.\n\n## When to Use It\n\n- **Learning TLS certificate chain validation** — the demo shows how browsers verify each link before trusting a server's identity.\n- **Auditing a custom certificate validator** — the tamper and revocation controls expose exactly which checks a validator must pass.\n- **Understanding CT monitoring** — useful when building a certificate log monitor or implementing CT client-side verification.\n- **Studying CA compromise blast radius** — the intermediate and root compromise scenarios show which certificates become invalid when a CA key is stolen.\n- When you need peer-to-peer trust without a central authority, prefer web-of-trust or decentralized PKI (e.g., DANE); hierarchical PKI is the wrong model for that.\n- Do NOT treat this as a production PKI or certificate validator — it is a browser teaching demo, not a hardened CA or TLS stack.\n\n## Live Demo\n\n**[systemslibrarian.github.io/crypto-lab-pki-chain](https://systemslibrarian.github.io/crypto-lab-pki-chain/)**\n\nThe demo provides six interactive exhibits. The **Tamper / Repair** buttons toggle a single signed field on any certificate so you can flip a link between PASS and FAIL and watch WebCrypto signature verification react in real time; a **Reset lab** button restores every scenario to its defaults. Toggle **CRL** and **OCSP** checkboxes to simulate leaf revocation, switch trust store contexts (Browser / OS / Application), mark a CA as compromised to see subtree distrust, submit certificates to the simulated CT log to generate SCTs and verify **RFC 6962 Merkle inclusion and consistency proofs**, and compare classical P-256, ML-DSA, and hybrid post-quantum signature footprints drawn to scale from the live chain.\n\nThe Merkle log is implemented to RFC 6962 exactly — leaves prefixed with `0x00`, interior nodes with `0x01`, and trees split at the largest power of two with no lone-node duplication — so inclusion and consistency proofs are the same compact `O(log n)` artifacts a real CT log produces, not a recomputation over the whole log.\n\n## What Can Go Wrong\n\n- **Trust anchor mismatch** — different operating systems and browsers ship different root CA bundles; a certificate trusted by Chrome may be rejected by an embedded application that pins its own trust store.\n- **CA compromise blast radius** — if an Intermediate CA private key is stolen, every leaf certificate it ever signed is retroactively untrustworthy, even if the leaf itself was issued correctly.\n- **CRL staleness** — certificate revocation lists have a validity window; a revoked certificate may still be accepted if the relying party caches an outdated CRL and the responder is unavailable.\n- **CT log split-view attack** — without verifying consistency proofs between two tree states, a misbehaving log can show different views to different monitors, hiding a fraudulent certificate from detection.\n- **Signature algorithm confusion** — ECDSA P-256 signatures are tied to the `SHA-256` hash; using a different hash parameter at verification time silently fails rather than throwing in some WebCrypto implementations.\n\n## Real-World Usage\n\n- **Let's Encrypt** — issues certificates using ECDSA P-256 chains and submits every certificate to at least two CT logs as required by the CA/Browser Forum Baseline Requirements.\n- **Google Chrome** — has enforced CT inclusion for all publicly trusted TLS certificates since April 2018; connections to sites with certificates not logged in a trusted CT log are rejected.\n- **Apple platforms** — Safari and iOS enforce CT policy requiring certificates to include SCTs from at least two approved logs before the TLS handshake is accepted.\n- **ACME protocol (RFC 8555)** — the automated certificate issuance protocol used by Let's Encrypt and other CAs encodes the Root → Intermediate → Leaf chain model directly in its order and finalization flow.\n- **Mozilla NSS / Firefox** — maintains an independent root CA trust store (distinct from the OS store), demonstrating exactly the trust-store divergence shown in Exhibit 3.\n\n## How to Run Locally\n\n```bash\ngit clone https://github.com/systemslibrarian/crypto-lab-pki-chain\ncd crypto-lab-pki-chain\nnpm install\nnpm run dev\n```\n\n## Related Demos\n- [crypto-lab-merkle-vault](https://systemslibrarian.github.io/crypto-lab-merkle-vault/) — SHA-256 Merkle trees and inclusion proofs, the data structure behind Certificate Transparency.\n- [crypto-lab-web-of-trust](https://systemslibrarian.github.io/crypto-lab-web-of-trust/) — the decentralized PGP trust-graph alternative to hierarchical CA trust.\n- [crypto-lab-dilithium-seal](https://systemslibrarian.github.io/crypto-lab-dilithium-seal/) — ML-DSA signatures, the post-quantum option compared against P-256 in this chain.\n- [crypto-lab-pq-rotation](https://systemslibrarian.github.io/crypto-lab-pq-rotation/) — hybrid X.509 certificates and the operational PKI migration to post-quantum signatures.\n- [crypto-lab-kerberos](https://systemslibrarian.github.io/crypto-lab-kerberos/) — an alternative authentication model based on a trusted ticket-granting authority rather than certificate chains.\n\n## Tests\n\nA cryptography lab should prove its own crypto, so the math is covered by an executable test suite (`src/pki.test.ts`, `src/ct.test.ts`) that runs in CI before every deploy:\n\n- **Chain validation** — a well-formed chain passes; tampering any signed field breaks that link's signature; an unknown trust anchor is rejected.\n- **Revocation** — CRL and OCSP revocation each fail the leaf.\n- **CA compromise** — root compromise distrusts the whole subtree; intermediate compromise spares the root.\n- **RFC 6962 Merkle proofs** — inclusion and consistency proofs verify for every leaf and every `old \u003c new` size up to eight, stay `O(log n)` in size, and are rejected when any root or proof node is corrupted.\n\n---\n\n*One of 120+ browser demos in the [Crypto Lab](https://crypto-lab.systemslibrarian.dev/) suite.*\n\n*\"So whether you eat or drink or whatever you do, do it all for the glory of God.\" — 1 Corinthians 10:31*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsystemslibrarian%2Fcrypto-lab-pki-chain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsystemslibrarian%2Fcrypto-lab-pki-chain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsystemslibrarian%2Fcrypto-lab-pki-chain/lists"}