### TUF Repository File Naming (Bash Example) Source: https://context7.com/theupdateframework/specification/llms.txt This example demonstrates the difference in repository file naming conventions between a setup without consistent snapshots and one with consistent snapshots enabled. Consistent snapshots use version prefixes for metadata and hash prefixes for target files. ```bash # Repository layout WITHOUT consistent snapshots: repository/ ├── root.json ├── timestamp.json ├── snapshot.json ├── targets.json └── targets/ └── mypackage-1.0.tar.gz # Repository layout WITH consistent snapshots: repository/ ├── 1.root.json # Version-prefixed metadata ├── 2.root.json ├── timestamp.json # Always without version prefix ├── 42.snapshot.json # Version-prefixed ├── 42.targets.json # Version-prefixed └── targets/ └── c14aeb4ac9f4a8fc.mypackage-1.0.tar.gz # Hash-prefixed target ``` -------------------------------- ### Example snapshot.json File Source: https://github.com/theupdateframework/specification/blob/master/tuf-spec.md An example of a complete snapshot.json file, demonstrating the inclusion of signatures, version information, and metadata for various files like targets.json, project1.json, and project2.json. ```json { "signatures": [ { "keyid": "66676daa73bdfb4804b56070c8927ae491e2a6c2314f05b854dea94de8ff6bfc", "sig": "f7f03b13e3f4a78a23561419fc0dd741a637e49ee671251be9f8f3fceedfc112e4\n 4ee3aaff2278fad9164ab039118d4dc53f22f94900dae9a147aa4d35dcfc0f" } ], "signed": { "_type": "snapshot", "spec_version": "1.0.0", "expires": "2030-01-01T00:00:00Z", "meta": { "targets.json": { "version": 1 }, "project1.json": { "version": 1, "hashes": { "sha256": "f592d072e1193688a686267e8e10d7257b4ebfcf28133350dae88362d82a0c8a" } }, "project2.json": { "version": 1, "length": 604, "hashes": { "sha256": "1f812e378264c3085bb69ec5f6663ed21e5882bbece3c3f8a0e8479f205ffb91" } } }, "version": 1 } } ``` -------------------------------- ### Example root.json File Source: https://github.com/theupdateframework/specification/blob/master/tuf-spec.md An example of a root.json file, demonstrating the 'signatures' and 'signed' sections. The 'signed' section includes metadata like version, expiration, keys, and role definitions with their associated key IDs and thresholds. ```json { "signatures": [ { "keyid": "cb3fbd83df4ba2471a736b065650878280964a98843ec13b457a99b2a21cc3b4", "sig": "a312b9c3cb4a1b693e8ebac5ee1ca9cc01f2661c14391917dcb111517f72370809\n f32c890c6b801e30158ac4efe0d4d87317223077784c7a378834249d048306" } ], "signed": { "_type": "root", "spec_version": "1.0.0", "consistent_snapshot": false, "expires": "2030-01-01T00:00:00Z", "keys": { "1bf1c6e3cdd3d3a8420b19199e27511999850f4b376c4547b2f32fba7e80fca3": { "keytype": "ed25519", "scheme": "ed25519", "keyval": { "public": "72378e5bc588793e58f81c8533da64a2e8f1565c1fcc7f253496394ffc52542c" } }, "135c2f50e57ff11e744d234a62cebad8c38daf399604a7655661cc9199c69164": { "keytype": "ed25519", "scheme": "ed25519", "keyval": { "public": "68ead6e54a43f8f36f9717b10669d1ef0ebb38cee6b05317669341309f1069cb" } }, "cb3fbd83df4ba2471a736b065650878280964a98843ec13b457a99b2a21cc3b4": { "keytype": "ed25519", "scheme": "ed25519", "keyval": { "public": "66dd78c5c2a78abc6fc6b267ff1a8017ba0e8bfc853dd97af351949bba021275" } }, "66676daa73bdfb4804b56070c8927ae491e2a6c2314f05b854dea94de8ff6bfc": { "keytype": "ed25519", "scheme": "ed25519", "keyval": { "public": "01c61f8dc7d77fcef973f4267927541e355e8ceda757e2c402818dad850f856e" } } }, "roles": { "root": { "keyids": [ "cb3fbd83df4ba2471a736b065650878280964a98843ec13b457a99b2a21cc3b4" ], "threshold": 1 }, "snapshot": { "keyids": [ ``` -------------------------------- ### Example Signed Timestamp JSON File Source: https://github.com/theupdateframework/specification/blob/master/tuf-spec.md Provides a concrete example of a signed timestamp.json file, demonstrating the expected format for signatures, signed content, and metadata hashes. ```json { "signatures": [ { "keyid": "1bf1c6e3cdd3d3a8420b19199e27511999850f4b376c4547b2f32fba7e80fca3", "sig": "90d2a06c7a6c2a6a93a9f5771eb2e5ce0c93dd580bebc2080d10894623cfd6eaed\n f4df84891d5aa37ace3ae3736a698e082e12c300dfe5aee92ea33a8f461f02" } ], "signed": { "_type": "timestamp", "spec_version": "1.0.0", "expires": "2030-01-01T00:00:00Z", "meta": { "snapshot.json": { "hashes": { "sha256": "c14aeb4ac9f4a8fc0d83d12482b9197452f6adf3eb710e3b1e2b79e8d14cb681" }, "length": 1007, "version": 1 } }, "version": 1 } } ``` -------------------------------- ### targets.json Metadata File Example Source: https://github.com/theupdateframework/specification/blob/master/tuf-spec.md An example of a targets.json metadata file used in The Update Framework. This file contains signature information, signed metadata including delegations, and a list of target files with their hashes and lengths. ```json { "signatures": [ { "keyid": "135c2f50e57ff11e744d234a62cebad8c38daf399604a7655661cc9199c69164", "sig": "e9fd40008fba263758a3ff1dc59f93e42a4910a282749af915fbbea1401178e5a0\n 12090c228f06db1deb75ad8ddd7e40635ac51d4b04301fce0fd720074e0209" } ], "signed": { "_type": "targets", "spec_version": "1.0.0", "delegations": { "keys": { "f761033eb880143c52358d941d987ca5577675090e2215e856ba0099bc0ce4f6": { "keytype": "ed25519", "scheme": "ed25519", "keyval": { "public": "b6e40fb71a6041212a3d84331336ecaa1f48a0c523f80ccc762a034c727606fa" } } }, "roles": [ { "keyids": [ "f761033eb880143c52358d941d987ca5577675090e2215e856ba0099bc0ce4f6" ], "name": "project", "paths": [ "project/file3.txt" ], "threshold": 1 } ] }, "expires": "2030-01-01T00:00:00Z", "targets": { "file1.txt": { "hashes": { "sha256": "65b8c67f51c993d898250f40aa57a317d854900b3a04895464313e48785440da" }, "length": 31 }, "dir/file2.txt": { "hashes": { "sha256": "452ce8308500d83ef44248d8e6062359211992fd837ea9e370e561efb1a4ca99" }, "length": 39 } }, "version": 1 } } ``` -------------------------------- ### TUF Client Update Workflow (Python Pseudocode) Source: https://context7.com/theupdateframework/specification/llms.txt This pseudocode illustrates the step-by-step process a TUF client follows to securely update its metadata, starting from loading the root metadata to fetching specific targets. It includes verification of signatures, hashes, versions, and expiration times to maintain security. ```python # Pseudocode for TUF client update workflow def update_client(): # Step 1: Record fixed update start time update_start_time = datetime.now(timezone.utc) # Step 2: Load trusted root metadata (shipped with client) trusted_root = load_local_metadata("root.json") # Step 3: Update root role (check for key rotations) current_version = trusted_root["signed"]["version"] while True: try: new_root = download(f"{current_version + 1}.root.json") # Verify signed by threshold of keys from BOTH old and new root verify_signatures(new_root, trusted_root["signed"]["roles"]["root"]) verify_signatures(new_root, new_root["signed"]["roles"]["root"]) # Check version is exactly N+1 assert new_root["signed"]["version"] == current_version + 1 trusted_root = new_root persist("root.json", trusted_root) current_version += 1 except FileNotFoundError: break # Check root hasn't expired assert parse_datetime(trusted_root["signed"]["expires"]) > update_start_time # Step 4: Update timestamp timestamp = download("timestamp.json") verify_signatures(timestamp, trusted_root["signed"]["roles"]["timestamp"]) assert parse_datetime(timestamp["signed"]["expires"]) > update_start_time persist("timestamp.json", timestamp) # Step 5: Update snapshot snapshot_version = timestamp["signed"]["meta"]["snapshot.json"]["version"] snapshot = download(f"{snapshot_version}.snapshot.json") verify_hash(snapshot, timestamp["signed"]["meta"]["snapshot.json"].get("hashes")) verify_signatures(snapshot, trusted_root["signed"]["roles"]["snapshot"]) assert parse_datetime(snapshot["signed"]["expires"]) > update_start_time persist("snapshot.json", snapshot) # Step 6: Update targets targets_version = snapshot["signed"]["meta"]["targets.json"]["version"] targets = download(f"{targets_version}.targets.json") verify_hash(targets, snapshot["signed"]["meta"]["targets.json"].get("hashes")) verify_signatures(targets, trusted_root["signed"]["roles"]["targets"]) assert parse_datetime(targets["signed"]["expires"]) > update_start_time persist("targets.json", targets) return targets # Step 7: Fetch specific target def fetch_target(target_path, targets_metadata): target_info = targets_metadata["signed"]["targets"].get(target_path) if not target_info: raise TargetNotFoundError(target_path) # For consistent snapshots, use hash-prefixed filename target_hash = target_info["hashes"]["sha256"] filename = f"{target_hash}.{target_path}" content = download_target(filename, max_bytes=target_info["length"]) verify_hash(content, target_info["hashes"]) return content ``` -------------------------------- ### Build TUF Specification HTML with Makefile Source: https://context7.com/theupdateframework/specification/llms.txt Utilizes the Makefile to build the TUF specification into HTML format using Bikeshed. Supports building different versions and a full release. ```bash # Build the specification HTML from tuf-spec.md make spec # Build and copy to latest/ directory make latest # Build and copy to draft/ directory make draft # Build versioned directory (e.g., v1.0.34/) make versioned # Build index.html listing all versions make index # Full release: builds spec, latest, and versioned directories make release ``` -------------------------------- ### METAFILES Object Structure Source: https://github.com/theupdateframework/specification/blob/master/tuf-spec.md Describes the METAFILES object within snapshot.json, which maps metadata file paths to their version, optional length, and optional hashes. ```json { METAPATH : { "version" : VERSION, ("length" : LENGTH,) ("hashes" : HASHES) }, ... } ``` -------------------------------- ### Build TUF Specification Version Index HTML with Python Source: https://context7.com/theupdateframework/specification/llms.txt A Python script to generate an 'index.html' file that lists all published TUF specification versions, including 'latest' and 'draft'. It scans directories for versioned HTML files. ```python #!/usr/bin/env python3 import os def build_index(): """Generate index.html listing all specification versions.""" html_locations = ['latest', 'draft'] # Find all versioned directories (v1.0.0, v1.0.1, etc.) dir_contents = sorted(os.listdir('.'), reverse=True) for path in dir_contents: if path.startswith('v') and os.path.exists(f'{path}/index.html'): html_locations.append(path) # Generate HTML with links to each version html = '