CODESIGN(1) | General Commands Manual | CODESIGN(1) |
codesign
— Create
and manipulate code signatures
codesign |
-s identity [-i identifier] [-r requirements]
[-fv ] path ... |
codesign |
-v [-R requirement] [-v ]
[path|pid ...] |
codesign |
-d [-v ]
[path|pid ...] |
codesign |
-h [-v ]
[pid ...] |
codesign |
--validate-constraint path ... |
The codesign
command is used to create,
check, and display code signatures, as well as inquire into the dynamic
status of signed code in the system.
codesign
requires exactly one
operation option to determine what action is to be
performed, as well as any number of other options to modify its behavior. It
can act on any number of objects per invocation, but performs the same
operation on all of them.
codesign
accepts single-character
(classic) options, as well as GNU-style long options of the form --name and
--name=value. Common options have both forms; less frequent and specialized
options have only long form. Note that the form --name value (without equal
sign) will not work as expected on options with optional values.
The options are as follows:
--all-architectures
-a,
--architecture
architecturecodesign
will always
sign all architectures contained in a universal Mach-O file.--bundle-version
version-stringcodesign
uses the bundle's default version. Note
that most frameworks delivered with the system have only one version, and
thus this option is irrelevant for them. There is currently no facility
for operating on all versions of a bundle at once.--check-notarization
-d,
--display
-D,
--detached
filename--deep
codesign
tool will only discover
nested code content in the following
directories:
--deep
option--deep
option on an iOS style bundle
without a Contents folder will not cause an error but will only sign
the main binary of the bundle.codesign
command.--detached-database
-f,
--force
codesign
to replace any
existing signature on the path(s) given. Without this option, existing
signatures will not be replaced, and the signing operation fails.--generate-entitlement-der
-h,
--hosting
-i,
--identifier
identifier-o,
--options
flag,...-P,
--pagesize
pagesize--remove-signature
-r,
--requirements
requirements-R,
--test-requirement
requirement-s,
--sign
identity-v,
--verbose
-v,
--verify
--continue
codesign
to continue processing path
arguments even if processing one fails. If this option is given, exit due
to operational errors is deferred until all path arguments have been
considered. The exit code will then indicate the most severe failure (or,
with equal severity, the first such failure encountered).--dryrun
--entitlements
path--xml
or
--der
may be passed in to output the entitlements
in a desired format, if you pass in both then DER will be printed. Use
"-" as the path to write to standard output. If the signature
has no entitlement data, nothing is written (this is not an error).--enforce-constraint-validity
--launch-constraint-*
or
--library-constraint
) are structurally valid and
contain only keys that are known on this version of macOS or properly use
the $optional operator. By default, constraints are checked and
errors are reported but their validity is not required. This default
behavior allows developers to set contraints for newer OS versions on the
current OS version.--extract-certificates
prefix--file-list
pathcodesign
writes to the given path a list of files that may have been modified as
part of the signing process. This is useful for installer or patcher
programs that need to know what was changed or what files are needed to
make up the "signature" of a program. The file given is
appended-to, with one line per absolute path written. An argument of
"-" (single dash) denotes standard output. Note that the list
may be somewhat pessimistic - all files not listed are guaranteed to be
unchanged by the signing process, but some of the listed files may not
actually have changed. Also note that changes may have been made to
extended attributes of these files.--ignore-resources
--keychain
filename--prefix
string--preserve-metadata=list
--strict
options--timestamp
[=URL]--runtime-version
version--launch-constraint-self
path--launch-constraint-parent
path--launch-constraint-responsible
path--library-constraint
path--strip-disallowed-xattrs
--single-threaded-signing
--validate-constraint
In the first synopsis form, codesign
attempts to sign the code objects at the path(s)
given, using the identity provided. Internal
requirements and entitlements
are embedded if requested. Internal requirements not specified may be
assigned suitable default values. Defaulting applies separately to each type
of internal requirement. If an identifier is
explicitly given, it is sealed into all path(s).
Otherwise, each path derives its identifier
independently from its Info.plist or pathname. Code nested within bundle
directories must already be signed or the signing operation will
fail, unless the --deep
option is given, in
which case any unsigned nested code will be recursively signed before
proceeding, using the same signing options and parameters. If the
--force
option is given, any existing top-level
signature is replaced, subject to any
--preserve-metadata
options also present. Combining
the --force
and --deep
options results in forcible replacement of all signatures within the target
bundle.
In the second synopsis form, codesign
verifies the code signatures on all the path(s) given.
The verification confirms that the code at those
path(s) is signed, that the signature is valid, and
that all sealed components are unaltered. If a
requirement is given, each path
is also checked against this requirement (but see DIAGNOSTICS below). If
verbose verification is requested, the program is also checked against its
own designated requirement, which should never fail for a properly signed
program.
If a path begins with a decimal digit, it is interpreted as the process id of a running process in the system, and dynamic validation is performed on that process instead. This checks the code's dynamic status and just enough static data to close the nominal security envelope. Add at least one level of verbosity to also perform a full static check.
In the third synopsis form, codesign
displays the contents of the signatures on the path(s)
given. More information is displayed as the verbosity level increases. This
form may not completely verify the signatures on the
path(s); though it may perform some verification steps
in the process of obtaining information about the
path(s). If the -r path option
is given, internal requirements will be extracted from the
path(s) and written to path;
specify a dash "-" to write to standard output. If the code does
not contain an explicit designated requirement, the implied one will be
retrieved and written out as a source comment. If the
--entitlements path option is given, embedded
entitlement data will be extracted likewise and written to the file
specified.
In the fourth synopsis form, codesign
constructs the hosting path for each pid given and
writes it, one host per line, to standard output. The hosting path is the
chain of code signing hosts starting with the most specific code known to be
running, and ending with the root of trust (the kernel). If the
--verbose option is given, the dynamic validity status
of each host is also displayed, separated from the path by a tab character.
Note that hosting chains can at times be constructed for invalid or even
unsigned code, and the output of this form of the
codesign
command should not be taken as a statement
of formal code validity. Only codesign
--verify can do that; and in fact, formal verification
constructs the hosting chain as part of its operation (but does not display
it).
In the fifth synopsis form, codesign
validates the path(s) supplied. Validation means
ensuring that keys and operators are properly structured with appropriate
types and that all keys and operators are known or nested in the
$optional operator.
To be used for code signing, a digital identity must be stored in
a keychain that is on the calling user's keychain search list. All keychain
sources are supported if properly configured. In particular, it is possible
to sign code with an identity stored on a supported smart card. If your
signing identity is stored in a different form, you need to make it
available in keychain form to sign code with it.
If the --keychain argument is used,
identity is only looked-for in the specific keychain
given. This is meant to help disambiguate references to identities. Even in
that case, the full keychain search list is still consulted for additional
certificates needed to complete the signature.
The identity is first considered as the full name of a keychain identity preference. If such a preference exists, it directly names the identity used. Otherwise, the identity is located by searching all keychains for a certificate whose subject common name (only) contains the identity string given. If there are multiple matches, the operation fails and no signing is performed; however, an exact match is preferred over a partial match. These comparisons are case sensitive. Multiple instances of the exactly same certificate in multiple keychains are tolerated as harmless.
If identity consists of exactly forty hexadecimal digits, it is instead interpreted as the SHA-1 hash of the certificate part of the desired identity. In this case, the identity's subject name is not considered.
Both identity preferences and certificate hashes can be used to identify a particular signing identity regardless of name. Identity preferences are global settings for each user and provide a layer of indirection. Certificate hashes are very explicit and local. These choices, combined with what is placed into Xcode project and target build variables and/or script settings, allows for very flexible designation of signing identities.
If identity is the single letter "-" (dash), ad-hoc signing is performed. Ad-hoc signing does not use an identity at all, and identifies exactly one instance of code. Significant restrictions apply to the use of ad-hoc signed code; consult documentation before using this.
codesign
will attempt to embed the entire
certificate chain documenting the signing identity in the code signature it
generates, including any intermediate certificates and the anchor
certificate. It looks for those in the keychain search list of the user
performing the signing operation. If it cannot generate the entire
certificate chain, signing may still succeed, but verification may fail if
the verifying code does not have an independent source for the missing
certificates (from its keychains).
The requirement(s) arguments (-r and -R) can
be given in various forms. A plain text argument is taken to be a path to a
file containing the requirement(s). codesign
will
accept both binary files containing properly compiled requirements code, and
source files that are automatically compiled before use. An argument of
"-" requests that the requirement(s) are read from standard input.
Finally, an argument that begins with an equal sign "=" is taken
as a literal requirements source text, and is compiled accordingly for
use.
When signing, a set of option flags can be specified to change the
behavior of the system when using the signed code. The following flags are
recognized by codesign
; other flags may exist at the
API level. Note that you can specify any valid flags by giving a (single)
numeric value instead of a list of option names.
Note that code can set the hard and kill flags on itself at any time. The signing options only affect their initial state. Once set by any means, these flags cannot be cleared for the lifetime of the code. Therefore, specifying such flags as signing options guarantees that they will be set whenever the signed code runs.
If the code being signed has an Info.plist that contains a key named CSFlags, the value of that key is taken as the default value for the options. The value of CSFlags can be a string in the same form as the --options option, or an integer number specifying the absolute numeric value. Note however that while you can abbreviate flag names on the command lines, you must spell them out in the Info.plist.
To sign application Terminal.app with a signing identity named "authority":
codesign --sign authority
Terminal.app
To sign the command-line tool "helper" with the same identity, overwriting any existing signature, using the signing identifier "com.mycorp.helper", and embedding a custom designated requirement
codesign -f --sign authority
--prefix=com.mycorp. -r="designated => anchor /tmp/foo"
helper
To enable the hardened runtime on Terminal.app and sign with the signing identity named "authority":
codesign --sign authority --options
runtime Terminal.app
To verify the signature on Terminal.app and produce some verbose output:
codesign --verify --verbose
Terminal.app
To verify the dynamic validity of process 666:
codesign --verify +666
To display all information about Terminal.app's code signature:
codesign --display --verbose=4
Terminal.app
To extract the internal requirements from Terminal.app to standard output:
codesign --display -r-
Terminal.app
To display the entitlements of a binary or bundle:
codesign --display --entitlements -
/sbin/launchd
codesign --display --entitlements -
--der Terminal.app
To display the entitlements of process 666:
codesign --display --entitlements -
+666
To display the XML entitlements of process 1337:
codesign --display --entitlements -
--xml +1337
To sign Terminal.app with an embedded launch constraint and an embedded library constraint:
codesign --sign authority
--launch-constraint-self self-constraint.plist --library-constraint
library-constraint.plist Terminal.app
To validate a set of constraint files before signing:
codesign --validate-constraint
self-constraint.plist library-constraint.plist
A common source of confusion when using
codesign
arises from the ordering of command line
options. If codesign
is not behaving as expected,
consult this manual and check the ordering of your arguments. As a general
rule codesign
follows a
verb noun
rule. For example --sign
should be placed before
--options
in the invocation. This is because you are
performing a "sign" action with a given set of options.
If these are inverted and --options
is
provided before --sign
in the invocation, the value
of --options
is ignored silently.
codesign
exits 0 if all operations
succeed. This indicates that all codes were signed, or all codes verified
properly as requested. If a signing or verification operation fails, the
exit code is 1. Exit code 2 indicates invalid arguments or parameters. Exit
code 3 indicates that during verification, all path(s) were properly signed
but at least one of them failed to satisfy the requirement specified with
the -R option.
For verification, all path arguments are always investigated
before the program exits. For all other operations, the program exits upon
the first error encountered, and any further path arguments are ignored,
unless the --continue option was specified, in which case
codesign
will defer the failure exit until after it
has attempted to process all path arguments in turn.
When a signing operation fails for a particular code, the code may
already have been modified in certain ways by adding requisite signature
data. Such information will not change the operation of the code, and the
code will not be considered signed even with these pieces in place. You may
repeat the signing operation without difficulty. Note however that a
previous valid signature may have been effectively destroyed if you
specified the -f option.
If you require atomicity of signing stricter than provided by
codesign
, you need to make an explicit copy of your
code and sign that.
If the CODESIGN_ALLOCATE environment variable is set, it identifies a substitute codesign_allocate tool used to allocate space for code signatures in Mach-O binaries. This is used by Xcode SDK distributions to provide architectural support for non-native platforms such as iPhones. The system will not accept such substitutes unless they are specially signed (by Apple).
The codesign
command first appeared in Mac
OS 10.5.0 (Leopard).
Some options only apply to particular operations, and
codesign
ignores them (without complaining) if you
specify them for an operation for which they have no meaning.
The --preserve-metadata option used to take no value, and varied across releases in what exactly it preserved. The ensuing confusion is still with you if you need to make backward-compatible scripts.
The dual meaning of the -v option, indicating either verbosity or verification, confuses some people. If you find it confusing, use the unambiguous long forms --verbose and --verify instead.
The --verify
option can take either a file
or a pid. If your file path starts with a number you should prefix it with
"./" to force codesign
to interpret the
argument as a path. For example:
codesign --verify 666
codesign --verify ./666
The Xcode build system invokes codesign
automatically if the CODE_SIGN_IDENTITY build variable is set. You can
express any combination of codesign
options with
additional build variables there.
codesign
is fundamentally a shell around
the code signing APIs, and performs nothing of the underlying work.
Replacing it with older or newer versions is unlikely to have a useful
effect.
codesign
has several operations and
options that are purposely left undocumented in this manual page because
they are either experimental (and subject to change at any time), or
unadvised to the unwary. The interminably curious are referred to the
published source code.
May 7, 2011 | macOS 14.6 |