Mac Application Signing And Notarization
In the new version of macOS, Apple made mandatory some requirements for applications that were previously recommendations: 64-bit executable files, signing and notarization. Applications that do not meet these requirements will no longer be launched.
If you don’t have one yet, enable two-factor authentication for your Apple ID. This can be done from any i-device or from a Mac. On a Mac, go to the iCloud control panel -> System Preferences. At the top there should be a panel suggesting to enable 2FA.
Log in to https://developer.apple.com/ using your Apple ID and go to the Membership tab. Buy or upgrade your Apple Developer Program membership if necessary. Keep in mind that processing a purchase takes some time on Apple’s internal systems, so if you are unable to generate certificates (see below), drink a cup of tea and calm down.
You may need to register the application bundle ID in the developer's backend. The bundle ID can be found in YourApp.app/Contents/Info.plist. (You can open application bundles by right-clicking on them and selecting “Show Package Contents.”) The identifier should be com.yourcompanyname.applicationname, for example, my game Airships has com.zarkonnen.airships.
To register an ID, log in to https://developer.apple.com/, select “Certificates, IDs & Profiles” in the left pane, and then select “Identifiers” on the next page. Then you can click the “+” button to add the application identifier.
To sign from the command line, you will need the application password, so go to https://appleid.apple.com/account/manage and generate it.
Xcode and tools
Install Xcode through the Mac App’s App Store. Then install also the Xcode command line tools from https://developer.apple.com/download/more. You need Command Line Tools for Xcode 11 or the version of Xcode you are using.
Launch Xcode, go to Preferences, open the Accounts tab. If necessary, add your Apple ID to the list of accounts. Then click on the "Manage Certificates ..." button in the lower right corner. The certificates you have for signing applications are displayed. You need a “Developer ID Application” certificate; if it is not in the list, then create it. Click "Done" and then "Download" in the Preferences: Accounts window to download the certificates locally.
For the application to work correctly on the new system, the executable file and libraries must be 64-bit.
In addition, Mac OS performs an operation called “translocation”: for security reasons, it moves the running application bundle to a random location. In the case of my application, this manifested itself in the fact that it could not find the data files located next to the application bundle. You can get the initial location of the application bundle, but I solved the problem by simply placing everything in the bundle.
This is the process of creating a digital signature informing: the one who has access to the signature certificate promises that this particular application bundle is reliable and not malicious. Any changes to the bundle of the application (except for attaching a confirmation of notarization, see above) after signing it invalidate the signature and require re-signing of the bundle.
This also means that your application should not change anything in the contents of the application bundle, for example, do not put a cache there.
Each executable file and dynamic library in the application bundle are signed separately. In some cases, libraries may already be signed. That is, it is more polite and calm to sign a bundle by signing each element in turn, and then sign the entire bundle. If any element already has a signature, then it will remain in its place.
A coarse, but effective way is to force deep signing, that is, your signature will be applied to all elements of the application bundle, replacing all previous signatures. This is exactly what we will do, because it is simpler and because previous signatures may be invalid or not strong enough.
You will need the following command:
codesign -s "Developer ID Application: <YourName>" --timestamp --options runtime -f --entitlements entitlements.plist --deep YourApp.app
The --timestamp option means that a valid timestamp, which is necessary for successful notarization, is embedded with the signature.
The option --options runtime means that the signature includes “hardened runtime”, which is also necessary for successful notarization.
You can check the signature by the command:
codesign -d -vvvv YourApp.app
You should also run the application to make sure that it continues to work after signing.
If you want to sign elements in a more polite manner, then remove -f and --deep from the command, first sign all the executable files and libraries inside the application, and then the whole application.
After signing the application, you need to provide it to Apple systems for notarization in order to say: “Look, I signed this thing.”
To do this, first compress the application into a special zip file using the ditto command:
/usr/bin/ditto -c -k --keepParent YourApp.app YourApp.zip
Simply pack the application in zip using Finder or the command line will not work.
Then send a zip file for notarization:
xcrun altool --notarize-app --primary-bundle-id "<id>" -u "<appleid>" -p "<app-specific password>" --file YourApp.zip
xcrun altool --notarize-app --primary-bundle-id "com.zarkonnen.airships" -u "email@example.com" -p "bwnh-pbbt-llpt-xxxx" --file Airships.zip
The bundle ID can be found by looking at YourApp.app/Contents/Info.plist. (You can open application bundles by right-clicking on them and selecting “Show Package Contents”.)
Notarization can take quite a while. This is usually a few seconds or minutes, but sometimes it can be an hour. Pour yourself more tea, or something stronger, choose for yourself. Sooner or later you will get something like this:
No errors uploading 'YourApp.zip'.
RequestUUID = 29926ae6-f551-4d54-b283-e29d6f9b9156
Now you can use the following command to check the status of the passed bundle:
xcrun altool --notarization-info <RequestUUID> -u -u "<appleid>" -p "<app-specific password>"
xcrun altool --notarization-info 29926ae6-f551-4d54-b283-e29d6f9b9156 -u "firstname.lastname@example.org" -p "bwnh-pbbt-llpt-xxxx"
Something similar will be displayed:
Date: 2019-10-08 06:59:58 +0000 Hash: 0774fb95035408bacecebd64935a611ecd27b45ad9cbf3cc1aa48fa1e0eaa649 LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets/Enigma123/... Status: success Status Code: 0 Status Message: Package Approved
Confirmation usually takes about 15 minutes, but sometimes the same application takes several hours.
If status is failure, then see the errors listed by the log file URL. If you get success, then take a look anyway, because there may be warnings, and these warnings may well become errors when Apple tightens its requirements again.
Finally, attach the notarization confirmation to the application bundle so that even a Mac can check it without an Internet connection. To do this, you must execute a surprisingly short command:
xcrun stapler staple "YourApp.app"
Congratulations, you have signed up and notarized the Mac app. Now you can distribute the application bundle in any way convenient for you if it does not change in the process.
Documentation in Russian
Подробная статья на русском языке тут.