A user’s guide to code signatures and notarization

Code signatures and notarization are confusing enough for developers and sysadmins. In this short article, I show some of the most common places you can find them, and how you can discover what they mean.

There are several excellent tools for checking signatures and notarization. Perhaps the most popular is Objective-See’s What’s Your Sign?, which is just in the process of being updated. From the App Store is Max Inspect, aimed mainly at developers. I also have two apps which you may find useful: Taccy, which is mainly about investigating privacy protection, and ArchiChect, which looks more broadly at the requirements imposed by Catalina.

There are also several command tools which can give details, including codesign and spctl. These aren’t easy to use, though, and unless you’re a developer who has to understand and use them, they’re probably worth avoiding.

Regular apps come in bundles, folders with the extension .app whose contents you can inspect in the Finder using its Show Package Contents command. Inside you’ll find a single folder named Contents, within which you should see the innards of the app. If there’s a folder named _CodeSignature, then that app has been signed, and a file named CodeResources is the tell-tale that its notarization ticket has been stapled in the app too.

codesign01

Taccy tells you that this app has been ‘hardened’, a requirement for normal notarization, and is notarized. The text at the bottom confirms both with full details of a signature check and a check of the signature using the codesign tool.

codesign02

ArchiChect gives much the same information for apps.

codesign03

Command tools, and other single-file executable code, don’t have the luxury of a folder in which to store signatures and tickets. The standard solution is to embed the contents of what would be additional files at the end of the executable code. Open a signed command tool using any decent editor – here I’m just using BBEdit – and you should see tell-tale data.

codesign04

First comes the XML text that you’d normally find in an app’s Info.plist file.

codesign05

A little later you’ll see text from the embedded certificates.

ArchiChect decodes all this, and will even tell you if the tool has been notarized. Currently, you can’t embed the ticket supplied for notarized apps in a command tool, as that would alter its signature. What happens when macOS wants to check that a signed command tool has been notarized is that it contacts Apple’s servers, which will confirm whether it has been accepted.

codesign06

The third mechanism is used by signed AppleScripts, and can be used by shell scripts and any other files which consist of text, so can’t have binary data stuck at the end. Here the signature is added using extended attributes – of four different types: com.apple.cs.CodeDirectory, com.apple.cs.CodeRequirements, com.apple.cs.CodeRequirements-1 and com.apple.cs.CodeSignature. These are easily inspected using my extended attribute toolkit xattred.

codesign07

Notice that each of these is binary, although scrolling through the contents of com.apple.cs.CodeSignature you’ll find it easy to spot the text contents of the certificates.

When inspected using ArchiChect, you’ll normally notice that the first of the signature checks results in spctl error 3. This is because Catalina now only passes items which have been notarized, and a signed but un-notarized script is thus failed. The lower results from a codesign check confirm that the script has been signed properly, though.

codesign08

Finally, you need to recognise some of the big differences between code signing and notarization. Signing is performed locally, normally by the developer, using a certificate issued by Apple. Part of the signing process involves saving checksums for the signed content, which macOS uses to verify its integrity. Signatures thus have to be included with the executable code, inside its bundle, tacked on to the end of the code, or in extended attributes.

Notarization is performed by Apple’s Notary Service, and anyone with a Developer ID can submit items for notarization. When notarization is complete, Apple issues the person who submitted the item for notarization with a ticket, which can be stapled into an app bundle or installer package (where it’s just added to the end). Tickets can also be stapled to disk images, which gets more complex.

But the ticket may not be stapled at all: in that case, when Catalina checks whether that code has been notarized, it tries to contact Apple’s servers and check whether it has been notarized and a ticket issued. So a correctly notarized app may not contain any overt evidence that it has been notarized. The only way to be sure is to use one of these tools to check with Apple.

I did warn you that this isn’t simple.

Thanks to @kukushechkin and @rosyna for reminding me about packages and disk images.