From cba89df53bec3ff75f380cf3deae2e33f91120c4 Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Sun, 5 Apr 2026 23:20:13 +0200 Subject: [PATCH] Add +all argument --- README.md | 11 ++++++----- cmd/ctfetch/main.go | 14 +++++++++----- internal/utils/utils.go | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 28a0cb6..df08870 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ not index modules on `git.ipng.ch`. Fetch a specific entry (or all entries in its tile) by leaf index: ```bash -ctfetch [flags] [+sct] [+issuer] [+ctlog] +ctfetch [flags] [+sct] [+issuer] [+ctlog] [+all] ``` **Examples:** @@ -32,7 +32,7 @@ ctfetch https://halloumi2026h1.mon.ct.ipng.ch 629794635 Dump with SCTs, issuer chain, and CT log details: ```bash -ctfetch https://halloumi2026h1.mon.ct.ipng.ch 629794635 +sct +issuer +ctlog +ctfetch https://halloumi2026h1.mon.ct.ipng.ch 629794635 +all ``` ### Tile-dump mode @@ -40,7 +40,7 @@ ctfetch https://halloumi2026h1.mon.ct.ipng.ch 629794635 +sct +issuer +ctlog Fetch all entries from a tile URL or a local file. Automatically detects data tiles (log entries) and hash tiles (Merkle tree hashes). ```bash -ctfetch [flags] [+sct] [+issuer] [+ctlog] +ctfetch [flags] [+sct] [+issuer] [+ctlog] [+all] ``` **Examples:** @@ -69,9 +69,9 @@ ctfetch --monitoring-url https://halloumi2026h1.mon.ct.ipng.ch tile.bin +issuer A Static CT log stores two kinds of tiles: -**Data tiles** (`/tile/data/...`) contain the actual log entries — DER-encoded certificates and precertificates along with their metadata (leaf index, timestamp, chain fingerprints, etc.). These are what `ctfetch` parses into structured JSON. The output modifiers `+sct`, `+issuer`, and `+ctlog` all operate on data tiles. +**Data tiles** (`/tile/data/...`) contain the actual log entries — DER-encoded certificates and precertificates along with their metadata (leaf index, timestamp, chain fingerprints, etc.). These are what `ctfetch` parses into structured JSON. The output modifiers `+sct`, `+issuer`, `+ctlog`, and `+all` all operate on data tiles. -**Hash tiles** (`/tile/N/...`, where N is a tree level ≥ 0) contain the internal nodes of the Merkle tree — rows of raw 32-byte SHA-256 hashes used for inclusion and consistency proofs. There are no certificates in a hash tile; `ctfetch` outputs only the list of hashes. Using `+sct`, `+issuer`, or `+ctlog` with a hash tile is an error. +**Hash tiles** (`/tile/N/...`, where N is a tree level ≥ 0) contain the internal nodes of the Merkle tree — rows of raw 32-byte SHA-256 hashes used for inclusion and consistency proofs. There are no certificates in a hash tile; `ctfetch` outputs only the list of hashes. Using `+sct`, `+issuer`, `+ctlog`, or `+all` with a hash tile is an error. The tree is organised so that level 0 hashes cover individual leaves (each is `SHA-256(0x00 || MerkleTreeLeaf)`), and each higher level hashes pairs of nodes from the level below. The tile URL encodes the level: `/tile/0/...` is level 0, `/tile/1/...` is level 1, and so on. @@ -82,6 +82,7 @@ The tree is organised so that level 0 hashes cover individual leaves (each is `S | `+sct` | Parse and include embedded Signed Certificate Timestamps from final (non-precert) certificates | | `+issuer` | Fetch and include issuer certificate details from the log's `/issuer/` endpoint | | `+ctlog` | Look up each SCT's log ID in the CT log list and include operator/state details | +| `+all` | Enable all of `+sct`, `+issuer`, and `+ctlog` at once | ## Flags diff --git a/cmd/ctfetch/main.go b/cmd/ctfetch/main.go index 5949ede..2c60e0e 100644 --- a/cmd/ctfetch/main.go +++ b/cmd/ctfetch/main.go @@ -2,8 +2,8 @@ // // Two modes: // -// ctfetch [flags] [+sct] [+issuer] [+ctlog] fetch one entry by leaf index -// ctfetch [flags] [+sct] [+issuer] [+ctlog] dump all entries in a tile +// ctfetch [flags] [+sct] [+issuer] [+ctlog] [+all] fetch one entry by leaf index +// ctfetch [flags] [+sct] [+issuer] [+ctlog] [+all] dump all entries in a tile // // (C) Copyright 2026 Pim van Pelt package main @@ -27,8 +27,8 @@ func main() { monitoringURL := flag.String("monitoring-url", "", "log root URL for issuer lookups when input is a file") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage:\n") - fmt.Fprintf(os.Stderr, " %s [flags] [+sct] [+issuer] [+ctlog] fetch one entry\n", os.Args[0]) - fmt.Fprintf(os.Stderr, " %s [flags] [+sct] [+issuer] [+ctlog] dump all entries in a tile\n", os.Args[0]) + fmt.Fprintf(os.Stderr, " %s [flags] [+sct] [+issuer] [+ctlog] [+all] fetch one entry\n", os.Args[0]) + fmt.Fprintf(os.Stderr, " %s [flags] [+sct] [+issuer] [+ctlog] [+all] dump all entries in a tile\n", os.Args[0]) fmt.Fprintf(os.Stderr, "\nExamples:\n") fmt.Fprintf(os.Stderr, " %s https://halloumi2026h1.mon.ct.ipng.ch 457683896 +sct +issuer +ctlog\n", os.Args[0]) fmt.Fprintf(os.Stderr, " %s https://halloumi2026h1.mon.ct.ipng.ch/tile/data/x002/x460/135 +sct\n", os.Args[0]) @@ -68,8 +68,12 @@ func main() { opts.ShowIssuer = true case "+ctlog": opts.ShowCTLog = true + case "+all": + opts.ShowSCT = true + opts.ShowIssuer = true + opts.ShowCTLog = true default: - fatal("unknown argument %q (expected +sct, +issuer, or +ctlog)", arg) + fatal("unknown argument %q (expected +sct, +issuer, +ctlog, or +all)", arg) } } diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 6c8eab6..b8e44da 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -238,7 +238,7 @@ func dumpDataTile(tileData []byte, opts Options) (*DumpResult, error) { func dumpHashTile(tileData []byte, opts Options) (*DumpResult, error) { if opts.ShowSCT || opts.ShowIssuer || opts.ShowCTLog { - return nil, fmt.Errorf("+sct, +issuer, and +ctlog are not valid for hash tiles (only data tiles contain certificates)") + return nil, fmt.Errorf("+sct, +issuer, +ctlog, and +all are not valid for hash tiles (only data tiles contain certificates)") } const hashSize = 32 // SHA-256 hash size