Sign in Join
Wiki copytemporary

Code Signing for macOS: what changed

Revision 2 to 3. 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
38-`spctl developer-mode enable-terminal`
38+```
39+spctl developer-mode enable-terminal
40+```
3941
4042and 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.
4143
4244Intel 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.
4345
4446For more details, see: [[macOS Big Sur changes for developers|Big Sur changes for developers: Code signing - Intel vs M1]].
4547
4648## Gatekeeper Dialogs
4749
4850![](/wiki-images/2/26/Load_security_warning_dmg_leopard_en.png)
4951
5052Simple warning after opening a downloaded application in Leopard.
5153
5254![](/wiki-images/3/31/Load_security_warning_dmg_mavericks_en.png)
5355
5456Default settings are more strict in Mavericks, where they prevent downloaded unsigned apps from being started via double-clicking.
5557
5658![](/wiki-images/2/20/Load_security_warning_mavericks_context_en.png)
5759
5860If the application is launched via context menu in Mavericks a simple warning is displayed similar to that of earlier versions.
5961
6062![](/wiki-images/c/c3/Simple_load_security_warning_mavericks_en.png)
6163
6264Gatekeeper 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.
6365
6466![](/wiki-images/1/15/Codesigning.png)
6567
6668Overview of code-signing a program written with Lazarus and Free Pascal
6769
6870## Overview
6971
7072The basic steps to sign an application that has been written with Lazarus and/or Free Pascal are:
7173
72741. Obtain a Developer ID from Apple and install it in your system's key chain.
73752. Note the alphanumeric key of your Developer ID (aka TeamIdentifier).
74763. Sign your application with the *codesign* command.
75774. Sign your installer pkg with the *productsign* command.
7678
7779It 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).
7880
7981A macOS application distributed outside the Mac App Store will generally have 3–4 separate layers of signing:
8082
8183- The application itself will be code signed using an application certificate.
8284- If the application has an installer, the package file will be signed using an installer certificate.
8385- The disk image containing the application or installer will be signed using an application certificate.
8486- 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.
8587
8688## Gatekeeper requirements
8789
8890- 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.
8991
9092- All binary files inside MyApp.app should be code signed.
9193
9294- All binary files should be located in standard locations inside the MyApp.app bundle folder. Refer to the table below.
9395
9496| Location | Description |
9597|----|----|
9698| Contents | Top content directory of the bundle |
9799| Contents/MacOS | Main executable; helper apps and tools |
98100| Contents/Frameworks | Frameworks, dylibs |
99101| Contents/PlugIns | Plug-ins, both loadable and extensions |
100102| Contents/XPCServices | XPC services |
101103| Contents/Helpers | Helper apps and tools |
102104| Contents/Library/Automator | Automator actions |
103105| Contents/Library/Spotlight | Spotlight importers |
104106| Contents/Library/LoginItems | Installable login items |
105107| Contents/Library/LaunchServices | Privileged helper tools installed by the ServiceManagement framework |
106108
107109Standard locations for code inside a bundle
108110
109111Note: No non-binary files should ever be located in the folders specified in the table above.
110112
111113## Using codesign to sign your application
112114
113115**1.** Sign your application with:
114116
115117``` bash
116118codesign -f -o runtime --timestamp -s "Developer ID Application: YOUR NAME (TEAM_ID)" /path/to/bundle.app
117119```
118120
119121**2.** Display basic information about the result of the signing process:
120122
121123``` bash
122124codesign -dv -r- /path/to/bundle.app
123125```
124126
125127If your application was successfully signed this command will return information similar to this:
126128
127129 Executable=/Users/apple/Desktop/your.app/Contents/MacOS/yourappname
128130 Identifier=org.yourdomain.yourappname
129131 Format=app bundle with Mach-O thin (x86_64)
130132 CodeDirectory v=20500 size=101470 flags=0x10000(runtime) hashes=3164+3 location=embedded
131133 Signature size=9063
132134 Timestamp=7 Dec 2019 at 18:36:08
133135 Info.plist entries=16
134136 TeamIdentifier=<10 alpha numeric digits>
135137 Runtime Version=10.14.0
136138 Sealed Resources version=2 rules=13 files=45
137139 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>
138140
139141**3.** Verify your signature:
140142
141143``` bash
142144codesign -vv /path/to/bundle.app
143145```
144146
145147If 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.
146148
147149## Using productsign to sign your pkg installer
148150
149151**1.** Sign your installer pkg file with:
150152
151153``` bash
152154productsign --timestamp --sign "Developer ID Installer: YOUR NAME (TEAM_ID)" /path/to/unsigned.pkg /path/to/signed.pkg
153155```
154156
155157**2.** Verify your signature with:
156158
157159``` bash
158160spctl -vv --assess --type install /path/to/your.pkg
159161```
160162
161163which should yield information similar to this if it was successful:
162164
163165 your.pkg: accepted
164166 source=Developer ID
165167 origin=Developer ID Installer: YOUR NAME (<10 alpha numeric digits>)
166168
167169## Using codesign to sign your disk image
168170
169171Beginning 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.
170172
171173**1.** Sign your disk image with:
172174
173175``` bash
174176codesign -f -o runtime --timestamp -s "Developer ID Application: YOUR NAME (TEAM_ID)" /path/to/YourImage.dmg
175177```
176178
177179**2.** Verify your signature with:
178180
179181``` bash
180182spctl -a -t open --context context:primary-signature -vv /path/to/YourImage.dmg
181183```
182184
183185which should yield information similar to this if it was successful:
184186
185187 YourImage.dmg: accepted
186188 source=Developer ID
187189 origin=Developer ID Application: YOUR NAME (<10 alpha numeric digits>)
188190
189191**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:
190192
191193 YourImage.dmg: rejected
192194 source=Unnotarized Developer ID
193195 origin=Developer ID Application: YOUR NAME (<10 alpha numeric digits>)
194196
195197See [[Notarization for macOS 10.14.5+]] for more details.
196198
197199## Updating a signed file
198200
199201Whenever you update a signed file, create a new file. Do not copy a new signed file over an old signed file.
200202
201203Specifically, 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).
202204
203205## Ad hoc signing
204206
205207This 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:
206208
207-` codesign --force --deep -s - lazarus.app`
209+```
210+ codesign --force --deep -s - lazarus.app
211+```
208212
209213or to ad hoc sign an executable file:
210214
211-` codesign --force -s - lazarus`
215+```
216+ codesign --force -s - lazarus
217+```
212218
213219A single dash/hyphen on its own for the identity makes it an ad hoc signature with no certificate.
214220
215221You can check the validity of an ad hoc signed executable with:
216222
217-` codesign -dv -r- lazarus`
223+```
224+ codesign -dv -r- lazarus
225+```
218226
219227which should produce output similar to the below:
220228
221-`Executable=/Users/trev/lazarus-src/lazarus`\
222-`Identifier=lazarus`\
223-`Format=Mach-O thin (arm64)`\
224-`CodeDirectory v=20400 size=336137 flags=0x2(adhoc) hashes=10498+2 location=embedded`\
225-`Signature=adhoc`\
226-`Info.plist=not bound`\
227-`TeamIdentifier=not set`\
228-`Sealed Resources=none`\
229-`# designated => cdhash H"2e6f474452344d6fa42feee3db14a05c14d595a3"`
229+```
230+Executable=/Users/trev/lazarus-src/lazarus
231+Identifier=lazarus
232+Format=Mach-O thin (arm64)
233+CodeDirectory v=20400 size=336137 flags=0x2(adhoc) hashes=10498+2 location=embedded
234+Signature=adhoc
235+Info.plist=not bound
236+TeamIdentifier=not set
237+Sealed Resources=none
238+# designated => cdhash H"2e6f474452344d6fa42feee3db14a05c14d595a3"
239+```
230240
231241In 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::
232242
233-` CodeDirectory v=20400 size=336032 flags=0x20002(adhoc,linker-signed) hashes=10498+0 location=embedded`
243+```
244+ CodeDirectory v=20400 size=336032 flags=0x20002(adhoc,linker-signed) hashes=10498+0 location=embedded
245+```
234246
235247## Code signing an x86_64 binary on an aarch64 machine
236248
237249## How to install certificates on a second computer
238250
239251There are two ways to do this:
240252
2412531. using the Keychain Access application; and
2422542. using Xcode.
243255
244256### Using the Keychain Access application
245257
246258- 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.
247259
248260- 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.
249261
250262### Using Xcode
251263
252264- 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.
253265
254266- 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.
255267
256268## How to check what certificates are installed
257269
258270Once 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:
259271
260-`$ security find-identity -p basic -v`
272+```
273+$ security find-identity -p basic -v
274+```
261275
262276This 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.
263277
264278You can identify the certificates by the hexadecimal number or by the descriptive name, eg "Developer ID Application: Your Name (AB123456DE)"
265279
266280The 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.
267281
268282## See also
269283
270284- [[macOS Big Sur changes for developers|Code signing: Intel vs Apple Silicon]]
271285- [[Apple Developer Certificates]]
272286- [[Notarization for macOS 10.14.5+]]
273287- [[Hardened runtime for macOS]]
274288- [[Sandboxing for macOS]]
275289- [[Signing and Notarization FAQ]]
276290- [[macOS Gatekeeper Debugging Tips]]
277291
278292## External links
279293
280294- [Apple Developer portal](https://developer.apple.com/)
281295- [Apple: Code Signing Overview](https://developer.apple.com/support/technical/code-signing/)
282296- [Apple: Code Signing Guide](https://developer.apple.com/library/mac/documentation/Security/Conceptual/CodeSigningGuide/)
283297- [Apple: TN2206 - macOS Code Signing In Depth](https://developer.apple.com/library/archive/technotes/tn2206/_index.html)
284298- [Apple: Code signing x86_64 binaries on aarch64](https://developer.apple.com/forums/thread/673323).
285299
286300---
287301*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