Sign in Join
Wiki copytemporary

Code Signing for macOS: what changed

Revision 3 to 4. 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-```
38+```text
3939spctl developer-mode enable-terminal
4040```
4141
4242and 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.
4343
4444Intel 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.
4545
4646For more details, see: [[macOS Big Sur changes for developers|Big Sur changes for developers: Code signing - Intel vs M1]].
4747
4848## Gatekeeper Dialogs
4949
5050![](/wiki-images/2/26/Load_security_warning_dmg_leopard_en.png)
5151
5252Simple warning after opening a downloaded application in Leopard.
5353
5454![](/wiki-images/3/31/Load_security_warning_dmg_mavericks_en.png)
5555
5656Default settings are more strict in Mavericks, where they prevent downloaded unsigned apps from being started via double-clicking.
5757
5858![](/wiki-images/2/20/Load_security_warning_mavericks_context_en.png)
5959
6060If the application is launched via context menu in Mavericks a simple warning is displayed similar to that of earlier versions.
6161
6262![](/wiki-images/c/c3/Simple_load_security_warning_mavericks_en.png)
6363
6464Gatekeeper 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.
6565
6666![](/wiki-images/1/15/Codesigning.png)
6767
6868Overview of code-signing a program written with Lazarus and Free Pascal
6969
7070## Overview
7171
7272The basic steps to sign an application that has been written with Lazarus and/or Free Pascal are:
7373
74741. Obtain a Developer ID from Apple and install it in your system's key chain.
75752. Note the alphanumeric key of your Developer ID (aka TeamIdentifier).
76763. Sign your application with the *codesign* command.
77774. Sign your installer pkg with the *productsign* command.
7878
7979It 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).
8080
8181A macOS application distributed outside the Mac App Store will generally have 3–4 separate layers of signing:
8282
8383- The application itself will be code signed using an application certificate.
8484- If the application has an installer, the package file will be signed using an installer certificate.
8585- The disk image containing the application or installer will be signed using an application certificate.
8686- 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.
8787
8888## Gatekeeper requirements
8989
9090- 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.
9191
9292- All binary files inside MyApp.app should be code signed.
9393
9494- All binary files should be located in standard locations inside the MyApp.app bundle folder. Refer to the table below.
9595
9696| Location | Description |
9797|----|----|
9898| Contents | Top content directory of the bundle |
9999| Contents/MacOS | Main executable; helper apps and tools |
100100| Contents/Frameworks | Frameworks, dylibs |
101101| Contents/PlugIns | Plug-ins, both loadable and extensions |
102102| Contents/XPCServices | XPC services |
103103| Contents/Helpers | Helper apps and tools |
104104| Contents/Library/Automator | Automator actions |
105105| Contents/Library/Spotlight | Spotlight importers |
106106| Contents/Library/LoginItems | Installable login items |
107107| Contents/Library/LaunchServices | Privileged helper tools installed by the ServiceManagement framework |
108108
109109Standard locations for code inside a bundle
110110
111111Note: No non-binary files should ever be located in the folders specified in the table above.
112112
113113## Using codesign to sign your application
114114
115115**1.** Sign your application with:
116116
117117``` bash
118118codesign -f -o runtime --timestamp -s "Developer ID Application: YOUR NAME (TEAM_ID)" /path/to/bundle.app
119119```
120120
121121**2.** Display basic information about the result of the signing process:
122122
123123``` bash
124124codesign -dv -r- /path/to/bundle.app
125125```
126126
127127If your application was successfully signed this command will return information similar to this:
128128
129129 Executable=/Users/apple/Desktop/your.app/Contents/MacOS/yourappname
130130 Identifier=org.yourdomain.yourappname
131131 Format=app bundle with Mach-O thin (x86_64)
132132 CodeDirectory v=20500 size=101470 flags=0x10000(runtime) hashes=3164+3 location=embedded
133133 Signature size=9063
134134 Timestamp=7 Dec 2019 at 18:36:08
135135 Info.plist entries=16
136136 TeamIdentifier=<10 alpha numeric digits>
137137 Runtime Version=10.14.0
138138 Sealed Resources version=2 rules=13 files=45
139139 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>
140140
141141**3.** Verify your signature:
142142
143143``` bash
144144codesign -vv /path/to/bundle.app
145145```
146146
147147If 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.
148148
149149## Using productsign to sign your pkg installer
150150
151151**1.** Sign your installer pkg file with:
152152
153153``` bash
154154productsign --timestamp --sign "Developer ID Installer: YOUR NAME (TEAM_ID)" /path/to/unsigned.pkg /path/to/signed.pkg
155155```
156156
157157**2.** Verify your signature with:
158158
159159``` bash
160160spctl -vv --assess --type install /path/to/your.pkg
161161```
162162
163163which should yield information similar to this if it was successful:
164164
165165 your.pkg: accepted
166166 source=Developer ID
167167 origin=Developer ID Installer: YOUR NAME (<10 alpha numeric digits>)
168168
169169## Using codesign to sign your disk image
170170
171171Beginning 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.
172172
173173**1.** Sign your disk image with:
174174
175175``` bash
176176codesign -f -o runtime --timestamp -s "Developer ID Application: YOUR NAME (TEAM_ID)" /path/to/YourImage.dmg
177177```
178178
179179**2.** Verify your signature with:
180180
181181``` bash
182182spctl -a -t open --context context:primary-signature -vv /path/to/YourImage.dmg
183183```
184184
185185which should yield information similar to this if it was successful:
186186
187187 YourImage.dmg: accepted
188188 source=Developer ID
189189 origin=Developer ID Application: YOUR NAME (<10 alpha numeric digits>)
190190
191191**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:
192192
193193 YourImage.dmg: rejected
194194 source=Unnotarized Developer ID
195195 origin=Developer ID Application: YOUR NAME (<10 alpha numeric digits>)
196196
197197See [[Notarization for macOS 10.14.5+]] for more details.
198198
199199## Updating a signed file
200200
201201Whenever you update a signed file, create a new file. Do not copy a new signed file over an old signed file.
202202
203203Specifically, 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).
204204
205205## Ad hoc signing
206206
207207This 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:
208208
209-```
209+```text
210210 codesign --force --deep -s - lazarus.app
211211```
212212
213213or to ad hoc sign an executable file:
214214
215-```
215+```text
216216 codesign --force -s - lazarus
217217```
218218
219219A single dash/hyphen on its own for the identity makes it an ad hoc signature with no certificate.
220220
221221You can check the validity of an ad hoc signed executable with:
222222
223-```
223+```text
224224 codesign -dv -r- lazarus
225225```
226226
227227which should produce output similar to the below:
228228
229-```
229+```text
230230Executable=/Users/trev/lazarus-src/lazarus
231231Identifier=lazarus
232232Format=Mach-O thin (arm64)
233233CodeDirectory v=20400 size=336137 flags=0x2(adhoc) hashes=10498+2 location=embedded
234234Signature=adhoc
235235Info.plist=not bound
236236TeamIdentifier=not set
237237Sealed Resources=none
238238# designated => cdhash H"2e6f474452344d6fa42feee3db14a05c14d595a3"
239239```
240240
241241In 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::
242242
243-```
243+```text
244244 CodeDirectory v=20400 size=336032 flags=0x20002(adhoc,linker-signed) hashes=10498+0 location=embedded
245245```
246246
247247## Code signing an x86_64 binary on an aarch64 machine
248248
249249## How to install certificates on a second computer
250250
251251There are two ways to do this:
252252
2532531. using the Keychain Access application; and
2542542. using Xcode.
255255
256256### Using the Keychain Access application
257257
258258- 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.
259259
260260- 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.
261261
262262### Using Xcode
263263
264264- 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.
265265
266266- 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.
267267
268268## How to check what certificates are installed
269269
270270Once 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:
271271
272-```
272+```text
273273$ security find-identity -p basic -v
274274```
275275
276276This 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.
277277
278278You can identify the certificates by the hexadecimal number or by the descriptive name, eg "Developer ID Application: Your Name (AB123456DE)"
279279
280280The 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.
281281
282282## See also
283283
284284- [[macOS Big Sur changes for developers|Code signing: Intel vs Apple Silicon]]
285285- [[Apple Developer Certificates]]
286286- [[Notarization for macOS 10.14.5+]]
287287- [[Hardened runtime for macOS]]
288288- [[Sandboxing for macOS]]
289289- [[Signing and Notarization FAQ]]
290290- [[macOS Gatekeeper Debugging Tips]]
291291
292292## External links
293293
294294- [Apple Developer portal](https://developer.apple.com/)
295295- [Apple: Code Signing Overview](https://developer.apple.com/support/technical/code-signing/)
296296- [Apple: Code Signing Guide](https://developer.apple.com/library/mac/documentation/Security/Conceptual/CodeSigningGuide/)
297297- [Apple: TN2206 - macOS Code Signing In Depth](https://developer.apple.com/library/archive/technotes/tn2206/_index.html)
298298- [Apple: Code signing x86_64 binaries on aarch64](https://developer.apple.com/forums/thread/673323).
299299
300300---
301301*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