Conveyor updates for July

It’s that time again! The Conveyor July release focuses on code signing improvements. It adds support for cloud code signing services, lets you change your signing identity, improves HSM compatibility and finally also improves the conformance of our generated Mac signatures. You can update in the usual manner, by starting the app GUI and clicking “Check for updates”, or on Linux using apt-get.

Code signing is an obscure topic for most developers, so we plan to do a series of blog posts over the coming months covering some of the less well known aspects. In this post we’ll cover the new support for signing services and identity changes.

Cloud signing services

In recent months some CAs have started offering cloud code signing services for Windows. With these services signing gets way easier. You don’t need to think about CSRs, HSMs, key files or any of that nonsense anymore. You just purchase a certificate via their online store, go through any ID verification needed and then put the resulting credentials in your conveyor.conf file. Conveyor now has integrated support for SSL.com’s eSigner service, DigiCert KeyLocker and the AWS Key Management Service. Please note though that Amazon isn’t a code signing CA, so you’ll have to purchase your certs separately if you use that and provide evidence that they keys are stored in a real HSM.

Here’s an example that takes eSigner credentials from environment variables:

app { 
  windows {
    signing-key {
      ssl-esigner {
        username = your-username
        password = ${env.ESIGNER_PASSWORD}
        totp-secret = ${env.ESIGNER_TOTP_SECRET}
      }
    }
    signing-key-alias = your-key-alias
  }
} 

The only downside of cloud signing is that if the CA has an outage you can’t release a new version of your app, and you can’t air-gap the keys. For use cases that demand the highest availability or security you may still want to buy the signing hardware, and Conveyor’s support for that isn’t going anywhere.

Why is this new feature important?

As code signing security improved malware authors started stealing signing keys from legitimate developers, brute forcing any passphrases that protected the files. As a consequence, starting from May 30th Microsoft requires that all signing keys must be held in hardware security modules. Previously this was a requirement only for Extended Validation certificates. At the same time, CAs have decided to start charging for these tokens separately. It can cost over $100 just for the token and then more money on top for the certificate itself.

Whilst the unit cost isn’t a big deal for a typical software project, the inconvenience can cost more. You have to wait for the USB dongle to be delivered through the mail, install vendor drivers and then point Conveyor at where they are. They may enforce 30 day passphrase rotation policies. If you rent CI workers you’re stuck because you can’t ask your cloud vendor to plug in special hardware. If the signing machine goes to sleep, the token may refuse access until it’s re-plugged. For some devices it’s even possible to break them if you make a mistake with the vendor tools! Moving to cloud signing eliminates these problems.

Changing your signing identity

Code signing does have one obvious downside: what if your identity changes? This is a bit like changing the domain name for a web app. You’d lose your site’s cookies, permissions and local storage if you did that. Code signing faces the same issue. Apple and the Microsoft Store have a solution for this - certificates include a stable organization identifier that isn’t derived from your legal name.

But when distributing outside the Microsoft Store, Windows certificates can change. This happens if your organization changes its name, but it can also occur if you change the location of your headquarters. That’s because company/people names aren’t globally unique, so signing identities include the name of the home jurisdiction. Even just switching to a new certificate authority can cause the name to change.

Because of this Microsoft added a “persistent identity” feature to Windows which lets you do identity migrations. Unfortunately, on close inspection this feature turned out to be unusable. For example, it requires Windows 11. It also doesn’t work if your old certificate has expired, but the moment you’re most likely to find out you have a new name in your certificate is when replacing the old one.

To address these problems we’ve developed an alternative. A new “escape hatch” mechanism changes your Windows packaging so that an asynchronous check against your download/update site is run in parallel to app launch. The metadata.properties file can instruct the install to download and run an arbitrary EXE. This lets you recover from any kind of broken update scenario and escape hatches are also a feature of other high-end update systems like Chrome’s.

How does it work?

When building your update site Conveyor records the signing identity in the metadata.properties file, which you should always make sure to upload along with the other files. During the next build it will download this file and check it. If your identity changed then Windows would stop updating your app in the background, because as far as it’s concerned there’s suddenly a totally different app from a different developer sitting at the same URL. To fix this Conveyor activates the escape hatch mechanism automatically, triggering a seamless uninstall/reinstall cycle and thus re-enabling updates. This works even if your old certificate has expired or been lost, and users don’t have to do anything.

The escape hatch changes your app’s startup sequence. To avoid compatibility issues it’ll be turned on only for configs that set the conveyor.compatibility-level key to 10 or above. We may turn it on by default for all apps in future.

If Conveyorized apps can download and run arbitrary code from their update server, does code signing still provide any security? The escape hatch certainly reduces the security you get by insisting on a consistent identity over time, but increases reliability by ensuring you can adapt to mistakes and unanticipated changes. In effect it changes the identity from a corporate ID to being the download site URL. You can pick whichever you think is more likely to change. Use cases that demand the highest security you can turn it off by setting app.windows.manifests.msix.use-update-escape-hatch to false. This would be appropriate for cases where you have a long term relationship with your CA and are unlikely to change your org name. For other cases we recommend you leave it enabled. If the site URL is backed by a simple static file server then it is relatively easy to protect and hard to hack, so it’s still easier to defend than a typical web origin.

In the long run we may switch to Microsoft’s official scheme for this, when Windows 10 support is no longer important or if they decide to backport support.

Better Mac signing

It’s not all about Windows! In this release we’ve rewritten the Mac signing code and now create signatures that are a closer match to Apple’s own tooling. This doesn’t resolve any reported issues because our previous code worked well, but it’s still good to eliminate differences no matter how tiny. The main change is that we’re now using the modern DER encoding for entitlements. Don’t worry if you don’t know what this means, just know that we’re keeping up with changes in the Apple ecosystem.

Other changes

We’ve improved compatibility with more types of private key file, and fixed a bug that could affect some types of YubiKey when used on Windows. Self-signing certificates are now exported when using conveyor keys export

But this release isn’t only about code signing:

  • If you use conveyor generate to create a project using an io.github reverse DNS name, the created project will be set up to use GitHub Releases and Pages, configured as an open source project (so Conveyor can be used for free), and then checked into a new local git repository automatically. You just have to create the repository via the GitHub UI and do a git push.
  • You can now control which Debian or Ubuntu base distribution is used to determine package dependencies.
  • We documented what names can be changed post-launch and what can’t.
  • Commercial users can now remove the “Packaged with Conveyor” badge from your download page by setting a config key.
  • We fixed bugs that could occur on Windows when your username contains spaces.

Share and enjoy!

.