Date: 2026-08-04 Status: verified
Is the GitHub alias switck (github.com/switck/libngu) actually doc-hex
(Peter D. Gray, Coinkite/Coldcard), on the basis of GPG signatures over git commits?
Yes — cryptographically proven. 58 commits authored as
Switck <69336248+switck@users.noreply.github.com> carry valid GPG signatures
made with doc-hex's personal key, the same key that signs doc-hex's
Peter D. Gray <peter@conalgo.com> commits in the same repo, interleaved in
time. The switck GitHub account has no GPG key of its own.
doc-hex's GitHub-published keyring (https://github.com/doc-hex.gpg) contains exactly one primary key:
- Primary:
A2DCD558C2BE5D7C(rsa2048, created 2013-05-28, expired 2023-05-28), fingerprintA004 C9BC E217 ABE9 341C D81A A2DC D558 C2BE 5D7C- UID:
Peter D. Gray (Personal) <peter@conalgo.com> - UID:
Peter Gray <peter@ripeapps.com>
- UID:
- Signing subkey:
F0E6CC6AFC16CF7B(rsa2048, same dates)
switck's GitHub keyring (https://github.com/switck.gpg) is empty
("This user hasn't uploaded any GPG keys"). GitHub therefore shows switck's
signed commits as unverifiable/unattributed — but the signatures are in the
git objects and verify fine against doc-hex's public key.
Verified with git verify-commit against an isolated keyring holding
doc-hex's, scgbckbone's, and GitHub web-flow's public keys:
| Signing key | Key belongs to | Commit author identity | Count | Result |
|---|---|---|---|---|
F0E6CC6AFC16CF7B |
doc-hex (subkey) | Switck | 56 | valid sig (key expired) |
A2DCD558C2BE5D7C |
doc-hex (primary, used directly) | Switck | 2 | valid sig (key expired) |
F0E6CC6AFC16CF7B |
doc-hex (subkey) | Peter D. Gray | 19 | valid sig (key expired) |
4AEE18F83AFDEB23 |
GitHub web-flow (web UI merges) | Switck | 8 | valid (GitHub-signed, uninformative) |
B5690EEEBB952194 |
GitHub web key | scgbckbone | 1 | valid (GitHub-signed, uninformative) |
A940F7604E73741B |
scgbckbone (scaag <scgbckbone@proton.me>) |
scgbckbone | 1 | valid |
58 Switck-authored commits are signed by doc-hex's personal key (56 via the
signing subkey, 2 — 999bdb41, f7711c5, 2024-03-30 — by the primary key
directly, i.e. he signed with the master key itself). Example verification:
$ git verify-commit 28aa2927d5f7
gpg: Signature made Thu 29 Sep 2022 09:31:09 AM EDT
gpg: using RSA key D9766C79E77B0198D66975BDF0E6CC6AFC16CF7B
gpg: Good signature from "Peter D. Gray (Personal) <peter@conalgo.com>" [expired]
$ git log -1 --format='%an <%ae>' 28aa2927d5f7
Switck <69336248+switck@users.noreply.github.com>
(The key's 2023-05-28 expiry is why a bare git log shows status E and why
git verify-commit exits non-zero; the signatures are cryptographically good —
gpg reports Good signature — and only the private-key holder could produce
them, including the two 2024 commits signed after expiry.)
Commits signed by subkey F0E6CC6AFC16CF7B, grouped by month:
Switck 2020-10 (14) <- repo created 2020-10-15, "Initial commit" d4922f6
Switck 2021-01 (15)
Peter D. Gray 2021-02 (5)
Switck 2021-02 (23) <- same key, same month, both names
Peter D. Gray 2021-03 (6)
Peter D. Gray 2021-07 (3)
Peter D. Gray 2021-09 (3)
Peter D. Gray 2021-10 (1)
Peter D. Gray 2022-03 (1)
Switck 2022-09 (4)
Both names were used interchangeably, signed by one key, within the same weeks.
- Coldcard production firmware depends on switck/libngu:
Coldcard/firmwaremaster.gitmodulespullsexternal/libngufromhttps://github.com/switck/libngu.git. Coinkite ships hardware wallets whose crypto library lives under the switck account. https://github.com/Coldcard/firmware/blob/master/.gitmodules - doc-hex == Coinkite == Peter D. Gray: GitHub profile lists "Coinkite
Inc.", coinkite.com, Toronto; key UID is
peter@conalgo.com. doc-hex's older accountpeter-conalgoappears in old Coldcard submodule URLs (peter-conalgo/trezor-cryptoin switck/firmware's.gitmodules). https://github.com/doc-hex - doc-hex maintains switck/libngu in public: opens issues ("AES is slow"
#12), answers issues as maintainer (#8: "I'll see if I can fix this import
issues and give a PR"), pushes PR commits that
switckmerges (PR #17, "switck merged 4 commits ... doc-hex added 4 commits"). switck/libngu#12, switck/libngu#17 - switck account profile: created 2020-08-07 (user id 69336248), name
"Switck", company "NaN", location "Cyberspace", bio
mx@switck.com; 5 repos: forks of Coldcard/firmware, Coldcard-adjacent bech32 + micropython, plus two originals (libngu, pandora-shar). The account exists solely inside the Coldcard/Coinkite ecosystem. https://api.github.com/users/switck - Merge commit
f7711c5(signed by doc-hex primary key) message: "Merge branch 'master' of git-switck:switck/libngu" — the local ssh remote alias on the signing machine is namedgit-switck, i.e. one person operating the switck remote from doc-hex's key-holding machine. - Third-party write-up treats switck/libngu as a Coldcard project component: Wizardsardine's Coldcard RNG-vuln analysis: "Three public repositories are involved: the firmware itself, Coldcard/firmware; the cryptographic library it calls into, switck/libngu; and the MicroPython fork it runs on, Coldcard/micropython." https://wizardsardine.com/blog/coldcard-rng-vulnerability/
scgbckbone <scgbckbone@proton.me>— separate, real contributor (own keyA940F7604E73741B, uid "scaag"). All recent commits (2023–2026, e.g.cf1988a2026-05-25, the anchor in the URL under analysis) are authored by scgbckbone and unsigned; committer isSwitckvia GitHub noreply, i.e. rebases/merges done through the switck account. Not part of the identity question.avirgovi <avirgovi@cisco.com>— 2 unsigned commits, 2022-04. Unrelated.
- Rebase artifact ("doc-hex merely rebased/re-signed a real switck's
commits"): ruled out on mechanism + four empirical tests (2026-08-04):
- Mechanism: a commit signature covers the whole commit object (tree,
parents, author, committer, timestamps, message). Rebase changes
parents/committer/time → old signatures are destroyed, never carried
over;
rebase --gpg-signre-signs with the rebaser's key at rebase time. Signatures cannot "travel" across a rebase. - Committer field: rebase rewrites committer to the rebaser's configured
identity. All 58 signed Switck commits have committer =
Switck <69336248+switck@users.noreply.github.com>, never Peter D. Gray. For doc-hex to have produced these by rebasing, his git would have to be configured as Switck — which is the alias itself, not an alternative to it. - Author-date vs commit-date: rebase preserves author date and stamps a new commit date. All 77 doc-hex-key-signed commits (58 Switck + 19 Peter) have author timestamp == commit timestamp (delta 0s for 76/77, 34s for one amend). No rebase happened on any signed commit.
- Signature timestamps: GPG signature time == commit time to the second on all sampled commits spanning 2020-10-15 → 2024-03-30 (e.g. d4922f6 both 2020-10-15 09:34:17 -0400; f7711c5 commit 12:05:23, sig 12:05:26). A batch re-sign at rebase time would cluster all sig timestamps at one moment; instead each sig is contemporaneous with its own commit across 3.5 years.
- Internal contrast set: the repo contains real rebases — 29/34 unsigned scgbckbone-authored commits (committer=Switck) have author/commit date gaps >1h (up to 8 months, e.g. 65343de authored 2025-07-11, committed 2026-03-12) — and they are UNSIGNED. History shows what rebasing looks like in this repo; the signed Switck commits match none of it.
- No patch-id duplicates among all 123 commits (no re-signing-batch residue). Residual escape hatch ("doc-hex rebased a real switck's work while impersonating the switck identity and re-signing each commit within seconds of its original author date, for 4 years") is self-erasing: it requires doc-hex to operate the switck identity continuously, which is the conclusion, and it explains the data less simply.
- Mechanism: a commit signature covers the whole commit object (tree,
parents, author, committer, timestamps, message). Rebase changes
parents/committer/time → old signatures are destroyed, never carried
over;
- Key sharing between two people: doc-hex could theoretically have given another person his private key. Nothing supports this: the key UID is personal ("Peter D. Gray (Personal)"), it is the only key on doc-hex's GitHub account since long before switck existed, switck published no key of its own, and the repo is production infrastructure for doc-hex's employer's flagship product. Occam: one person, two aliases.
- Forged signatures: infeasible — signatures verify against a key published on doc-hex's GitHub since before the switck account was created; forging would require the private key (which collapses to the key-sharing case).
- Why the alias exists at all (inference, not sourced): libngu is Coldcard's crypto library; hosting it under a pseudonymous personal account rather than the Coldcard org keeps it at arm's length from the corporate brand while the same developer (Gray) maintains it. Motive is speculation; identity is not.
git clone https://github.com/switck/libngu && cd libngu
export GNUPGHOME=$(mktemp -d)
curl -sL https://github.com/doc-hex.gpg | gpg --import
git log --format='%H|%an|%ae|%G?|%GK' # census
git verify-commit 28aa2927d5f7208c5e124d141f4a85e0425ac9e3 # Switck-authored, doc-hex key
git verify-commit f7711c5522f432e9827fabe3c5c1366068485cac # Switck-authored, doc-hex PRIMARY key
curl -s https://github.com/switck.gpg # "hasn't uploaded any GPG keys"Note: git verify-commit exits non-zero on these because the key is expired
(gpg EXPKEYSIG); check for "Good signature" in output rather than exit code.
- https://github.com/switck/libngu — repo under analysis (commit graph, signatures)
- https://github.com/doc-hex.gpg — doc-hex's published key: primary A2DCD558C2BE5D7C + subkey F0E6CC6AFC16CF7B, UID Peter D. Gray peter@conalgo.com
- https://github.com/switck.gpg — empty keyring for switck
- https://api.github.com/users/switck — account created 2020-08-07, id 69336248
- https://api.github.com/users/doc-hex — "Coinkite Inc.", coinkite.com, Toronto
- https://github.com/Coldcard/firmware/blob/master/.gitmodules — production submodule → switck/libngu
- switck/libngu#12, switck/libngu#8, switck/libngu#17 — doc-hex acting as libngu maintainer
- https://wizardsardine.com/blog/coldcard-rng-vulnerability/ — third party treats switck/libngu as Coldcard's crypto library
- switck.com domain registration history (bio: mx@switck.com) — likely privacy-shielded; not checked.
- Whether the same doc-hex key signs commits in
switck/pandora-shar(other original switck repo) — not checked here. - Wayback Machine history of libngu's repo home (was it ever under doc-hex/ or coinkite/?
doc-hex/libngucurrently 404s). - Search divergence note: Kagi surfaced GitHub-internal pages (issues/PRs); Yandex surfaced the Wizardsardine analysis + noise. No substantive disagreement between engines on this topic.
Great investigation.
This is pretty damning evidence. Coinkite says (ref: https://blog.coinkite.com/entropy-technical-backgrounder/):
This is BS. Claude found the entropy issue with libngu in less than a minute.
Clearly Peter Gray is the same person as switck. Now the question is if nvk knew.