{"id":50961480,"url":"https://github.com/robstradling/mtc-demo","last_synced_at":"2026-06-18T14:33:14.311Z","repository":{"id":361693884,"uuid":"1219245245","full_name":"robstradling/mtc-demo","owner":"robstradling","description":"AI-generated Merkle Tree Certificates Demo","archived":false,"fork":false,"pushed_at":"2026-05-31T20:23:55.000Z","size":33,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-31T22:13:34.993Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","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/robstradling.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-23T17:19:50.000Z","updated_at":"2026-05-31T20:23:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/robstradling/mtc-demo","commit_stats":null,"previous_names":["robstradling/mtc-demo"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/robstradling/mtc-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robstradling%2Fmtc-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robstradling%2Fmtc-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robstradling%2Fmtc-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robstradling%2Fmtc-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robstradling","download_url":"https://codeload.github.com/robstradling/mtc-demo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robstradling%2Fmtc-demo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34495378,"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-06-18T02:00:06.871Z","response_time":128,"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":[],"created_at":"2026-06-18T14:33:13.543Z","updated_at":"2026-06-18T14:33:14.297Z","avatar_url":"https://github.com/robstradling.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mtc-demo\n\nA Go implementation of **Merkle Tree Certificates** as specified in\n[draft-ietf-plants-merkle-tree-certs-04](https://www.ietf.org/archive/id/draft-ietf-plants-merkle-tree-certs-04.txt).\n\nGenerated by Claude Opus 4.6 from [prompts](#prompts) listed further down this document.\n\nMerkle Tree Certificates are a new form of X.509 certificate that integrates\npublic logging with certificate issuance. A CA maintains an append-only\nissuance log, signs views of the log, and constructs certificates from\ninclusion proofs into the log. This reduces overhead from post-quantum\nsignature algorithms and shorter-lived certificates while preserving\nCertificate Transparency–style security properties.\n\n## Installation\n\n```\ngo install mtc/cmd/mtc-demo@latest\n```\n\nOr build from source:\n\n```\ngit clone https://github.com/robstradling/mtc-demo\ncd mtc-demo\ngo build ./cmd/mtc-demo/\n```\n\nRequires Go 1.25+ and depends on `golang.org/x/crypto/cryptobyte` and\n`filippo.io/mldsa` (ML-DSA post-quantum signatures).\n\n## Overview\n\nThe package implements the full lifecycle described in the draft:\n\n1. **Issuance log** — the CA appends validated entries to an append-only log\n2. **Checkpoints \u0026 subtrees** — the CA signs tree snapshots\n3. **Cosignatures** — external cosigners attest to correct log operation\n4. **Certificate construction** — inclusion proofs + cosignatures form a certificate\n5. **Verification** — relying parties verify proofs against trusted cosigners or predistributed landmark subtrees\n\n```\n┌─ CA ─────────────────┐    ┌─ Authenticating Party ─┐\n│ Validate request     │    │                        │\n│ Add to issuance log  │───\u003e│ Download certificates  │\n│ Cosign checkpoint    │    │   - TBSCertificate     │\n└──────┬───────────────┘    │   - inclusion proof    │\n       │                    │   - cosignatures       │\n       ▼                    └────────────┬───────────┘\n┌─ Cosigners ──────────┐                │\n│ Verify append-only   │                ▼\n│ Sign subtrees        │    ┌─ Relying Party ────────┐\n└──────────────────────┘    │ Verify proof + sigs    │\n                            │ Check revocation       │\n┌─ Monitors ───────────┐    └────────────────────────┘\n│ Watch for misuse     │\n└──────────────────────┘\n```\n\n## CLI Tool\n\nThe `mtc-demo` CLI provides subcommands for operating all MTC ecosystem\nroles: CA, cosigner, mirror, relying party, and landmark manager.\n\nState is persisted in `./mtc-state.json` (override with `MTC_STATE` env var).\n\n### Quick Start\n\n```sh\n# Initialize a CA and issuance log\nmtc-demo ca init 32473.1 1\n\n# Generate cosigner keys\nmtc-demo cosigner keygen 32473.100 ed25519\nmtc-demo cosigner keygen 32473.200 p256\n\n# Add certificate entries\nmtc-demo ca add example.com\nmtc-demo ca add test.example.com\n\n# Cosign subtrees (check subtree ranges with 'ca checkpoint')\nmtc-demo ca checkpoint\nmtc-demo cosigner sign 32473.100 0 2\nmtc-demo cosigner sign 32473.200 0 2\n\n# Issue and verify a certificate\nmtc-demo ca issue 1\nmtc-demo verify cert cert-1.pem\n```\n\n### CA Operations\n\n```\nmtc-demo ca init \u003cca-id\u003e \u003clog-number\u003e    Initialize a new CA and issuance log\nmtc-demo ca info                         Show CA and log state\nmtc-demo ca add \u003ccommon-name\u003e            Add a TBS certificate entry to the log\nmtc-demo ca checkpoint                   Display current checkpoint and subtree hashes\nmtc-demo ca issue \u003cindex\u003e                Issue a certificate for a log entry\nmtc-demo ca prune \u003cmin-index\u003e            Prune entries below min-index\n```\n\n### Cosigner Operations\n\n```\nmtc-demo cosigner keygen \u003cid\u003e \u003calgorithm\u003e   Generate a key pair (ed25519, p256, p384)\nmtc-demo cosigner list                      List configured cosigner keys\nmtc-demo cosigner sign \u003cid\u003e \u003cstart\u003e \u003cend\u003e   Cosign a subtree\n```\n\n### Mirror Operations\n\n```\nmtc-demo mirror inclusion \u003cindex\u003e              Generate and verify an inclusion proof\nmtc-demo mirror consistency \u003cold-size\u003e \u003chex\u003e   Verify consistency with a previous checkpoint\n```\n\n### Certificate Verification\n\n```\nmtc-demo verify cert \u003ccert.pem\u003e   Verify a Merkle Tree Certificate\n```\n\n### Landmark Operations\n\n```\nmtc-demo landmark init \u003cmax-active\u003e   Initialize landmark sequence\nmtc-demo landmark allocate            Allocate a landmark at current tree size\nmtc-demo landmark info                Show landmark sequence info\nmtc-demo landmark find \u003cindex\u003e        Find which landmark covers an entry\n```\n\n### Utilities\n\n```\nmtc-demo demo                          Run a full end-to-end lifecycle demo\nmtc-demo hash leaf [data]              Compute a Merkle leaf hash\nmtc-demo hash node \u003cleft-hex\u003e \u003cright-hex\u003e   Compute an interior node hash\nmtc-demo tree [entries...]             Build a Merkle tree and show info\n```\n\n## Package Structure\n\n| File | Spec Section | Purpose |\n|------|-------------|---------|\n| `trustanchorid.go` | §5.2 | `TrustAnchorID` type (base-128 OID encoding), `LogID()`, `LandmarkID()` |\n| `hash.go` | RFC 9162 §2.1 | SHA-256 leaf and node hashing |\n| `subtree.go` | §4.1, §4.5 | Subtree validation and interval covering |\n| `tree.go` | §4.3, §4.4 | `MerkleTree` with proof generation |\n| `proof.go` | §4.3.2–§4.4.3 | Proof evaluation and verification |\n| `entry.go` | §5.3 | Log entry encoding (`MerkleTreeCertEntry`) with extensions |\n| `cosign.go` | §5.4 | Cosignature generation and verification |\n| `cert.go` | §6.1 | `MTCProof` and X.509 certificate construction |\n| `verify.go` | §7.1–§7.5 | Relying party verification |\n| `log.go` | §5 | `IssuanceLog` management |\n| `landmark.go` | §6.3 | `LandmarkSequence` for size-optimized certificates |\n| `cmd/mtc-demo/` | — | CLI tool for operating MTC ecosystem roles |\n\n## Usage\n\n### Creating an Issuance Log\n\n```go\ncaID, _ := mtc.ParseTrustAnchorID(\"32473.1\")\nlog := mtc.NewIssuanceLog(caID, 1) // CA ID + log number\n\n// The log starts with a mandatory null entry at index 0.\n// Add certificate entries:\nentry := mtc.MarshalTBSCertEntry(tbsCertLogEntryContents)\nindex := log.AddEntry(entry)\n```\n\n### Generating and Verifying Inclusion Proofs\n\n```go\n// Generate a subtree inclusion proof for entry at `index`\n// within subtree [start, end).\nproof, _ := log.SubtreeInclusionProof(index, start, end)\n\n// Compute the entry hash.\nrawEntry, _ := log.Entry(index)\nentryHash := mtc.HashEntry(rawEntry)\n\n// Verify the proof against a known subtree hash.\nsubtreeHash, _ := log.SubtreeHash(start, end)\nerr := mtc.VerifySubtreeInclusionProof(proof, index, entryHash, subtreeHash, start, end)\n```\n\n### Generating and Verifying Consistency Proofs\n\n```go\n// Prove subtree [start, end) is consistent with the full tree.\nproof, _ := log.SubtreeConsistencyProof(start, end)\n\nrootHash, _ := log.CheckpointHash()\nsubtreeHash, _ := log.SubtreeHash(start, end)\nerr := mtc.VerifySubtreeConsistencyProof(proof, start, end, log.Size(), subtreeHash, rootHash)\n```\n\nStandard RFC 9162–style proofs are also available:\n\n```go\nproof, _ := log.Tree().InclusionProof(index)\nerr := mtc.VerifyInclusionProof(proof, index, treeSize, entryHash, rootHash)\n\nproof, _ := log.Tree().ConsistencyProof(oldSize)\nerr := mtc.VerifyConsistencyProof(proof, oldSize, newSize, oldRoot, newRoot)\n```\n\n### Cosigning Subtrees\n\n```go\ncosignerID, _ := mtc.ParseTrustAnchorID(\"32473.1.1\")\n\ncosignerKey := \u0026mtc.CosignerKey{\n    CosignerID:         cosignerID,\n    SignatureAlgorithm: mtc.SignatureP256SHA256,\n    PrivateKey:         ecdsaPrivateKey, // crypto.Signer\n}\n\nlogID := caID.LogID(1) // derive log ID from CA ID + log number\nsubtreeHash, _ := log.SubtreeHash(start, end)\nsig, _ := mtc.Cosign(cosignerKey, logID, uint64(start), uint64(end), \u0026subtreeHash)\n\n// Verify:\nerr := mtc.VerifyCosignature(\n    cosignerID, \u0026ecdsaPrivateKey.PublicKey, mtc.SignatureP256SHA256,\n    logID, uint64(start), uint64(end), \u0026subtreeHash, sig,\n)\n```\n\nSupported signature algorithms:\n\n| Constant | Algorithm |\n|----------|-----------|\n| `SignatureP256SHA256` | ECDSA with P-256 and SHA-256 |\n| `SignatureP384SHA384` | ECDSA with P-384 and SHA-384 |\n| `SignatureEd25519` | Ed25519 |\n\n### Creating Certificates\n\n```go\ncertDER, _ := mtc.CreateCertificate(\n    log.Tree(),     // Merkle tree\n    issuerID,       // issuer trust anchor ID\n    logID,          // log ID (derived from CA ID + log number)\n    logNumber,      // uint16 log number\n    index,          // entry index\n    tbsCertFields,  // func(b *cryptobyte.Builder) to write validity, subject, extensions\n    spkiDER,        // DER-encoded SubjectPublicKeyInfo\n    start, end,     // subtree for the proof\n    extensions,     // MerkleTreeCertEntry extensions (or nil)\n    cosignerKeys,   // []*CosignerKey\n)\n```\n\nThe certificate is a standard DER-encoded X.509 Certificate where:\n- `signatureAlgorithm` is `id-alg-mtcProof` (experimental OID `1.3.6.1.4.1.44363.47.0`)\n- `signatureValue` contains the serialized `MTCProof`\n- `issuer` DN contains the CA's trust anchor ID under the experimental RDN attribute OID `1.3.6.1.4.1.44363.47.2`\n- `serialNumber` encodes `(log_number \u003c\u003c 48) | index`\n\n### Verifying Certificates (Relying Party)\n\n```go\ncfg := \u0026mtc.VerifierConfig{\n    CAID: caID,\n    Cosigners: []mtc.TrustedCosigner{\n        {\n            CosignerID:         cosignerID,\n            SignatureAlgorithm: mtc.SignatureP256SHA256,\n            PublicKey:          \u0026ecdsaPublicKey,\n        },\n    },\n    Policy: \u0026mtc.AnyNCosignerPolicy{\n        N:       1,\n        Trusted: []mtc.TrustAnchorID{cosignerID},\n    },\n    // Optional: predistributed landmark subtree hashes\n    TrustedSubtrees: []mtc.TrustedSubtree{ ... },\n    // Optional: revoked index ranges\n    RevokedRanges: mtc.RevokedRanges{\n        {Start: 0, End: 100}, // distrust serial numbers [0, 100)\n    },\n}\n\nerr := mtc.VerifyCertificateSignature(certDER, cfg)\n```\n\nThe verification procedure (§7.2):\n1. Parses the `MTCProof` from the certificate's `signatureValue`\n2. Checks the serial number against revoked ranges\n3. Extracts log number and index from the serial number\n4. Derives the log ID from the CA ID and log number\n5. Reconstructs the `MerkleTreeCertEntry` (with extensions) from the `TBSCertificate`\n6. Evaluates the inclusion proof to compute the expected subtree hash\n7. If the subtree matches a trusted subtree (landmark-relative), accepts immediately\n8. Otherwise, verifies cosignatures against the cosigner policy\n\n### Landmark Sequences\n\nLandmarks are periodic tree sizes that enable size-optimized\n**landmark-relative certificates** (§6.3). These certificates contain only\nan inclusion proof to a predistributed subtree — no signatures.\n\n```go\ncaID, _ := mtc.ParseTrustAnchorID(\"32473.1\")\n\n// 7-day cert lifetime, 1-hour landmark interval → 169 active landmarks\nmaxActive := mtc.RecommendedMaxActiveLandmarks(168, 1) // 169\n\nls := mtc.NewLandmarkSequence(caID, 1, maxActive) // CA ID + log number + max active\nls.AllocateLandmark(1000)  // landmark 1 at tree size 1000\nls.AllocateLandmark(5000)  // landmark 2 at tree size 5000\n\n// Find which landmark contains an entry.\nlandmarkNum, subtree, _ := ls.FindContainingLandmark(3000)\n\n// Get the trust anchor ID for a landmark (e.g. \"32473.1.1.1.42\").\ntaID := ls.LandmarkTrustAnchorID(42)\n\n// List currently active landmarks.\nactive := ls.ActiveLandmarks()\n```\n\n### Subtree Interval Covering\n\nGiven an arbitrary interval [start, end), `FindSubtrees` returns one or two\nvalid subtrees that efficiently cover it (§4.5):\n\n```go\nleft, right, single, _ := mtc.FindSubtrees(5, 13)\n// left  = [4, 8)   (full subtree)\n// right = [8, 13)  (may be partial)\n```\n\n### Log Pruning\n\nLong-expired entries can be pruned from the log (§5.6.1):\n\n```go\nlog.Prune(1000) // entries [0, 1000) are no longer available\n// The tree structure is preserved — only entry data is dropped.\n```\n\n### Entry Encoding\n\n```go\n// Null entry (required at index 0):\nnullEntry := mtc.MarshalNullEntry()\n\n// TBS certificate entry from log entry contents:\nentry := mtc.MarshalTBSCertEntry(tbsCertLogEntryContents)\n\n// Build a TBSCertificateLogEntry from a DER TBSCertificate:\nlogEntryContents, _ := mtc.BuildTBSCertificateLogEntry(tbsCertDER)\n\n// Compute the leaf hash for a serialized entry:\nhash := mtc.HashEntry(entry)\n```\n\n## Experimental OIDs\n\nThis implementation uses the experimental OIDs defined in the draft for\nearly experimentation:\n\n| OID | Name | Usage |\n|-----|------|-------|\n| `1.3.6.1.4.1.44363.47.0` | `id-alg-mtcProof` | Certificate signature algorithm |\n| `1.3.6.1.4.1.44363.47.1` | `id-rdna-trustAnchorID` | Issuer DN attribute type |\n| `1.3.6.1.4.1.44363.47.2` | `id-pe-mtcCertificationAuthority` | MTC CA extension |\n\nThese will be replaced with IANA-assigned OIDs when the specification is finalized.\n\n## Specification Coverage\n\nThis implementation covers the following sections of\ndraft-ietf-plants-merkle-tree-certs-04:\n\n- **§4** Subtrees — definition, inclusion proofs, consistency proofs, interval covering\n- **§5** Issuance Logs — log structure, entries, cosigners, CA cosigners, pruning\n- **§6** Certificates — certificate format, standalone certificates, landmark-relative certificates\n- **§7** Relying Parties — trust anchors, signature verification, cosigner policies, trusted subtrees, revocation\n\nNot implemented (out of scope or dependent on external protocols):\n- §8 Use in TLS (trust anchor ID negotiation)\n- §9 ACME Extensions\n- §5.6 Log serving protocol (e.g. tlog-tiles)\n- Appendix C Tiled Transparency Log extensions\n- ML-DSA signature algorithms (pending Go standard library support)\n\n## Testing\n\n```\ngo test ./...\n```\n\nTo run the full lifecycle demo:\n\n```\ngo run ./cmd/mtc-demo/ demo\n```\n\n## License\n\nSee LICENSE file.\n\n## References\n\n- [draft-ietf-plants-merkle-tree-certs-04](https://www.ietf.org/archive/id/draft-ietf-plants-merkle-tree-certs-04.txt)\n- [RFC 9162 — Certificate Transparency v2](https://www.rfc-editor.org/rfc/rfc9162)\n- [draft-ietf-tls-trust-anchor-ids](https://datatracker.ietf.org/doc/draft-ietf-tls-trust-anchor-ids/)\n- [GitHub: ietf-plants-wg/merkle-tree-certs](https://github.com/ietf-plants-wg/merkle-tree-certs)\n\n## Prompts\n\n- [2026-04-23] Implement draft-ietf-plants-merkle-tree-certs-03\n- [2026-04-23] Create README.md with full documentation\n- [2026-05-31] Update implementation to draft-ietf-plants-merkle-tree-certs-04\n- [2026-06-02] Compare this repository with https://github.com/mcpherrinm/cactus.  For any behaviour differences or compatibility issues found, determine if there's a bug in this repository, or in the cactus repository, or if the MTC specification is insufficiently clear.  Produce a .md report of recommendations.\n- [2026-06-02] Fix those bugs.  Plug those conformance gaps, using filippo.io/mldsa instead of crypto/mldsa (for Go 1.26 compatibility).  One git commit per item.\nUpdate the headings in COMPARISON-WITH-CACTUS.md to indicate each item that has been fixed or mitigated.\n- [2026-06-02] Create a CLI tool.\n- [2026-06-02] Add CLI subcommands for operating an MTC CA, mirror, and anything else that might be missing.\n- [2026-06-02] Review and update README.md as necessary.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobstradling%2Fmtc-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobstradling%2Fmtc-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobstradling%2Fmtc-demo/lists"}