git / moonbite-network / docs/SIGNING-AND-NOTARISATION.md · raw

# Code signing and notarisation for MoonBite releasesStatus: playbook, 2026-10-10. Companion to `deploy/RELEASE-SIGNING.md` (theminisign machinery already wired into the publish scripts), `docs/AV-FALSE-POSITIVE-PLAYBOOK.md`(what to do when scanners flag the miner), `docs/REPRODUCIBLE-BUILDS.md`,`release/miner/ANTIVIRUS.md`, and the verifier scripts`scripts/release/verify-release.sh` / `scripts/release/Verify-Release.ps1`.MoonBite Labs publishes a CPU RandomX miner, a node (`moonbited`) and a desktopwallet. The operator is pseudonymous. Every platform's "trusted publisher"system ties trust to a verified legal identity, so this document separates**what a pseudonymous publisher can do today** from **what needs a legalentity**, with the current rules and prices cited.This is factual background, not legal or tax advice. Forming an entity hasjurisdiction-specific consequences; check them before acting.---## 1. Windows: Authenticode### 1.1 What Authenticode buys and what it does notA signed PE file lets Windows show a **publisher name** instead of "Unknownpublisher", and lets SmartScreen attach reputation to the certificate insteadof to each file hash. It does **not** make a file trusted on day one, and itdoes **not** stop antivirus engines classifying a miner as `PUA` / `CoinMiner`(see the AV playbook). Microsoft's own guidance, updated May 2026:- SmartScreen evaluates two signals: publisher reputation (is it signed, by a  known certificate?) and file-hash reputation (has this exact file been  downloaded without signs of malice?). "Even when signed, a newly created  binary could still show a SmartScreen warning until its hash or publisher  certificate accumulates sufficient evidence of positive reputation."- Unsigned files start from zero reputation on every release. Signed files let  reputation carry across versions "signed using the same publisher identity".- **EV certificates no longer bypass SmartScreen.** Microsoft: "Paying a  premium for EV solely to avoid SmartScreen warnings is no longer justified."- There is "no need (or mechanism) to manually submit a file for SmartScreen  reputation review for consumer endpoints. Reputation builds organically  through download volume" - "several weeks and hundreds of clean installs".- Do not sign PUA-like software: the certificate "may develop negative  reputation". For a miner this is a real risk, which is why build hygiene  (no persistence, no silent install, clear UI) matters before signing.Source: https://learn.microsoft.com/en-us/windows/apps/package-and-deploy/smartscreen-reputation### 1.2 Certificate routes and their identity requirements| Route | Identity required | Key storage | Cost (indicative, 2026) | Pseudonymous operator? ||---|---|---|---|---|| OV code-signing cert from a public CA (Sectigo, DigiCert, SSL.com, Certum, GlobalSign) | Organisation validation: registered legal entity, verifiable address and phone; some CAs sell OV to **individuals** against a government photo ID (name appears as publisher) | Since **1 June 2023** the CA/Browser Forum requires the private key on FIPS 140-2 L2 / CC EAL4+ hardware (USB token or cloud HSM) for **both OV and EV** | roughly USD 65-440 per year depending on CA; token or cloud-HSM fee often extra | No. Publisher field = legal name of entity or person || EV code-signing cert | Stricter organisation vetting (legal existence, operational history, signed agreement); not issued to individuals | Hardware as above | typically USD 250-700 per year | No. And no SmartScreen head-start any more || Azure **Artifact Signing** (renamed from Trusted Signing, Jan 2026) | Microsoft identity validation. Public Trust certs: organisations in US, Canada, EU, UK, Australia, New Zealand, Japan, South Korea, Singapore, Switzerland, Norway, Israel; **individual developers only in US or Canada**, validated via government photo ID + selfie (AU10TIX / Entra Verified ID) with legal name and address taken from the Azure billing account. During the 2025 preview Microsoft additionally required "3 years or more of verifiable history" for organisations; the current quickstart no longer states that, but expect public-record checks (business registration, domain invoice) | Cloud HSM, keys never leave Azure; short-lived certs; integrates with signtool and GitHub Actions | from USD 9.99 per month (Basic) | No. Certificate subject is the validated legal name || **SignPath Foundation** (free OSS signing) | No personal ID check in the usual CA sense, but: OSI licence with no commercial dual-licensing, team must own and maintain the repo, MFA for all members, defined author/reviewer/approver roles, manual approval per release, an initial "project reputation and control" check, and SignPath "decides whether to accept or reject". **Publisher name on the certificate is "SignPath Foundation", not the project.** Terms exclude malware and "potentially unwanted programs"; cryptominers are not named, but a miner is commonly classified as PUA, so acceptance is uncertain | SignPath HSM | free | **Partly.** Maintainer need not disclose a legal name, but acceptance for a miner is not assured; apply at https://signpath.org/apply.html || Self-signed certificate | none | any | free | Yes, but Microsoft: "Same behavior as no signature". Useless for trust || Microsoft Store | Partner Center account (individual or company; identity and payment verification) | Microsoft re-signs | USD 19 individual / 99 company one-off (historic figures; check Partner Center) | No for pseudonymity; and a background CPU miner is unlikely to pass Store policy |Sources:- CA/B Forum June 2023 key-protection change: https://venafi.com/blog/new-ca-b-forum-requirements-for-code-signing-start-in-june-will-you-be-ready and https://www.encryptionconsulting.com/understanding-the-ca-browser-forum-code-signing-requirements/- Azure Artifact Signing quickstart (eligibility note, individual validation flow): https://learn.microsoft.com/en-us/azure/trusted-signing/quickstart (canonical: https://learn.microsoft.com/en-us/azure/artifact-signing/quickstart)- April 2025 restriction announcement (3-year history): https://techcommunity.microsoft.com/blog/microsoftsecurityandcompliance/-/4273554- Artifact Signing pricing: https://azure.microsoft.com/pricing/details/artifact-signing/- SignPath Foundation terms: https://signpath.org/terms- Indicative OV pricing (reseller pages, verify before buying): https://sslinsights.com/digicert-vs-sectigo-code-signing/ and https://gabrielmoraru.com/obtaining-cheap-ev-ov-certificates-singing-your-application/### 1.3 Practical reading for MoonBiteNothing on Windows gives a pseudonymous publisher a trusted-publisher string.The realistic Windows options are, in order:1. Ship unsigned but **verifiable** (SHA-256 + minisign + GitHub attestation,   section 4), be explicit on the download page that SmartScreen will say   "Unknown publisher", and let hash reputation build per release.2. Apply to **SignPath Foundation**. If accepted, Windows shows "SignPath   Foundation" as publisher and reputation accrues to that certificate. Be   candid in the application that the product is a CPU miner that only runs   when the user starts it, with no persistence.3. Form an entity (section 5) and use **Azure Artifact Signing** (cheapest   managed route, no hardware token) or an OV certificate from a public CA.---## 2. macOS: Developer ID and notarisation- Since macOS 10.15, software distributed outside the App Store must be signed  with a **Developer ID Application** certificate and **notarised** or Gatekeeper  blocks it with "cannot be opened because the developer cannot be verified".  Users can bypass this (right-click Open, or `xattr -dr com.apple.quarantine`,  which `/mine` already documents), but every bypass is friction and a support cost.- Developer ID certificates come only from the **Apple Developer Program**,  USD 99 per year. Enrolment is as an **individual** (government photo ID  verification, legal name becomes the signing identity) or as an  **organisation** (must be a legal entity - "DBAs, fictitious businesses,  trade names, and branches are not accepted" - with a **D-U-N-S number**  registered to that entity, and the enroller must have authority to bind it).  Forum reports through 2026 show individual ID verification can stall for weeks.- Notarisation itself is automated: `xcrun notarytool submit --apple-id ... --team-id ...  --password <app-specific-password>` (or an App Store Connect API key for CI),  then `xcrun stapler staple`. Hardened Runtime and a secure timestamp are  required. Notarisation is a malware scan, not a review; a CPU miner is not  automatically rejected, but Apple can revoke a Developer ID later.- The name on the certificate is the enrolled legal name or organisation.  There is no anonymous Developer ID.Sources:- Apple enrolment (individual vs organisation): https://developer.apple.com/support/compare-memberships/- D-U-N-S requirement: https://developer.apple.com/support/D-U-N-S/- Notarisation requirements and tooling (third-party summary): https://www.electron.build/docs/notarization- Whether CLI tools need notarising (background): https://eclecticlight.co/2023/02/17/should-apps-and-command-tools-be-notarized/Practical reading: macOS signing requires either the operator's real name or anentity. Until one exists, ship macOS tarballs unsigned, keep thequarantine-removal instructions, and make the SHA-256 / minisign check theprimary trust step.---## 3. LinuxLinux has no platform gatekeeper. Trust comes from:- **Checksums + a detached signature.** MoonBite uses **minisign** (Ed25519,  single small key, no web of trust). GPG is the distro convention but has a  larger key-management surface; minisign is what `deploy/publish-node-binaries.sh`  already calls. Runbook in section 6.- **Sigstore / cosign keyless** signing: `cosign sign-blob --bundle <file>.sigstore.json <file>`  binds the artefact to an OIDC identity (for GitHub Actions, the workflow  identity `https://moonbite.org/git/moonbite-network<name>.yml@refs/tags/<tag>`),  recorded in the public Rekor transparency log. Verification must pin the  identity: `cosign verify-blob --bundle <file>.sigstore.json --certificate-identity <workflow-id> --certificate-oidc-issuer https://token.actions.githubusercontent.com <file>`.- **GitHub artifact attestations**: `actions/attest-build-provenance` in the  release workflow produces a SLSA provenance attestation stored by GitHub;  anyone verifies with `gh attestation verify <file> --repo moonbitecoin/moonbite-network`  (`--owner moonbitecoin` is looser; `--repo` is preferred). This proves "built by  this repository's CI from this commit", which is exactly the claim a  pseudonymous project can make honestly.- **Reproducible builds** (`docs/REPRODUCIBLE-BUILDS.md`): anyone rebuilding the  tagged commit gets the same hash, so independent parties can confirm the  release without trusting the signer at all.Sources:- `gh attestation verify` manual: https://cli.github.com/manual/gh_attestation_verify- cosign keyless concepts and pinning (beginner guide): https://code.mendhak.com/understanding-sigstore-cosign-as-a-beginner/- minisign: https://jedisct1.github.io/minisign/---## 4. Decision matrix for a pseudonymous operator| Capability | Possible today without a legal identity | Requires a legal entity (or real-name individual enrolment) ||---|---|---|| SHA-256 manifest for every release (`SHA256SUMS.txt`) | Yes | - || minisign signature on the manifest (`SHA256SUMS.txt.minisig`), public key published in repo, site and DNS | Yes | - || GitHub build-provenance attestation + `gh attestation verify` | Yes (needs the release built in GitHub Actions, not on a laptop) | - || Sigstore cosign keyless bundle per artefact | Yes (identity = the CI workflow, not a person) | - || Reproducible build instructions and third-party rebuild confirmations | Yes | - || VirusTotal pre-scan + vendor false-positive submissions (AV playbook) | Yes (submissions accept any contact email) | - || Windows publisher name instead of "Unknown publisher" | Only via SignPath Foundation (publisher shows "SignPath Foundation"; acceptance for a miner not assured) | OV cert or Azure Artifact Signing in the entity's name || SmartScreen reputation carrying across releases | No (unsigned: resets per hash) | Yes, once signed consistently || macOS Developer ID + notarisation (no Gatekeeper warning) | No | Yes: Apple Developer Program, USD 99/yr, individual (real name) or organisation (D-U-N-S) || Microsoft Store / Mac App Store listing | No | Yes, and Store policy may still reject a miner |### 4.1 Entity routes commonly used by small software publishersFactual summary only; costs and disclosure rules change and differ byjurisdiction. The point of an entity here is that the **entity** is thepublisher of record on the certificate, while the operator's name appears onlyin registry filings (public in some jurisdictions, private or agent-shielded inothers).- **US single-member LLC** (commonly Wyoming, New Mexico, Delaware). Formation  roughly USD 50-300 plus a registered agent (roughly USD 50-150/yr). Some  states do not publish member names; a registered agent provides the public  address. An EIN is free from the IRS. Needed for: OV cert, Azure Artifact  Signing (US-based organisation; new entities may face the "verifiable  history" bar), Apple organisation enrolment (needs a D-U-N-S number, free  from Dun and Bradstreet, up to 5 business days).- **UK Ltd**: Companies House incorporation GBP 50; director names and a  service address are public; a correspondence address can be used instead of  home. Eligible for Azure Artifact Signing (UK is listed) and OV certs.- **EU single-member company** (for example Estonian OU via e-Residency):  EU is in the Artifact Signing list; registry data is public.- Beneficial-ownership reporting regimes (US CTA as currently applied, UK PSC  register, EU UBO registers) may require filing the owner's identity with the  state even where the public registry does not show it.The cheapest working stack once an entity exists is: entity + domain in theentity's name + Azure Artifact Signing (USD 9.99/mo, no token) for Windows, andApple Developer Program (USD 99/yr) for macOS. Total under USD 300/yr beforeformation costs.---## 5. What MoonBite does now (policy)1. Every release is built by GitHub Actions from a signed tag, with   `actions/attest-build-provenance` enabled.2. Every release ships `SHA256SUMS.txt` and `SHA256SUMS.txt.minisig`.3. The minisign public key is published in three independent places (section 6.5).4. The download pages state plainly that Windows and macOS builds are unsigned,   what the OS will say, and how to verify instead.5. The wallet never bundles the miner; the website never mines in the browser.   This keeps the wallet's own reputation clean and gives AV vendors a narrow,   honest story for the miner.6. If SignPath Foundation accepts the project, Windows miner and wallet builds   are signed there. If an entity is formed later, switch to Artifact Signing   and Developer ID and announce the publisher name on the site and in an ADR.---## 6. RunbooksAll commands are POSIX shell; on Windows use Git Bash or WSL. The key filenames match `deploy/RELEASE-SIGNING.md` and `deploy/publish-node-binaries.sh`.### 6.1 Generate the minisign key (offline, air-gapped, two copies)Do this once, on a machine that is not connected to any network and will notbe again until the key material is off it.1. Prepare the offline machine: a live Linux USB (for example Tails or a plain   Debian live image) on a laptop with Wi-Fi disabled in firmware or the card   removed; no Ethernet cable. Bring `minisign` in as a static binary you   verified on an online machine (`sha256sum` against the project release page   https://github.com/jedisct1/minisign/releases) on a freshly formatted USB stick.2. Generate:   ```sh   mkdir -p /tmp/mb-key && cd /tmp/mb-key   minisign -G -p moonbite-release.pub -s moonbite-release.key   # choose a long passphrase; it is what protects the key at rest   cat moonbite-release.pub   # untrusted comment: minisign public key XXXXXXXXXXXXXXXX   # RWQ...                                   <- this line is the public key   ```3. Record the **key ID** (the hex after "public key") and the full `RWQ...`   line by hand on paper. Also sign a test file and verify it before leaving   the room:   ```sh   echo moonbite > t && minisign -Sm t -s moonbite-release.key && minisign -Vm t -p moonbite-release.pub   ```4. Make **two** copies of `moonbite-release.key` on two separate, new,   encrypted USB sticks (LUKS or VeraCrypt, different passphrase from the key   passphrase). Label them A and B. Store them in two different physical   locations. Store the passphrases separately from the sticks (paper in a   sealed envelope, or a password manager that is itself backed up offline).5. Copy only `moonbite-release.pub` to the online world. Wipe `/tmp/mb-key`   (live images lose it on reboot; reboot anyway). Never let   `moonbite-release.key` touch a networked disk, a cloud sync folder, a   screenshot, or a chat.6. Confirm `*.key` is git-ignored: `git check-ignore -v moonbite-release.key`.For day-to-day signing, you may keep **one** working copy of the key on anencrypted volume on the release machine (the signing step in`deploy/publish-node-binaries.sh` expects it there). If that machine is eversuspected compromised, rotate (6.4).### 6.2 Sign a releasePrerequisites: the GitHub Actions release workflow has produced the artefactsand attestations; you have downloaded them to a clean directory.```shcd release-vX.Y.Z/# 1. Independent re-hash. Must match what CI printed in the workflow log.sha256sum moonbite-miner-*.tar.gz moonbite-miner-*.zip moonbite-wallet*.exe > SHA256SUMS.txtdiff <(sort SHA256SUMS.txt) <(sort SHA256SUMS.ci.txt)      # CI's copy; must be empty# 2. Provenance check before you put your signature on it.for f in moonbite-miner-*.tar.gz moonbite-miner-*.zip moonbite-wallet*.exe; do  gh attestation verify "$f" --repo moonbitecoin/moonbite-network || exit 1done# 3. Sign the manifest (trusted comment is signed; include version and date).minisign -Sm SHA256SUMS.txt -s /path/to/moonbite-release.key \  -t "MoonBite release vX.Y.Z $(date -u +%F) https://moonbite.org/mine"# 4. Verify with the PUBLISHED key, not the local file.curl -fsSL https://moonbite.org/.well-known/moonbite-release.pub -o pub.verifyminisign -Vm SHA256SUMS.txt -p pub.verify# 5. Attach to the GitHub release and stage on the site.gh release upload vX.Y.Z SHA256SUMS.txt SHA256SUMS.txt.minisig```Then run `scripts/release/verify-release.sh vX.Y.Z` (and`Verify-Release.ps1` on a Windows VM) exactly as a user would, from a machinethat never saw the private key. Only after that passes do the download buttonson `/mine` and `/get-wallet` go live (`build-windows-bundle.py --stage`refuses to stage an unsigned bundle once a key is configured).### 6.3 Verify (what users run)```sh# Linux / macOSsha256sum -c SHA256SUMS.txt --ignore-missing          # shasum -a 256 -c on macOSminisign -Vm SHA256SUMS.txt -P 'RWQ...'               # public key from the site, repo and DNSgh attestation verify moonbite-miner-linux-x86_64.tar.gz --repo moonbitecoin/moonbite-network``````powershell# WindowsGet-FileHash .\moonbite-miner-windows-x86_64.zip -Algorithm SHA256minisign -Vm SHA256SUMS.txt -P 'RWQ...'gh attestation verify .\moonbite-miner-windows-x86_64.zip --repo moonbitecoin/moonbite-network```### 6.4 Rotate the keyminisign has no revocation. Rotation is announcement plus overlap.1. Generate the new key with the 6.1 ceremony. Note the new key ID.2. Sign a **rotation statement** `KEY-ROTATION-<date>.txt` ("MoonBite release   key <oldID> is retired as of <date>; new key <newID> is `RWQ...`; reason:   scheduled / suspected compromise") with **both** keys (two `.minisig`   files) if the old key is still trusted, or with the new key only if it is   not. Commit it to the repo, attach it to a GitHub release, and link it from   `/mine`.3. Update the public key in all three publication places (6.5) in one change,   and in `deploy/moonbite-release.pub` and the `RELEASE_PUBKEY=` line in   `deploy/setup-seed2.sh` (grep `RELEASE_PUBKEY`).4. Re-sign the current release's `SHA256SUMS.txt` with the new key so the   latest download verifies against the current key.5. On compromise: additionally post on every channel the project uses, open a   GitHub Security Advisory, and treat every artefact signed after the   suspected compromise date as untrusted until rebuilt and re-signed.6. Destroy the old key (both sticks) only after the overlap period (suggest 90   days) so historic releases can still be cross-checked.### 6.5 Publish the public key in three placesUsers should be able to fetch the key from three independent trust roots andcompare. Publish the identical `RWQ...` line:1. **Repository**: `deploy/moonbite-release.pub` and the top-level `README.md`   under "Verify a download", at   https://moonbite.org/git/moonbite-network/file/deploy/moonbite-release.pub.html.   Commit with a signed git tag so the history is auditable.2. **Website**: served as a plain text file at   `https://moonbite.org/.well-known/moonbite-release.pub` (static file;   add to `static/` or nginx) and printed inline on `/mine` in the   "Antivirus warnings and how to verify" section.3. **DNS TXT**: a record on the project domain, for example   ```   _moonbite-release.moonbite.org.  TXT  "v=minisign1; keyid=<hex>; key=RWQ..."   ```   Check with `dig +short TXT _moonbite-release.moonbite.org`. Enable DNSSEC on   the zone if the registrar supports it so the record itself is signed.Mention the key fingerprint (key ID) in release notes and in the signed trustedcomment so a user who already has one copy can cross-check the others.---## 7. Open items for the operator- Decide whether to apply to SignPath Foundation (free, no real name on the  certificate, acceptance uncertain for a miner).- Decide whether and where to form an entity; until then macOS and Windows  stay unsigned and the site says so.- Complete the key ceremony in 6.1 (the placeholder in  `deploy/moonbite-release.pub` is still `REPLACE_ME`).- Add the `.well-known` static file and the DNS TXT record.