Refuse the +sct +issuer +ctlog flags when fetching hash tiles

This commit is contained in:
2026-04-05 22:06:51 +02:00
parent d80eeb9677
commit 76e3ce28e1
3 changed files with 16 additions and 2 deletions

View File

@@ -62,6 +62,16 @@ Data tile from a local file (with issuer resolution):
ctfetch --monitoring-url https://halloumi2026h1.mon.ct.ipng.ch tile.bin +issuer ctfetch --monitoring-url https://halloumi2026h1.mon.ct.ipng.ch tile.bin +issuer
``` ```
## Hash tiles vs data tiles
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.
**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.
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.
## Output modifiers ## Output modifiers
| Modifier | Description | | Modifier | Description |

View File

@@ -211,7 +211,7 @@ func DumpAllEntries(tileData []byte, opts Options) (*DumpResult, error) {
if err != nil { if err != nil {
// If it fails, try as hash tile // If it fails, try as hash tile
fmt.Fprintf(os.Stderr, "Not a data tile, trying as hash tile...\n") fmt.Fprintf(os.Stderr, "Not a data tile, trying as hash tile...\n")
return dumpHashTile(tileData) return dumpHashTile(tileData, opts)
} }
return result, nil return result, nil
} }
@@ -237,7 +237,11 @@ func dumpDataTile(tileData []byte, opts Options) (*DumpResult, error) {
}, nil }, nil
} }
func dumpHashTile(tileData []byte) (*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)")
}
const hashSize = 32 // SHA-256 hash size const hashSize = 32 // SHA-256 hash size
if len(tileData)%hashSize != 0 { if len(tileData)%hashSize != 0 {

BIN
tile.data Normal file

Binary file not shown.