Code signing for the concerned: 1 Why?

Even in Mojave, there’s no requirement that apps or other code bundles are signed, and many on your Mac still aren’t. Signing can be required for certain features, such as access to Keychains, and negotiating privacy protection enforced by TCC. Most importantly, signing may allow an app to be launched when it is run through Gatekeeper’s full checks.

Apple has stated its intention, at some time in the future, to require that all apps obtained and installed from external sources have either been delivered by its App Store, or have undergone notarization by Apple to check for malware. It hasn’t said when that will apply, nor has it explained how this might affect those who develop their own script apps, or build open source software for themselves.

There’s a lot of confusion about code signing, when it’s required, and what it does. In this and the next few articles, I’m going to try to clear that up so that you know how it applies to you, and those who provide your software. This is a complex area which isn’t always clearly documented. Apple’s last detailed guides, listed in the references below, haven’t been updated since 2016 (Sierra) either. If I have got something confused or wrong, please tell me in a comment so that I can correct it.

Why sign an app or code bundle?

Although code signatures provide verification of the integrity of a code bundle, which can be useful in itself, the primary purpose of a signature is to satisfy the designated requirements of a sub-system within macOS. The most obvious example, and the one of which we are most aware, is the thorough Gatekeeper check which apps undergo after they have been downloaded and are being run for the first time.

Code signatures on bundles are also checked for many other reasons. Most recently, these determine whether an app can be granted access to protected locations and services which are private, a function of TCC. Apps which run in a sandbox also rely on their signature to access facilities according to their entitlements.

Given that apps distributed through the App Store are required to run in a sandbox and may use entitlements extensively, they are clearly heavily reliant on their code signature to make all that work. Apps which are notarized are similarly marked as being different, by being ‘hardened’. This is different from a sandbox, and enforced by the SIP mechanism, which is detailed in this article by Jeff Johnson. As he writes there, “both sandboxing and hardening rely on code signing entitlements.”

So now and in the future, if you want your app to run in a sandbox or to be notarized, then code signing is mandatory. But what if you just want to use an app yourself, or pass it on to a few friends, and aren’t interested in sandboxing or notarization?

Until Apple gives us further details of how things will change in the future, for personal use there is little value in signing apps or code bundles unless your code requires access to a sub-system which needs code signatures. In those cases, you’ll need to follow the rules for that sub-system’s checks – which is generally unusual for non-commercial code.

What about Gatekeeper?

Gatekeeper only performs thorough checks on code signatures the first time that you open an app, and only when the quarantine flag is set on that app. If you build the app locally and don’t distribute it via an online site, then the quarantine flag won’t be set, and that thorough check will never be performed. You might be caught out, though, when copying the app to other Macs: for example, moving it by AirDrop is likely to set the quarantine flag, but copying it over local file sharing won’t.

So almost all the circumstances in which someone might think about using techniques such as self-signing an app, they are very unlikely to be needed to satisfy Gatekeeper checks (something which self-signing doesn’t do anyway). If you want to distribute your app via a website or similar, then you really must go through the process of signing up as a developer with Apple and using a Developer ID to sign your apps properly.

This doesn’t apply to apps which are supplied unbuilt, as source code. You can’t sign source or ‘pre-sign’ it in any way that will help those who build it for themselves. As far as Gatekeeper is concerned, locally-built apps won’t have a quarantine flag, and won’t get thoroughly checked.

Ad hoc signing

You’ll come across ad hoc signing on various websites, but it’s hardly mentioned by Apple. This is because some users feel that ad hoc signing addresses a problem; in truth, it doesn’t achieve much, if anything, and isn’t to be generally recommended.

Ad hoc signing isn’t really signing at all, because it doesn’t use a certificate to provide cryptographic evidence that the signature is valid. All it really does is provide a hash value which claims to verify that the code bundle hasn’t been tampered with. As you can’t validate that hash in any way, you can’t trust it, and Gatekeeper won’t either.

Where an ad hoc signature can be valuable is when the hash value can be compared against a suitably-protected known good value. As there’s currently no robust way for a user to do that, you can’t trust an ad hoc signature any further than you can forge one.

Signing with a personal certificate

Obtaining certificates is usually not free. To obtain an Apple Developer certificate, you have to pay to be a recognised developer; you can sign code using certificates which rely on another root certificate, although for code signatures on macOS these are relatively unusual, and certificate authorities don’t often provide certificates suitable for code signing free of charge.

You can, though, generate your own personal certificate which you can designate as trusted on your and other Macs. This is performed through Certificate Assistant. My next article will step you through that process.

References

Apple’s Code Signing Guide
TN2206 Code Signing in Depth