How can I sign and notarize my compiled application to conform with Apple's notarization requirements?

28 views (last 30 days)
Apple has announced that, starting with macOS Catalina (10.15), they're going to require notarization for all apps, even on systems set to allow non-AppStore apps.
How do I correctly sign, notarize, and distribute my compiled application to end users while meeting these new Apple requirements?

Accepted Answer

MathWorks Support Team
MathWorks Support Team on 18 Oct 2024
Edited: MathWorks Support Team on 3 Sep 2024
Prerequisites
There are a few prerequisites you need before you can begin signing and notarizing on Mac:
  1. A Mac that can run Xcode 13 (must be capable of running macOS 11.3 or later). Note that Xcode requires 25 GB of free space to run the install.
  2. An Apple Developer ID and Apple Developer ID Application certificate.
  3. MATLAB release R2020a or later. Note: You need MATLAB release R2021b or later if you want to notarize application installer with the "RuntimeDelivery" option set to 'installer'.
Once you have the above, you can begin notarizing your compiled app.
Steps for notarizing a compiled application
1. Create an "entitlements.plist" file using Xcode.
Entitlements are specific permissions that you include with the code signature that allow the signed app to do certain things. Compiling with Xcode allows you to set this up as part of that process; however, since you are adding entitlements to a MATLAB compiled app, you will need to manually create this file.
To create a new plist file with Xcode, select "New File" and then "Property List". You will need to add items to the "Root" dictionary with the names of the entitlements that you want, mapped to boolean:YES.
MATLAB compiled applications need permissions to set the DYLD_LIBRARY_PATH environment variable in order to run. See the MATLAB Runtime Path Settings for Run-Time Deployment page:
Consequently, you need to allow the following entitlements:
com.apple.security.cs.allow-jit com.apple.security.cs.disable-library-validation   com.apple.security.cs.allow-dyld-environment-variables
In the end, the file should look similar to this:
2. Code sign the application with the entitlements.
Every executable and dynamic library in the app bundle must be signed individually. Depending on what libraries you are using, they may already be signed. The best way to sign your bundle is to go over each of these and sign them before finally signing the bundle itself. Using codesign, if there is a signature already in place for something it will remain in place.
For example, for a simple "HelloWorld" app the process would be:
1. Code sign all MEX file dependencies (if any) before generating the application.
2. Compile the application (with the signed MEX files) using either mcc or the deploytool.
3. Code sign <HelloWorld appbundle>/Contents/MacOS/applauncher.
4. Code sign <HelloWorld appbundle>/Contents/MacOS/HelloWorld.
5. Code sign <HelloWorld appbundle>/Contents/MacOS/prelaunch.
6. Code sign the bundle itself.
Note 1: prelaunch must be signed after the app launcher and the HelloWorld executable. Otherwise, you will get an error.
Note 2: Please sign each executable separately and not using --deep flag to sign the entire app. As this will lead to future errors during notarization if you need to package the app in an installer.
The corresponding codesign commands for this example are:
 
Mac-Machine:HelloWorld.app username$ cd Contents/MacOS/
Mac-Machine:MacOS username$ ls
applauncher HelloWorld prelaunch
Mac-Machine:MacOS username$ codesign --verbose=4 --options=runtime -s "<Your Developer ID Application Certificate>" --entitlements entitlements.plist applauncher
applauncher: signed Mach-O thin (x86_64) [applauncher]
Mac-Machine:MacOS username$ codesign --verbose=4 --options=runtime -s "<Your Developer ID Application Certificate>" --entitlements entitlements.plist HelloWorld
HelloWorld: signed Mach-O thin (x86_64) [HelloWorld]
Mac-Machine:MacOS username$ codesign --verbose=4 --options=runtime -s "<Your Developer ID Application Certificate>" --entitlements entitlements.plist prelaunch
prelaunch: signed app bundle with Mach-O thin (x86_64) [HelloWorld]
Mac-Machine:MacOS username$ cd ..
Mac-Machine:Contents username$ cd ..
Mac-Machine:hello.app username$ cd ..
Mac-Machine:standalone username$ codesign --verbose=4 --options=runtime -s "<Your Developer ID Application Certificate>" --entitlements entitlements.plist HelloWorld.app
HelloWorld.app: is already signed
 
After doing this, you can use the following command to verify the entitlements of the app:
codesign -d --entitlements - HelloWorld.app
You should also launch the app to verify that it still works as expected after signing.
3. Zip the application into a zip file to be submitted for notarization.
You can do this either manually or programmatically, using the command:
ditto -c -k --keepParent AppName.app AppName.zip
4. Submit the ZIP file to a notarization service
You can execute the following command to notarize your app using Xcode:
Note that the password is an app-specific password for notarytool (not your Apple ID) which you will need to set on the Apple Developer website.
xcrun notarytool submit YourApp.zip --apple-id <appleid> --password <password>
Using the HelloWorld example, this will look something like:
Mac-Machine:standalone username$ xcrun notarytool submit HelloWorld.zip --apple-id youremail@gmail.com --password <password> No errors uploading 'HelloWorld.zip'. RequestUUID = 889a6a12-ecca-4d60-ae84-e0edb3284xxx
To check the status of the submission, use the following command:
xcrun notarytool info <RequestUUID> --apple-id <appleid> --password <password>
Once again, for the HelloWorld app example, this will look like:
Mac-Machine:standalone username$ xcrun notarytool info 889a6a12-ecca-4d60-ae84-e0edb3284xxx --apple-id youremail@gmail.com --password <password> No errors getting notarization info. Date: 2020-07-29 00:49:27 +0000 Hash: 7776e46ad3085840be4ea56875c794b3e81f5684faa32b8fc8b9e4316daa46xx LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets/... RequestUUID: 889a6a12-ecca-4d60-ae84-e0edb3284xxx Status: success Status Code: 0 Status Message: Package Approved
5. Staple the notarization approval to the app bundle
You can do this with Xcode using the following command:
xcrun stapler staple YourApp.app
The output should looks something like this:
Mac-Machine:standalone username$ xcrun stapler staple hello_signed.app Processing: /Users/username/Documents/MATLAB/standalone/hello_signed.app Processing: /Users/username/Documents/MATLAB/standalone/hello_signed.app The staple and validate action worked!
6. Verify that the app is notarized
Use the following command to verify that the app bundle is correctly notarized:
spctl -a -t exec -vvv YourApp.app
If all notarization and signing was successful, the output should look like this:
Mac-Machine:standalone username$ spctl -a -t exec -vvv hello_signed.app hello_signed.app: accepted source=Notarized Developer ID origin=Your Certificate
7. Deploy the application
You can simply send the notarized application to your end users. They will also need to install MATLAB Runtime separately.
Steps for notarizing the application installer
Alternatively, you can generate an installer that installs both your application and MATLAB Runtime on the target machine. There are additional steps required for notarizing the installer.
As mentioned earlier, each executable and dynamic library in the app bundle is signed individually, meaning an app bundle has to be code signed from the inside out. To sign the installer, the app itself must be signed following the previous section's instructions.
        1. Follow the previous section to code sign the standalone application
        2. Generate the installer using the "compiler.package.installer" command and pass the signed app to it.
Note that using the deploytool to generate the installer is not supported for notarization. This is because there is no way for the standalone application to be signed prior to generating the installer using the deploytool.
        Using the HelloWorld app, this looks like:
compiler.package.installer(... 'helloworld.app','requiredMCRProducts.txt',... 'ApplicationName','hello world')
        Note: The "RuntimeDelivery" option of the above command must be set to "web" for releases prior to R2021b. This is the default behavior if the option is not specified. The installer generated with the "RuntimeDelivery" option set to 'installer' cannot be notarized before R2021b.
3. Code sign the generated installer. Make sure not use "-–deep" flag in the codesign command, which may cause prelauch to report error during notarization. (Example error in the log - "path": "MyAppInstaller.zip/MyAppInstaller.app/Contents/Resources/bundle.zip/application/hello.app/Contents/MacOS/prelaunch", "message": "The signature of the binary is invalid.")
        4. Notarize and staple the signed installer
Refer to the "Steps for notarizing a compiled application" section for detailed commands for steps 3 and 4. After completing the above, the installer and application should correctly signed and notarized for deployment. For further information regarding the codesign and notarization commands used, please refer to Apple's documentation.
  2 Comments
Image Analyst
Image Analyst on 22 Jul 2022
Edited: Image Analyst on 22 Jul 2022
Is there a similar process for using a certificate from an organization such as Entrust or Certs4Less to sign a standalone executable created with the MATLAB Compiler Toolbox on the Windows 10 platform?

Sign in to comment.

More Answers (0)

Categories

Find more on MATLAB Compiler in Help Center and File Exchange

Products


Release

R2019b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!