feat(build): one-command reproducible-build verification script#449
Open
BitHighlander wants to merge 2 commits into
Open
feat(build): one-command reproducible-build verification script#449BitHighlander wants to merge 2 commits into
BitHighlander wants to merge 2 commits into
Conversation
Third-party verifiers keep failing KeepKey reproducibility checks by hashing the freshly built binary (zeroed signature slots in its 256-byte KPKY header) against the signed release's payload hash — an apples-to-oranges comparison that can never match (#433, and the same confusion in 2021's #283). scripts/build/verify-repro.sh makes the correct comparison a single command: clean clone at the tag, official Docker build, download of the signed release asset, and payload-hash (tail -c +257) comparison on both sides, printing all four hashes and PASS/FAIL. docs/ReproducibleBuilds.md documents the header layout, why full-file hashes never match by construction, the manual steps, and the on-device cross-checks (Features.revision, Features.firmware_hash).
…s-check - error out on unrecognized/mistyped flags (e.g. --local=x) instead of silently ignoring them and falling through to the download-and-compare path, which could print a false PASS for a binary that was never read - docs: Features.firmware_hash covers the full signed file (header + payload, per memory_firmware_hash()), not the payload alone — the doc previously implied it matched the payload hash, which never matches
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
scripts/build/verify-repro.shanddocs/ReproducibleBuilds.md— a single command that clones a release tag, builds it with the official Docker image, downloads the signed release binary, and compares the device-verifiable payload hashes (sha256 of everything after the 256-byte KPKY header).Why
Third-party verifiers keep failing reproducibility checks by comparing the wrong hashes: a freshly built binary has zeroed signature-index bytes and signature slots in its 256-byte header (release signing fills them in — nothing else changes), so
sha256(built full file)can never equalsha256(signed release file), even for a byte-identical build. Only the payload hash (tail -c +257) is meaningful.This exact confusion has now hit KeepKey twice: #283 (2021, resolved manually by @reidrankin in a comment) and #433 (2026, WalletScrutiny). We reproduced #433's build today — the reporter's own "Built" hash matches our official binary's full-file hash exactly, meaning their build was byte-for-byte correct; only the final comparison was wrong.
docs/ReproducibleBuilds.mddocuments the 256-byte header layout, why full-file hashes never match by construction, the manual verification steps, and two on-device cross-checks:Features.revision(embeds the build commit) andFeatures.firmware_hash(sha256 of the full signed image as installed — explicitly not the payload hash, to avoid propagating the same confusion).Test plan
bash -n+shellcheckcleanv7.14.1: built payload73a880…matches the official release payload hash inHASHES.txt—PASS--local, mistyped--local=x, unknown flags, and trailing garbage after a valid--localall now error instead of silently falling through