This guide is meant to help you notarize Adobe Flash and AIR executables for distribution outside of the App Store. Distributing within the App Store requires a few extra steps such as packing icons and setting up specific provisioning profiles as well.
Some of the following steps are likely to apply to software developed with other non-Xcode tools. Some popular tools like Unity will presumably integrate most of this workflow in their IDEs, but even in that case developers may not be in the position of rebuilding some projects using the most updated environments.
This guide was written on September 13, 2019 and it’s likely to become obsolete as soon as Apple comes up with some new bullshit.
Update: Apple temporarily relaxed the notarization requirements.
Apple’s Gatekeeper is the single biggest threat to software preservation under the macOS environment. It entraps users and developers into a monoculture of Apple products, makes standalone software dependent on inscrutable and ever-changing remote protocols, turns general purpose computers into appliances.
Apple has been building up its security theater for years, fencing off independent developers, and collecting tributes from commercial developers for the privilege of using their systems.
After employing all sorts of dark patterns to discourage users from running applications from “unidentified developers” (i.e. not due-paying Apple developers), starting from macOS 10.15, aka Catalina, Apple will require to sign and “notarize” all applications meant to run on their system. Catalina will also block all 32bit applications, which are still rather common.
Certifying software is a good practice – that’s how you know that a file named photoshop.app is actually coming from Adobe – but preventing users from executing all uncertified files on their own machines is a paternalistic, rent-seeking move that will mostly affect small, non-commercial developers.
In order to notarize an app you’ll need:
- macOS 10.14+ aka Mojave, and a machine that can run it.
- XCode 10.3+ not just the command line tools but the whole 10GB of stuff.
- An Apple developer account, it’s $100 for individuals and $300 for businesses. It’s per year and needed only for the signing/notarization process, or if you distribute on the App Store, or if you use advanced Apple features like maps, Apple Pay etc. If your membership expires, your apps on the App Store will disappear (but not from your users’ phones). If you don’t make any update the notarization should remain valid.
- A distribution certificate in your computer’s keychain. This requires an elaborate mating ritual between your computer and Apple’s servers to verify that you are actually the developer. However, once set up, it functions rather seamlessly. Until, of course, you change computer.
- The two-factor authentication enabled in your account. It basically adds to the user/password another layer of security tied to a physical device so a Russian hacker can’t mess with your precious apps without also stealing your phone or computer.
- An app-specific password to use in the terminal for the notarization. This requires the two-factor authentication and it appears to be a workaround for a security restriction that Apple itself created. It’s something like gtko-apem-voei-afpp and you want to copypaste it on a text file for later use.
- The app you need to notarize. Make sure it’s a 64bit application. Make a backup because an incorrect signing action can corrupt it forever.
The Entitlements file
This whole notification thing is basically just an automated malware check. By default it’s super strict but you can opt-out of certain restrictions by sending Apple a nice letter. The nice letter is a simple XML file named like entitlements.plist. Apparently it *must* be written through Xcode, the 10GB of mysterious stuff you downloaded.
For Flash and AIR executables you have to allow the “JIT compiler” and the “unsigned executable memory” whatever they are. Without entitlements the signing might still be successful but the app will likely be corrupted, crashing on start.
You can try to use my file (entitlements.plist) or make your own in Xcode through a particularly idiotic procedure that I can’t even describe in words:
Apple needs a unique identifier associated to your account for each app you want to distribute. Log in the developer backend and create one:
As a punishment for not developing your software using handsome Xcode, you have to crawl back to the command line era.
Luckily you can open a Terminal window directly to your desired location by right clicking on the containing folder.
Make sure that you have the correct certificate identifier. It is the *whole string* in the keychain, copypaste it in a text file.
Mine is something like ‘Developer ID Application: PAOLO PEDERCINI (P7OI89C619)‘, which I’m going to use below.
Make sure you have the app identifier handy. For this example I’m going to use org.molleindustria.game
The application’s hypothetical file name is game.app
The unformatted strings are the commands you’ll have to type or copypaste in the terminal.
xattr -cr 'game.app'
This gets rid of Finder information associated to the file. If not done, the signing might trow the error “resource fork, Finder information, or similar detritus not allowed”.
codesign --force --options runtime --deep --sign 'Developer ID Application: PAOLO PEDERCINI (P7OI89C619)' --entitlements 'entitlements.plist' 'game.app'
This is the code signing operation in which you associate the file to your certificate.
--force replaces the previous signature
--options runtime performs a “hardened runtime” check which is required for notarization under Catalina
--deep recursively signs all the files in the app
--entitlements 'entitlements.plist' associates the entitlement file making the exception described above. In this case entitlements.plist is assumed to be in the same directory of the app.
The operation should trigger multiple password requests because of the –deep search. The password to use is you computer’s login password, because you are accessing the keychain which contains the developer’s certificate.
If you get an error like “unrecognized blob type (accepting blindly)” or “invalid length in entitlement blob” it’s because it busted you with an entitlements file created manually. You fucked up, you underestimated the blob. Go make a .plist file with Xcode as described above.
If you don’t get any message, don’t worry, the Terminal is a “tough love” kind of guy and it will not congratulate you for doing things right. So you may want to check if the operation was successful:
codesign --verify --verbose=4 'game.app'
This outputs a bit of relatively human-readable information about the signature.
Zip the app to create a file called, for example, game.app.zip. In theory you can also create a DMG but I didn’t have any luck with that.
xcrun altool -t osx -f 'game.app.zip' --primary-bundle-id org.molleindustria.game --notarize-app --username firstname.lastname@example.org
This upload the zip to Apple’s servers for notarization. The action is on Apple’s server now, so you have to use the unique app id and your Apple developer username which is usually an email address.
The terminal will prompt a password. This is not the account password nor the computer password but rather the strange app-specific password tied to the two-factor authentication. Copypaste it and press enter.
The terminal will appear absolutely unresponsive during password input and upload. It’s tough love, no frills, just stare at the blank window.
After a while it should confirm that the upload was successful and give you a requestUUID ticket for the operation.
It’s something like: af438ac0-da02-4352-ab55-77c5446c2f81
Now you have to wait a couple of minutes for the automatic (and probably non-existent) security check. You’ll get a response in your mailbox.
It can be negative like this:
Like a bad partner, Apple won’t directly tell you what you did wrong. To find out, you have to go back to the terminal and type something like:
xcrun altool --notarization-info af438ac0-da02-4352-ab55-77c5446c2f81 -u email@example.com
The alphanumeric string is the requestUUID related to the submission. The terminal will spit out a link (LogFileURL). Copypaste in your browser and have fun interpreting the machine generated log:
Hopefully you get the “good news” email.
But wait, you are not done yet.
You still have to *staple* the app, whatever that means:
xcrun stapler staple 'game.app'
If you get a message like “The staple and validate action worked!” you are ready to go.
You can always verify if the file is properly stapled by typing:
xcrun stapler validate 'game.app'
Make sure to delete the zip you uploaded, which is not stapled, and re-zip the app you just stapled for distribution.
At this point I believe it’s safe to change the filename and the file icon.
Changing icons on mac used to be as easy as dragging an image in the info panel. Not anymore. You have to create a set of icons of different sizes now. I create my icon files from png files with this neat right-click script.
Note that when the file is downloaded from the internet, the app will still trigger a stranger-danger warning, but the user will be able to ignore it.
Congratulations! For a mere $100 a year you can now distribute software for macOS.
This should work until Apple decides all software must be distributed through their store. That’s their obvious end game.
In the early ’00s Steve Jobs managed to resurrect Apple by positioning it as brand for an elite of creatives that valued a thoughtful user experience and slick design. These times are long gone. At every new update, Apple computers look more and more like glorified iPads: funneling sanitized content to passive users through centrally controlled platforms.
Products that are appropriate for children, Candy-Crush-addicted soccer moms, and suburban man caves, might not be the best choice for gamers, developers, or users looking for independent digital culture.