The original address

About Code signing

Code signing is a macOS security technique that you use to prove that an app was created by you. Once an application is signed, the system can detect any changes to the application, whether caused by accident or malicious code.

Note: In most cases, you can rely on XCode’s automatic code signing, which simply requires specifying a code signing identifier for your project in the build Settings. This document is intended for readers who go beyond automatic code signing — perhaps to solve unusual problems, or to integrate a signing tool into a build system.

Benefits of code signing

After installing a signed new version of the app, users are no longer bothered by being allowed access to keystrings and similar prompts. As long as the new version uses the same digital signature, macOS will treat the new version as exactly the same as the previous one.

Other MacOS security features, such as application sandboxes and parental controls, also rely on code signatures. Specifically, code signing allows the operating system to:

  • Ensure that a piece of code has not been modified since it was signed. The system can detect even the smallest change, whether it is intentional (from a malicious attacker, for example) or accidental (a file is corrupted). When the code signature is intact, the system can ensure that the code conforms to the signer’s intent.
  • Identify code from the specified source (developer or signer). Code signatures contain encrypted information that is explicitly directed to a particular author.
  • Determine whether code can be trusted for a particular purpose. In addition, developers can use code signatures to declare that newer versions of their applications should be treated as identical to previous versions.

Limitations of code signing

Code signing is a component of a complete security solution that works in conjunction with other technologies. It doesn’t solve all security problems. For example, code signing cannot:

  • Make sure your code is bug free.
  • Ensure that the application does not load unsafe or altered code — such as untrusted plug-ins during execution.
  • Provides digital rights management (DRM) or copy protection technology. Code signing does not hide or obscure the content of the signed code in any way.

Please refer to the

Read the security Overview to understand where code signatures fit in the macOS security diagram

See CoDesign and CSREq for instructions on command-line tools that perform code signing

Understand code signing

A wide variety of code can be signed, including tools, applications, scripts, libraries, plug-ins, and other code-like data. In addition, you can create signature installation packages, and signature disk images. In most cases, a code signature consists of three parts:

  • Seal. This is a collection of checksums or hashes of various parts of code, created by code signing software. Seals can be used to detect changes during the validation phase.
  • Electronic signature. Code signing software creates a digital signature by encrypting and sealing it using the signer’s identity. This ensures the integrity of the seal.
  • Code requirements. These are the rules that govern the validation of code signatures. Some are inherent to the validator (depending on its goal). Others are specified by the signer and sealed with remaining codes.

seal

The code signing machine creates a seal by running different parts of your final package (application, library, or framework), including executables, resource files, info.plist files, code requirements, and so on, through a one-way hash algorithm. This produces a series of numbers, or checksums, which are short strings of numbers that mark the uniqueness of the input block but cannot be used to recover the original input.

A checksum entity consists of the collection of the code being checked and the corresponding hash values, which are hashed using the same algorithm as the signer, and compared to the original saved hash value to see if there are any changes. Even small changes in the code can result in different hashes, indicating tampering or corruption. However, the reliability of this validation depends on the reliability of the stored hash. And digital signatures guarantee that.

A digital signature

As described in the Security Overview, digital signatures use public key encryption to ensure data integrity. Like a signature written in ink on paper, digital signatures can be used to identify and verify signers. Digital signatures, however, are harder to forge, and further: they ensure that signature data has not been altered. This is a bit like designing a paper check or money order, where if someone changes the written amount, you can see a watermark with the word “invalid” on the paper.

In the context of code signing, signing software creates a digital signature by encrypting a sealed hash with the signer’s private key. Because only the signer has the private key, only the signer can perform this encryption. It is this encrypted hash set that the signer is stored in the application (or framework, archive, or other signature object) and the matching certificate that collectively represents the digital signature.

To verify the signature, the validation software computes the same hash set on various code and data blocks. It then uses the signer’s public key embedded in the certificate to decrypt the encrypted hash attached to the code, thereby obtaining the original hash computed by the signer. If the two hashes match, the data is not modified because it is signed by the person who has the signer’s private key.

While the code signing process is not strictly required to take place, the certificate itself is usually signed by a trusted certification authority. If not, the verifier can determine the stability of the certificate from one version to another, not the stability of its source. If so, the certification authority (usually Apple) will vouch for the identity of the signer.

The signature code may contain multiple different digital signatures:

  • If the code is generic, the object code for each schema is signed separately. This signature is stored in the binary itself.
  • The various data components of the application package (such as info.plist files, if any) are also signed. These signatures are stored in a file named _CodeSignature/CodeResources in the bundle.
  • The nested code (such as libraries, assistive tools, and other code embedded in the application) is itself signed, and its signature is also stored in the _CodeSignature/CodeResources bundle.

Signature required

Code requirements are the rules macOS uses to evaluate code signatures. Depending on its goals, the system performing the evaluation decides which code requirements to apply in the evaluation. For example, Gatekeeper has a rule that before an application can be allowed to launch for the first time, it must be signed by a Mac App Store or developer ID certificate. Another example is that an application can enforce a code requirement that all plug-ins used by the application should be signed by Apple.

Code requirements specified by the signer and included as part of the code signature are called internal requirements. These can be used to validate a code-signed system, but the system can choose whether to use them or not. The application plug-ins in the previous example may have their own internal requirements, but it is up to the evaluation system (the application that uses the plug-in) to decide whether to apply them. Since the seal covers the specification requirements, as long as the signature is valid, the internal requirements must also be complete.

The most important internal requirement is the specified requirement or DR. This rule tells the evaluation system how to recognize a particular piece of code. Any two pieces of code with (and successfully verified) the same DR are considered the same code. This allows the code signer to publish a new version of the application that is considered a new version of the same application. For example, Apple Mail’s DR might be “signed by Apple with identifier com.apple.mail.” When a new version of an application is released, as long as the new version of the application has the same DR, it is still considered Apple Mail, even if the binary executables are completely different. In addition, only Apple could sign Apple, so no one else could make an application masquerading as a Mail application.

Program identifiers or entire specified requirements may be explicitly specified by the signer. Typically, the signature mechanism automatically builds specified requirements using the name of the program found in its info.plist file as the CFBundleIdentifier and the signature chain that protects the code signature.

Code requirements are actually scripts written in a specialized language that describe the conditions (limitations) that code must meet before it can be accepted for some purpose. For a detailed description of the code requirement scripting language, see Code Signing Requirement Language.

Code signature evaluation

When the macOS subsystem needs to determine whether it is safe to trust the code for certain purposes, it validates the signed code against a set of requirements. As described in digital signatures, internal requirements, especially specified requirements, come from the code signature itself. Other requirements are inherent to the system being validated.

Table 2-1 shows concrete examples of how different subsystems in macOS use code signing to enforce trust policies specific to one system resource. Note that these are the default behaviors; You can modify many of macOS’s code signing policies using the SPCTL (8) command.

Table 2-1 Examples of macOS subsystems that verify code validity