Skip to content

Document signature verification and the release signing step - #6

Merged
ohcee merged 2 commits into
Veil-Project:masterfrom
ohcee:pgp-signing
Aug 23, 2026
Merged

Document signature verification and the release signing step#6
ohcee merged 2 commits into
Veil-Project:masterfrom
ohcee:pgp-signing

Conversation

@ohcee

@ohcee ohcee commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

Problem

SHA256SUMS.txt proves a download matches what was published. It cannot prove who published it. Anyone able to attach assets to a release can attach a rewritten sums file alongside a tampered archive, and every documented check would still pass. Nothing in the repo closed that, and nothing told a maintainer to sign a release either, so it would not have happened consistently.

Description

Adds a detached PGP signature over the sums file to the release process, documents how a user verifies it, and adds a RELEASING.md so the signing step is part of the checklist rather than something remembered.

Root Cause

Checksums answer integrity, meaning the bytes did not change in transit. Authenticity, meaning these bytes came from the maintainer, needs a signature over something that covers the archives. The release process had the first half and not the second.

Why broke?

Not a regression, this was never present. It is easy to miss because a checksum file looks like it provides both properties, and it reads as sufficient right up until the threat is someone with write access rather than a flaky download.

Solution

Sign SHA256SUMS.txt with the maintainer key and publish SHA256SUMS.txt.asc next to it, the same model Bitcoin Core uses: one signature over the sums file covers every archive it lists, instead of a signature per binary.

Signing is deliberately a local step and not a CI job. A signing key held in CI secrets could be used by anyone who compromised the repository, which is close to the threat the signature exists to address, so it would add little over the checksums it sits beside.

How fix?

Users import the key once and check the sums file before checking their download:

gpg --keyserver keys.openpgp.org --recv-keys 5C2CFA030397FCD763F1A97BF8788EFB40E750E5
gpg --verify SHA256SUMS.txt.asc SHA256SUMS.txt
sha256sum -c SHA256SUMS.txt --ignore-missing

The maintainer fingerprint is in the README so it can be compared against a source the reader already trusts:

5C2C FA03 0397 FCD7 63F1  A97B F878 8EFB 40E7 50E5

RELEASING.md sets the order deliberately: verify the sums against the archives first, then sign, so a signature never certifies a mismatch. It also notes that PGP does nothing for Windows antivirus detections, since Windows does not read PGP, and points at Authenticode and the Microsoft false positive submission for that instead.

Unit Testing Results

Documentation and a checklist only, no code and no build changes, so CI covers this only in the sense that it must stay green.

The signing key was generated and inspected: ed25519 primary with signing capability, a cv25519 encryption subkey, uid ohcee <donkeybabe123@hotmail.com>, expires 2028-08-22, fingerprint as above.

Update: done end to end. The key is published to keys.openpgp.org with its email identity verified, and it is on the GitHub account so commits show as verified. v1.1.3 now carries SHA256SUMS.txt.asc on both this release and the fork's, and the How to test sequence below was run from a clean download: Good signature from "ohcee <donkeybabe123@hotmail.com>" against the published sums file, then veilminer-v1.1.3-macos-arm64.tar.gz: OK against those sums. The published sums were separately checked against GitHub's own digests of every archive and match.

One thing worth recording: the first signature uploaded was good but made over a stale local copy of the sums file, so it failed verification against the published one on both releases. It was replaced within the hour. That is exactly the mistake RELEASING.md orders the steps to prevent, and the fix for it is the rule the file states: sign the sums file downloaded from the release, never a local copy.

The README also gained a plain HTTPS fetch fallback, since some macOS builds of GnuPG 2.5 cannot reach the keyserver through dirmngr. A signature over the existing v1.1.3 sums file can be added without rebuilding anything, since the assets are unchanged.

How to test?

After the key is published and a release is signed, from a machine that has never seen the key:

gpg --keyserver keys.openpgp.org --recv-keys 5C2CFA030397FCD763F1A97BF8788EFB40E750E5
gh release download v1.1.3 -p 'SHA256SUMS.txt*' -p 'veilminer-*'
gpg --verify SHA256SUMS.txt.asc SHA256SUMS.txt
sha256sum -c SHA256SUMS.txt --ignore-missing

Expect Good signature from "ohcee <donkeybabe123@hotmail.com>" with the fingerprint above, then OK for each archive. The warning that the key is not certified with a trusted signature is expected and only means the verifier has not personally certified the key.

ohcee added 2 commits August 22, 2026 21:54
Checksums prove a download matches what was published, not who
published it: anyone who can attach a release can replace the sums
file alongside it. A detached signature over SHA256SUMS.txt closes
that gap.

Signing is a local step on purpose. A key kept in CI secrets could be
used by anyone who compromised the repository, so it would add no
assurance over the checksums it sits next to.

Adds the verify steps and the maintainer fingerprint to the README,
and a RELEASING checklist that verifies sums before signing them so a
signature never certifies a mismatch.
Some macOS builds of GnuPG 2.5 cannot reach keys.openpgp.org through
dirmngr and fail with Try again later, even though the server answers
a direct HTTPS request fine. Document the curl route so the verify
steps do not dead end on a local GnuPG quirk.
@ohcee
ohcee merged commit 1e5bf15 into Veil-Project:master Aug 23, 2026
5 checks passed
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.

1 participant