After choosing the certificate type, you can upload your Certificate Signing Request (CSR). (Hopefully, you generated the private key for the CSR on an HSM.) Note that the underlying key pair must be generated using the RSA algorithm with a length of 2048 bits. Apple will issue the certificate, and then you can import it into your code signing solution of choice.
Putting Code Signing Certificates to Work
You can’t distribute that HSM-backed key to your build/developer machines. That key will never leave the HSM. So how do you use it for code signing in your continuous integration pipeline? Simple. You just need an application known as CryptoTokenKit. It registers your certificate in the system’s keychain, along with an identifier for the private key. During the signing operation, Apple’s crypto backend calls the CryptoTokenKit extension, which in turn forwards any signing operation to the signing service (in our case, SignPath.io). If you’re interested in the technical details, there’s an excellent deep dive into the CryptoTokenKit architecture by Timothy Perfitt on this website.
The documentation for the SignPath CryptoTokenKit can be found here.
Notarization
The Apple notary service is an automated system that scans your software for malicious content, checks for code-signing issues, and returns the results to you quickly. If there are no issues, the notary service generates a ticket for you to staple to your software; the notary service also publishes that ticket online where Gatekeeper can find it.
If you want to avoid warning dialogs during install, notarization is required when distributing your software outside of the AppStore. For more details, see the official documentation. To automate this process, Apple provides the notarytool and stapler executables. The former uploads the artifact to the Apple servers for automated scanning and the latter attaches the notarization to the software. You will have to authenticate against Apple using an app-specific password. According to Apple, notarization is completed within 5 minutes for most software and within 15 minutes for 98% of uploaded software. That’s fast enough to include it in most automated builds. However, note that the first submission can take up to day.
Notarization requires a signature with a valid release certificate issued by Apple. You must use release certificates, or it won’t work.
Hardened Runtime
A hardened runtime is a pre-requisite for notarization. Follow the official article by Apple to add a hardened runtime capability to your app. You need to list all exceptions to the restrictions explicitly.
The Hardened Runtime is a collection of system-enforced restrictions that disable a set of functional capabilities, such as loading third-party frameworks, and prohibit access to restricted resources, such as the device’s built-in camera, to prevent certain classes of exploits from compromising the runtime integrity of your macOS app.
When signing your software with a hardened runtime, you need to add the –-options=runtime parameter to the codesign call. Make sure to test your app thoroughly after enabling the hardened runtime to ensure that all use-cases still work.
The get-task-allow entitlement
When building the software automatically using the xcodebuild tool, there is another special setting to consider: Apple automatically injects an entitlement used for debugging at build time which is incompatible with the notarization process. You can disable this behavior by passing the CODE_SIGN_INJECT_BASE_ENTITLEMENTS=NO flag to your xcodebuild call. See here for more technical details.
Sample
Let’s get hands on! First you’ll need a Free Trial account on Signpath. Sign up here: https://login.signpath.io/
Below is a code snippet that highlights how to sign and notarizes an application. For a full working sample, visit the demo repository.
Conclusion
You now have everything you need to start building and releasing trusted applications for macOS, directly to your user base. The Apple App Store and enterprise distribution channels provide safe and convenient ways to reach users, but direct distribution is often preferred for Enterprise software. However, it does come with the added responsibility of properly signing and notarizing your applications. By following these requirements and keeping your keys secure, you can safely distribute your application outside of the App Store, while still ensuring a quality end user experience with your trustworthy apps.
