Sign in Join
Wiki copytemporary

Code Signing for macOS: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11> **Note:** For Apple Notarization requirements for kernel extensions and applications from Mojave 10.14.5 onwards (for kernel extensions from 7 April 2019 and for developers whose first use of their code signing certificate occurred from 7 April 2019) and for all software from Catalina 10.15 onwards that is not distributed via the App Store, see [[Notarization for macOS 10.14.5+]]
22
33## Introduction
44
55**[[Code signing]]** ensures both authenticity and integrity of executables that have been downloaded from wide area networks like the Internet. The discussion below applies equally to App Store distribution and distribution outside the App Store.
66
77Code signing is required in [[Portal:iOS|iOS]]. On [[Portal:Mac|macOS]] 10.7 and later, it enables programs downloaded from the Internet to be opened without any warnings (if they are signed with an Apple-issued certificate) and it is required when using certain functionality (eg APIs used by debuggers; note that in this case a self-signed certificate that is marked as "trusted" suffices). This functionality is performed by Apple's Gatekeeper software.
88
99## The evolution of Gatekeeper
1010
1111Gatekeeper, first introduced in Mountain Lion (10.8, 2012), is a Mac security feature that was designed to protect Apple computers from malicious software. Gatekeeper checks applications against the list of apps that Apple has approved for its App Store or have been code signed by developers who have Apple-issued certificates where the application is not offered through the app store. It does not perform any safety checks by itself, other than that the application wasn't changed since the developer signed it, nor does it offer any guarantees about the developer other than that they are paying Apple \$US 99 per year (aka an "Identified Developer").
1212
1313The original Gatekeeper options introduced in Mountain Lion, accessed from Preferences \> Security and Privacy \> General, were:
1414
1515- App Store
1616- App Store and Identified Developers
1717- Anywhere
1818
1919By choosing the **Anywhere** option, the user was once able to entirely disable Gatekeeper. The default setting only allowed the launching of applications from the App Store or from a developer who had signed their application with an Apple-issued certificate.
2020
2121When macOS Sierra was released in 2016, Apple made some important changes to Gatekeeper and limited the the Gatekeeper options to:
2222
2323- App Store
2424- App Store and Identified Developers
2525
2626However, you can restore the missing Gatekeeper *Anywhere*' option in Preferences by opening a terminal and executing the command:
2727
2828 $ sudo spctl --master-disable
2929
3030which still works up to and including macOS Catalina. The better, as in more secure, alternative was to instead bypass Gatekeeper by opening the application from the right-click context menu or by control clicking on the application. This still triggered the alert dialog but it now contained an **Open** button to successfully launch the application. This method of bypassing Gatekeeper still works in macOS Catalina, except that on Catalina you need to launch the application a second time with the control-click or right-click to successfully bypass Gatekeeper - the first time you launch the application Gatekeeper cannot be bypassed whether you control-click or right-click or not.
3131
3232### Big Sur and later on Apple M1 ARM64 processors
3333
3434And then Apple changed the game.
3535
3636When Big Sur is running on an Apple M1 (ARM64) processor, **all native ARM64 code must be signed or the operating system prevents its execution**; and this new Gatekeeper requirement cannot be bypassed by users. Developers can bypass it by running the following command in an Applications \> Utilities \> Terminal window:
3737
3838`spctl developer-mode enable-terminal`
3939
4040and then going to System Preferences \> Security & Privacy \> Privacy, scrolling down until you see an entry for "Developer Tools", authenticate and then tick the checkbox next to Terminal.
4141
4242Intel executables being run under Big Sur on an Apple M1 processor via Rosetta 2 can still be run even though they are unsigned using the control-click or right-click method to bypass Gatekeeper.
4343
4444For more details, see: [[macOS Big Sur changes for developers|Big Sur changes for developers: Code signing - Intel vs M1]].
4545
4646## Gatekeeper Dialogs
4747
48-<File:load> security warning dmg leopard en.png\|Simple warning after opening a downloaded application in Leopard. <File:load> security warning dmg mavericks en.png\|Default settings are more strict in Mavericks, where they prevent downloaded unsigned apps from being started via double-clicking. <File:load> security warning mavericks context en.png\|If the application is launched via context menu in Mavericks a simple warning is displayed similar to that of earlier versions. <File:simple> load security warning mavericks en.png\|Gatekeeper shows a simplified warning, if a code-signed app has been downloaded and launched for the first time. In subsequent launches the program is starts immediately. <File:codesigning.png%7COverview> of code-signing a program written with Lazarus and Free Pascal
48+![](/wiki-images/2/26/Load_security_warning_dmg_leopard_en.png)
49+
50+Simple warning after opening a downloaded application in Leopard.
51+
52+![](/wiki-images/3/31/Load_security_warning_dmg_mavericks_en.png)
53+
54+Default settings are more strict in Mavericks, where they prevent downloaded unsigned apps from being started via double-clicking.
55+
56+![](/wiki-images/2/20/Load_security_warning_mavericks_context_en.png)
57+
58+If the application is launched via context menu in Mavericks a simple warning is displayed similar to that of earlier versions.
59+
60+![](/wiki-images/c/c3/Simple_load_security_warning_mavericks_en.png)
61+
62+Gatekeeper shows a simplified warning, if a code-signed app has been downloaded and launched for the first time. In subsequent launches the program is starts immediately.
63+
64+![](/wiki-images/1/15/Codesigning.png)
65+
66+Overview of code-signing a program written with Lazarus and Free Pascal
4967
5068## Overview
5169
5270The basic steps to sign an application that has been written with Lazarus and/or Free Pascal are:
5371
54721. Obtain a Developer ID from Apple and install it in your system's key chain.
55732. Note the alphanumeric key of your Developer ID (aka TeamIdentifier).
56743. Sign your application with the *codesign* command.
57754. Sign your installer pkg with the *productsign* command.
5876
5977It is **not possible** to use certificates from third-party providers like Comodo because they will not pass Gatekeeper which requires an Apple developer issued certificate. Also note that you cannot sign Windows applications with the Apple developer certificate (this time you do need a third-party Comodo etc certificate).
6078
6179A macOS application distributed outside the Mac App Store will generally have 3–4 separate layers of signing:
6280
6381- The application itself will be code signed using an application certificate.
6482- If the application has an installer, the package file will be signed using an installer certificate.
6583- The disk image containing the application or installer will be signed using an application certificate.
6684- The disk image will [[Notarization for macOS 10.14.5+|notarized]], and then the ticket generated by the notary service will be [[Notarization for macOS 10.14.5+|stapled]] to it.
6785
6886## Gatekeeper requirements
6987
7088- Your application should be standalone with no unacceptable external dependencies. The only acceptable external dependencies are system libraries. All other dependencies should be copied to your MyApp.app bundle folder. Gatekeeper rejects any application that has non-system external dependencies.
7189
7290- All binary files inside MyApp.app should be code signed.
7391
7492- All binary files should be located in standard locations inside the MyApp.app bundle folder. Refer to the table below.
7593
7694| Location | Description |
7795|----|----|
7896| Contents | Top content directory of the bundle |
7997| Contents/MacOS | Main executable; helper apps and tools |
8098| Contents/Frameworks | Frameworks, dylibs |
8199| Contents/PlugIns | Plug-ins, both loadable and extensions |
82100| Contents/XPCServices | XPC services |
83101| Contents/Helpers | Helper apps and tools |
84102| Contents/Library/Automator | Automator actions |
85103| Contents/Library/Spotlight | Spotlight importers |
86104| Contents/Library/LoginItems | Installable login items |
87105| Contents/Library/LaunchServices | Privileged helper tools installed by the ServiceManagement framework |
88106
89107Standard locations for code inside a bundle
90108
91109Note: No non-binary files should ever be located in the folders specified in the table above.
92110
93111## Using codesign to sign your application
94112
95113**1.** Sign your application with:
96114
97115``` bash
98116codesign -f -o runtime --timestamp -s "Developer ID Application: YOUR NAME (TEAM_ID)" /path/to/bundle.app
99117```
100118
101119**2.** Display basic information about the result of the signing process:
102120
103121``` bash
104122codesign -dv -r- /path/to/bundle.app
105123```
106124
107125If your application was successfully signed this command will return information similar to this:
108126
109127 Executable=/Users/apple/Desktop/your.app/Contents/MacOS/yourappname
110128 Identifier=org.yourdomain.yourappname
111129 Format=app bundle with Mach-O thin (x86_64)
112130 CodeDirectory v=20500 size=101470 flags=0x10000(runtime) hashes=3164+3 location=embedded
113131 Signature size=9063
114132 Timestamp=7 Dec 2019 at 18:36:08
115133 Info.plist entries=16
116134 TeamIdentifier=<10 alpha numeric digits>
117135 Runtime Version=10.14.0
118136 Sealed Resources version=2 rules=13 files=45
119137 designated => identifier "org.yourdomain.yourappname" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = <10 alpha numeric digits>
120138
121139**3.** Verify your signature:
122140
123141``` bash
124142codesign -vv /path/to/bundle.app
125143```
126144
127145If your app was successfully signed this command will return the strings "valid on disk" and "satisfies its Designated Requirement", respectively, after the path to your application.
128146
129147## Using productsign to sign your pkg installer
130148
131149**1.** Sign your installer pkg file with:
132150
133151``` bash
134152productsign --timestamp --sign "Developer ID Installer: YOUR NAME (TEAM_ID)" /path/to/unsigned.pkg /path/to/signed.pkg
135153```
136154
137155**2.** Verify your signature with:
138156
139157``` bash
140158spctl -vv --assess --type install /path/to/your.pkg
141159```
142160
143161which should yield information similar to this if it was successful:
144162
145163 your.pkg: accepted
146164 source=Developer ID
147165 origin=Developer ID Installer: YOUR NAME (<10 alpha numeric digits>)
148166
149167## Using codesign to sign your disk image
150168
151169Beginning in macOS 10.11.5, you can apply a code signature to read-only, compressed disk images that you use to distribute content. In this case you do not need to separately sign your application.
152170
153171**1.** Sign your disk image with:
154172
155173``` bash
156174codesign -f -o runtime --timestamp -s "Developer ID Application: YOUR NAME (TEAM_ID)" /path/to/YourImage.dmg
157175```
158176
159177**2.** Verify your signature with:
160178
161179``` bash
162180spctl -a -t open --context context:primary-signature -vv /path/to/YourImage.dmg
163181```
164182
165183which should yield information similar to this if it was successful:
166184
167185 YourImage.dmg: accepted
168186 source=Developer ID
169187 origin=Developer ID Application: YOUR NAME (<10 alpha numeric digits>)
170188
171189**After 3 February 2020 Apple is fully enforcing notarization** for macOS 10.14.5+ (Mojave) with the consequence that the above verification of your disk image will now return information similar to this:
172190
173191 YourImage.dmg: rejected
174192 source=Unnotarized Developer ID
175193 origin=Developer ID Application: YOUR NAME (<10 alpha numeric digits>)
176194
177195See [[Notarization for macOS 10.14.5+]] for more details.
178196
179197## Updating a signed file
180198
181199Whenever you update a signed file, create a new file. Do not copy a new signed file over an old signed file.
182200
183201Specifically, the code signing information (code directory hash) is hung off the vnode within the kernel, and modifying the file behind that cache will cause problems. You need a new vnode, which means a new file, that is, a new inode. Documented in WWDC 2019 Session 703 All About Notarization - see [slide 65 (PDF)](https://devstreaming-cdn.apple.com/videos/wwdc/2019/703yqvyjv9mi5ur6/703/703_all_about_notarization.pdf).
184202
185203## Ad hoc signing
186204
187205This is especially important on ARM64 M1 Apple processors which require all native code to be validly signed (if only ad hoc) or the operating system will not execute it, instead killing it on launch. To ad hoc sign an application:
188206
189207` codesign --force --deep -s - lazarus.app`
190208
191209or to ad hoc sign an executable file:
192210
193211` codesign --force -s - lazarus`
194212
195213A single dash/hyphen on its own for the identity makes it an ad hoc signature with no certificate.
196214
197215You can check the validity of an ad hoc signed executable with:
198216
199217` codesign -dv -r- lazarus`
200218
201219which should produce output similar to the below:
202220
203221`Executable=/Users/trev/lazarus-src/lazarus`\
204222`Identifier=lazarus`\
205223`Format=Mach-O thin (arm64)`\
206224`CodeDirectory v=20400 size=336137 flags=0x2(adhoc) hashes=10498+2 location=embedded`\
207225`Signature=adhoc`\
208226`Info.plist=not bound`\
209227`TeamIdentifier=not set`\
210228`Sealed Resources=none`\
211229`# designated => cdhash H"2e6f474452344d6fa42feee3db14a05c14d595a3"`
212230
213231In cases where you have compiled the executable yourself, the macOS linker will ad hoc sign the executable for you in which case you need do nothing. You can check the validity with the command above in which case the CodeDirectory output line will indicate that the linker signed the executable with an ad hoc signature as follows::
214232
215233` CodeDirectory v=20400 size=336032 flags=0x20002(adhoc,linker-signed) hashes=10498+0 location=embedded`
216234
217235## Code signing an x86_64 binary on an aarch64 machine
218236
219237## How to install certificates on a second computer
220238
221239There are two ways to do this:
222240
2232411. using the Keychain Access application; and
2242422. using Xcode.
225243
226244### Using the Keychain Access application
227245
228246- On the first computer which has the certificates, open the Keychain Access application and create a new keychain. Now select your existing login keychain, and then My Certificates. Your certificates should be shown on the right. There should be a disclosure arrow on the left side, and selecting that should reveal your private key. Select each certificate, and copy and paste (do not drag or you'll remove it from your login keychain) it into your new keychain.
229247
230248- Copy the newly created keychain from your first computer to your second computer, open it with the Keychain Access application and copy/paste/drag the certificate to your second computer's login keychain.
231249
232250### Using Xcode
233251
234252- On the first computer which has the certificates, open Xcode and go to Preferences \> Accounts, select your account, select the gear symbol in the bottom left, choose Export Apple ID and Code Signing Assets, and then save the file.
235253
236254- Copy the developer profile file you saved on your first computer to the second computer, open Xcode, go to Preferences \> Accounts, select your account, select the gear symbol in the bottom left, and then choose Import Apple ID and Code Signing Assets.
237255
238256## How to check what certificates are installed
239257
240258Once you have created or imported the certificates on your computer, you can check for their presence by opening an Applications \> Utilities \> Terminal and executing the following command:
241259
242260`$ security find-identity -p basic -v`
243261
244262This command will list all available certificates on this computer. Make sure that you can see the presence of the *Developer ID Application* and *Developer ID Installer* certificates. If you are a member of more than one team, you may see multiple certificates for each team.
245263
246264You can identify the certificates by the hexadecimal number or by the descriptive name, eg "Developer ID Application: Your Name (AB123456DE)"
247265
248266The ten character alpha-numeric code at the end of your name is your Developer Team ID. If you are a member of multiple developer teams, you will have multiple certificates and the team ID will help you distinguish them.
249267
250268## See also
251269
252270- [[macOS Big Sur changes for developers|Code signing: Intel vs Apple Silicon]]
253271- [[Apple Developer Certificates]]
254272- [[Notarization for macOS 10.14.5+]]
255273- [[Hardened runtime for macOS]]
256274- [[Sandboxing for macOS]]
257275- [[Signing and Notarization FAQ]]
258276- [[macOS Gatekeeper Debugging Tips]]
259277
260278## External links
261279
262280- [Apple Developer portal](https://developer.apple.com/)
263281- [Apple: Code Signing Overview](https://developer.apple.com/support/technical/code-signing/)
264282- [Apple: Code Signing Guide](https://developer.apple.com/library/mac/documentation/Security/Conceptual/CodeSigningGuide/)
265283- [Apple: TN2206 - macOS Code Signing In Depth](https://developer.apple.com/library/archive/technotes/tn2206/_index.html)
266284- [Apple: Code signing x86_64 binaries on aarch64](https://developer.apple.com/forums/thread/673323).
267285
268286---
269287*From the Free Pascal wiki, page "Code Signing for macOS", as it stood on 2022-02-13 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history