Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates Part IV: code signing #36

lrettig opened this issue Nov 25, 2020 · 1 comment

Updates Part IV: code signing #36

lrettig opened this issue Nov 25, 2020 · 1 comment


Copy link

lrettig commented Nov 25, 2020

Regardless of how we ultimately decide to communicate and transmit upgrades to users, and the UX around downloading and installing updates (see #32, #33, #34), we'll need a scheme that allows the developers to sign those updates and users to validate the signature of an update for authenticity and integrity.

The very simplest option here would be to sign the binary release files for each respective platform using PKI already built into that platform, e.g., using Apple code signing (as we already do) for our macOS release. This has the advantage of not requiring any additional steps or infrastructure, but it has several significant downsides: it's totally inflexible as it allows the use of only a single set of credentials, a fixed PKI, and a proprietary signing tool (that isn't open source), it may not be easy to verify these signatures in our own software, it requires use of the official, OS-supported install tool (which likely requires administrator credentials), it may cost money to establish an identity, this infrastructure will vary from platform to platform, there is no easy way for the end user to verify the signatures manually, etc.

Note that, regardless of what ancillary code signing mechanism we ultimately choose, we'll additionally need to make use of the OS-specific code signing mechanism for platforms that require it, most notably macOS, but the two are not mutually exclusive and indeed are quite orthogonal for our purposes.

Design goals:

  • minimize the likelihood of an adversary successfully convincing users that an unauthorized release has been authorized (and, thus, installing a potentially malicious release), by forging a signature, modifying a signed release, or otherwise
  • single, multi-platform solution
  • independent, manual verifiability: an end user should be able to manually verify the signature(s) on a release using standard software
  • flexible key management: allow signing using a flexible M-of-N multisignature scheme (in case a single key is compromised), allow modification of M and N, and replacing signatures using the same tools
  • support for hardware signing


  • conceal the identity of the signers
  • conceal the number of signers
  • minimize the size of the signature


  • Spacemesh core infrastructure is already released using GitHub.
  • Many of the commits to our repositories are already signed and verifiable.
  • The list of developers with write access to our repositories is already visible.
  • All of these developers already have at least an SSH pubkey, if not also a GPG key, attached to their GitHub profile, and these pubkeys are publicly accessible using the GitHub API. Thus, we already have a robust PKI in place.
  • Our developers can migrate to SSH private keys stored on a hardware device such as a YubiKey if desired.
  • If an adversary were to compromise GitHub itself, we'd have bigger problems.

Proposal: We make use of GitHub PKI and sign releases using multiple of these existing, publicly verifiable keys. The signature that accompanies a release can be as simple as signing the checksum of the release file multiple times, e.g.:


We could optionally use something more sophisticated such as Schnorr signatures but this is probably unnecessary as it adds complexity and doesn't get us any closer to our design goals.

A release can be signed trivially by having two or more developers sign the checksum of the release binary once it's ready. This scheme is quite flexible and can support any number of signatures performed in any order.

An end user can verify the release by independently calculating the checksum, verifying that the public keys of the signers are valid, and verifying that the checksum has been correctly signed. Validity of the pubkeys in question can be ascertained in several ways: one or more of them can be "pinned" into the verification tool (a chain of trust could even be established in this way, such that previous keys could sign new ones), and/or the user can verify that they match the correct profiles on GitHub. A key can be revoked by removing it from a developer's GitHub profile.

Copy link

tal-m commented Nov 26, 2020

I think auto-update is crucial (in the initial phase of the network), but it's also a potential vulnerability that could have huge consequences if exploited, so it needs to be secured appropriately.

Using the platform code-signing API is potentially dangerous because it implicitly trusts the platform developers (e.g., Apple can generate their own "Spacemesh" certificate and sign it).

I'm also not sure about just having two developers sign the release to enable auto-update. I was thinking of something like 2-out-of-3 or 3-out-of-5 signing keys that are held in cold storage or on secure hardware devices.

In terms of the technical infrastructure, I think it's fine to use Github public key formats, so these keys can be published on Github. They probably shouldn't be one of the developer's regularly-used keys, however. (Also, the fact that the keys are also registered on Github shouldn't matter to our update verification code.)

We can even have the Github releases page as one of the update URLs. I don't think we should count on this as the only update source, however --- we don't want a Github crash (which isn't that rare, unfortunately) to prevent us from distributing an update).

I was thinking of having a list of several update URLs on different domains (so a single DNS server crash would also not affect operation), and serving the files from CDNs different cloud providers. The updates are static files, so this shouldn't be very difficult or expensive...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
None yet

No branches or pull requests

2 participants