Skip to content

Verify GPG signatures against per-project trusted signers - #414

Merged
3rdIteration merged 5 commits into
devfrom
gpg-trusted-signers
Aug 30, 2026
Merged

Verify GPG signatures against per-project trusted signers#414
3rdIteration merged 5 commits into
devfrom
gpg-trusted-signers

Conversation

@3rdIteration

Copy link
Copy Markdown
Owner

What changed

ToolsGPGVerifyFileView now checks not just that a signature is cryptographically valid, but who made it:

  • New src/seedsigner/models/gpg_trusted_projects.py maps filenames to projects and primary-key fingerprints to expected signers (13 tracked projects).
  • Valid signature + trusted signer for the file's project → success screen showing the project name and full 40-char fingerprint(s) of every valid signer.
  • Valid signature from a key belonging to a different tracked project, or an untracked key for a known project → blocking warning (I Understand) before the success screen.
  • Files from untracked projects (or ambiguous names like a bare SHA256SUMS that can't be attributed) are shown neutrally — fingerprints only, no trust judgment.
  • Multi-signature files pass if any signer is in the project's set.
  • Detached signatures may use .sig or .asc (both paired; .sig preferred); clearsigned files (e.g. COLDCARD's signatures.txt) verify directly. Verification now parses gpg --status-fd=1 output for robust signer extraction.

Key bundle:

  • Added: Specter Signing Key 2026, Electrum felixb_f321x and svanstaa (key IDs observed in published release signatures).
  • Removed: Tails key (stale — missing the EdDSA subkey current signatures use) and duplicate BitcoinCore Matthew Zipkin entry.

Docs: new docs/gpg_trusted_signers.md with per-project websites, artifact naming/signature formats, signer tables, and evidence; cross-linked from gpg_tools.md and README. AGENTS.md gains a module↔docs consistency rule.

Tests

  • New: 14 unit tests (whitelist matching/ambiguity) + 16 view-level tests (trust matrix, pairing, status parsing) + 1 navigation flow test (Tools → GPG → File Ops → Verify Signature → BACK).
  • Full suite on this machine: 1446 passed / 135 skipped vs pristine-tree control 1415 passed / 135 skipped — the delta is exactly the 31 new tests; the only 2 failures (test_tools_screens.py button-hold timing) reproduce identically on the unmodified tree, i.e. pre-existing and unrelated.

ToolsGPGVerifyFileView now checks not just that a signature is cryptographically valid but who made it. Filenames are matched to projects and signer fingerprints to expected keys via the new gpg_trusted_projects module; a valid signature from a key not associated with the file's project (or an untracked key for a known project) raises a blocking warning before the success screen, which now shows the project name and full 40-char fingerprint(s). Multi-signature files pass if any signer is trusted. Detached signatures may use .sig or .asc; clearsigned files verify directly.

Key bundle: add Specter Signer 2026, Electrum felixb_f321x and svanstaa (from published release signature key IDs); remove stale Tails key (missing the EdDSA subkey current signatures use) and duplicate BitcoinCore Matthew Zipkin entry. Add docs/gpg_trusted_signers.md with per-project websites, artifact naming, signers, and evidence; cross-link from gpg_tools.md and README.
os.listdir order is filesystem-dependent; on Linux/macOS CI the data file was not first in the listing, so select_index=0 picked the .asc signature instead of the data file. Select by button label (order-independent) and add a regression test that forces signatures-first ordering.
test_diy_mount_status.py imported the shared test bootstrap as 'tests.base' (namespace-package form) instead of 'base'. That is a different module identity for the same file, so base.py executed twice in one process and reinstalled fresh MagicMocks into sys.modules on the second pass. Modules already imported (tools_screens, screen, keyboard...) kept constants from the first mock while later imports got the second's, breaking HardwareButtonsConstants identity checks: test_tools_screens button-hold tests failed only in full-suite context (and thus on CI), passing when run alone.
Audit of current releases (Aug 2026) found gaps in the trusted-signer list:

- Bitcoin Core v31.1 SHA256SUMS is signed by five keys not previously bundled: fanquake's second key, hebasto, benthecarman, marleo, and Sjors Provoost. Fetch each from a public keyserver with fingerprint verification.

- GnuPG 2.4.x/2.5.x releases are signed by Werner Koch and Niibe Yutaka; both keys were already bundled in GNUPG_ReleaseKeys.asc but missing from the whitelist, so every recent release triggered unknown-key warnings.

Docs: fix stale release URLs (Krux -> selfcustody/krux, Coldcard -> coldcard.com/downloads + clearsigned signatures.txt, Specter -> cryptoadvance org, Electrum -> download.electrum.org, Sparrow -> sparrowwallet/sparrow), document Krux's non-OpenPGP .sig limitation and Casa's pre-window signer.

Tests: session-scoped conftest fixture fails the run if tests/base.py is ever imported under two module identities (the double-import bug that broke test_tools_screens in full-suite CI runs); whitelist tests cover the seven new fingerprints and assert the new key files are bundled.
Gpg4Win installers and source archives (gpg4win-*) have been signed by the official GnuPG release keys since 2021 (verified: gpg4win-5.1.0.exe.sig is signed by Werner Koch's dist-signing key, already whitelisted). Add a ^gpg4win- filename pattern to the GnuPG project so Verify Signature attributes them correctly instead of showing a neutral unknown-project result.
@3rdIteration
3rdIteration merged commit 90bc21d into dev Aug 30, 2026
30 checks passed
@3rdIteration
3rdIteration deleted the gpg-trusted-signers branch August 30, 2026 21:41
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