Skip to content

fix: strip trailing null byte from RPi serial (s2b-debt-v2)#61

Closed
elmol wants to merge 41 commits into
elmol:mainfrom
biotexturas:fix/s2b-debt-v2-serial-null-byte
Closed

fix: strip trailing null byte from RPi serial (s2b-debt-v2)#61
elmol wants to merge 41 commits into
elmol:mainfrom
biotexturas:fix/s2b-debt-v2-serial-null-byte

Conversation

@elmol
Copy link
Copy Markdown
Owner

@elmol elmol commented Mar 21, 2026

Summary

  • RPi device tree serial (/sys/firmware/devicetree/base/serial-number) includes a trailing null byte (\0) from the FDT binary format
  • String::trim() only strips whitespace, not \0, so device capture embedded the null byte into capture.json while device init printed it without (invisible in terminal)
  • This caused keccak256("serial\0") ≠ keccak256("serial") → UNVERIFIED on-chain
  • Fix: add .trim_end_matches('\0') to read_serial() (same pattern already used for camera_info in lib.rs:170)
  • Added regression test verifying init serial == capture serial with no null bytes

Test plan

  • New test serial_has_no_trailing_null_byte passes
  • All 22 device tests pass
  • All 23 Solidity tests pass
  • just ci passes

🤖 Generated with Claude Code

elmol and others added 30 commits March 20, 2026 22:12
Rewrite README with TerraGenesis identity (microscopy DeSci application)
while preserving all HardTrust technical content. Add "Built on HardTrust"
section, hackathon proposal, and update CLAUDE.md with project context.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
docs: integrate TerraGenesis branding and proposal
Edited link for TerraScope
Fixed TerraScope link Markup typo
Update repo references from elmol/hardtrust to biotexturas/terra-genesis.
Rename HARDTRUST_VERSION env var to TERRAGENESIS_VERSION in install scripts.
Update release naming, deployment docs, and spec URLs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
chore: adapt CI/CD and install scripts for TerraGenesis
Add Signable trait with prehash() and signature_hex() methods.
Implement for existing Reading (moved reading_prehash body into it)
and new Capture type. Add generic sign<T>/verify<T> functions.
Keep sign_reading/verify_reading as backwards-compatible wrappers.

Add Capture and CaptureFile domain types with Signable implementation.
Add InvalidPayload variant to ProtocolError.

All 25 protocol tests pass (17 existing + 8 new Capture tests).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
refactor: extract Signable trait and generic sign/verify (s2a.1-v1)
…-v2)

Add `device capture --cmd <command> --output-dir <path>` subcommand that:
- Executes external command via bash -c
- Reads all output files, computes SHA-256 hashes
- Builds sorted file manifest with content_hash
- Signs Capture struct using protocol::sign
- Writes capture.json to current directory

Add sha2 dependency for SHA-256 file hashing.
Add helper functions: hash_file, compute_content_hash, collect_capture_files,
create_signed_capture in device/src/lib.rs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: add device capture command (s2a.1-v2)
Add generic verify_device_data<T: Signable> in attester lib, keep
verify_device as backwards-compatible wrapper. Auto-detect file format
in verify command by checking for "content_hash" (Capture) vs
"temperature" (Reading). No new CLI flags needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…capture

feat: extend attester verify to support capture files (s2a.1-v3)
…a.2-v1)

Create terrascope/capture.sh — hardware adapter for TerraScope microscopes.
Auto-detects libcamera-still or raspistill, captures image, generates
metadata.json with camera info, resolution, timestamp, and hostname.
Configurable via TERRASCOPE_RESOLUTION and TERRASCOPE_QUALITY env vars.

Add ADR-0009 documenting the capture script as hardware adapter pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: add TerraScope capture script with auto-detect and metadata (s2a.2-v1)
…-v2)

- Make --cmd optional with default /usr/local/lib/terrascope/capture.sh
- Show helpful error when default script missing (suggests install or --cmd override)
- Pass output_dir as argument to capture command (per ADR-0009 contract)
- install-device.sh now downloads and installs capture script
- release.yml uploads terrascope/capture.sh as release artifact

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: default capture script path + install + release pipeline (s2a.2-v2)
…ecksum, README, key helper (s2a-debt)

- Fix 1: Clean output-dir before capture to prevent stale files
- Fix 2: Replace json.contains("content_hash") with serde untagged enum
- Fix 3: Pass output_dir via bash -c positional args (handles spaces)
- Fix 4: Add SHA-256 checksum for capture script in install + release
- Fix 5: Add Capture section to README, update repo structure, check scope
- Fix 6: Extract load_device_key() to eliminate emit/capture duplication

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Serde untagged enum reports "did not match any variant" instead of
"missing field" — accept both patterns in test assertions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: review findings — clean dir, serde enum, quoted paths, checksum, README, key helper
- Create scripts/mock-capture.sh — deterministic mock following ADR-0009
- Case 3: device capture with mock → attester verify → VERIFIED
- Case 4: fake capture.json → attester verify → UNVERIFIED
- Update cleanup to remove capture artifacts
- Cases 1 + 2 (reading) unchanged

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Append "$1" to the command string so external scripts receive the
output directory as their first positional argument. Fixes e2e failure
where mock-capture.sh wasn't receiving the output dir.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
test: add capture e2e cases to The Wire (s2a.3-v1)
…es (s0.20)

- Add Release & Installation section with biotexturas/terra-genesis URLs
- Add Configuration section (env vars table)
- Add CI section (lint/test/e2e)
- Update Repository Structure (terrascope/, release.toml, install scripts)
- Check all 4 Hackathon Scope items
- Commit all untracked specs (9 files) and stories (2 files)
- Add capture.json and capture-output/ to .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
docs: full sync — README, specs/stories, gitignore, branch cleanup (s0.20)
…tory in artifact

The upload-artifact action preserved the terrascope/ directory, so the
file landed at artifacts/terrascope/capture.sh instead of artifacts/capture.sh.
Fix by copying to terrascope-capture.sh at repo root before upload.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… prehash

Adds CaptureEnvironment (script_hash, binary_hash, hw_serial, camera_info)
to the Capture domain type. Updates Signable::prehash to include environment
fields, ensuring any env change invalidates the signature.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds collect_environment() and detect_camera_info() to device lib.
Updates capture handler to collect and sign environment metadata
(script hash, binary hash, hw serial, camera info).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ecking

Prints environment info for captures. When --release-hashes is provided,
compares script_hash and binary_hash against known-good values and prints
MATCH or MISMATCH per field.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Case 5: capture + verify with --release-hashes → environment MATCH
Case 6: tampered script + verify → MISMATCH, signature still VERIFIED

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
elmol and others added 11 commits March 21, 2026 10:26
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…estation

feat: capture environment attestation (s2a.4-v1)
…4-v2)

- Embed SHA256SUMS at compile time (empty in debug, included in release)
- Environment check runs by default using embedded hashes
- --release-hashes <path> overrides with custom file
- --skip-env-check disables environment verification entirely
- Debug builds gracefully skip with warning when no hashes available
- Placeholder SHA256SUMS added to repo root

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e-hashes

feat: embed release hashes for default env verification (s2a.4-v2)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ices mapping

- Import OZ ECDSA for safe signature verification (rejects s-malleability)
- Add registeredDevices reverse lookup mapping, populated on registerDevice()
- Add verifyCapture(captureHash, v, r, s) view function — zero gas cost
- 9 new Foundry tests including shared test vector, fuzz, malleability

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ecover

- Compute prehash via Signable::prehash(), extract (v, r, s) from signature
- v derived explicitly as recovery_id + 27
- Handles invalid signatures gracefully (prints UNVERIFIED)
- Readings keep existing off-chain flow unchanged

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Identical bytes32 hash verified in both Rust (protocol) and Foundry tests,
proving the signing and verification sides agree on the capture prehash.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: on-chain capture verification via verifyCapture view function (s2b.1-v1)
…t function (s2b-debt-v1)

Merge the separate verifyCapture (4-param) and verifyEnvironment into a
single verifyCapture (6-param) that returns (valid, signer, scriptMatch,
binaryMatch). Add setApprovedHashes for on-chain env hash storage.

Attester CLI now makes ONE contract call for full capture verification,
falling back to embedded hashes when no on-chain approved hashes are set.

E2E Cases 5-6 updated to use on-chain env verification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ation (s2b-debt-v2)

RPi device tree serial (/sys/firmware/devicetree/base/serial-number) includes
a null terminator that was not stripped, causing keccak256 hash mismatch between
device init (no \0) and device capture (\0 included) → UNVERIFIED on-chain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@elmol elmol closed this Mar 21, 2026
@elmol elmol deleted the fix/s2b-debt-v2-serial-null-byte branch March 21, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants