Signing Manager Admin Guide
Current Version: 1.2
Signing Manager is a macOS application for code signing and package signing using remote identities. It includes a CryptoTokenKit extension for presenting X.509 certificates to the macOS keychain for use in cryptographic signing operations using built in commands such as
productsign. It can be customized for use with an external system or used with the signing service provided as part of the Signing Manager project.
Client: macOS 10.14 or later.
Server: macOS, Linux, or Windows system capable of running Node.js 12 or later.
Certificate and private keys for signing macOS, iOS, watchOS, and iPadOS code and packages.
Signing Manager is distributed as a disk image (dmg) that contains a standard macOS installer package.
To install the package in Finder:
- Double click on the disk image to mount it in Finder.
- Double click on the package in the mounted disk image to start installing the package.
Follow the prompts in the installer package to complete installation.
To install the package via the command line, use the
The macOS installer consists of three major components:
- macOS app ("Signing Manager.app") installed in the
- CryptoTokenKit extension installed in the Signing Manager.app bundle
- CCID driver for notifying macOS to add and remove certificates from the keychain. Installed in
/usr/local/lib/pcsc/drivers/serial/ifd-virtualserial.bundle. The configuration file for this driver is installed in
The installer requires a restart due to the initial installation of the CCID driver.
Signing Service Installation
The server is a Node.js application that runs on macOS, Linux, and Windows. The Node application is bundled with a runtime version of Node for easy deployment. If you are familiar with deploying Node applications, the Node script can be installed from source.
Signing Service Components
The signing service consists of:
signing_service: Node application binary
settings.json: Settings JSON file that contains the API keys, certificates and private keys, and other settings
server.key: Private key for the SSL certificate used to secure communications
server.cert: Certificate for securing communications
keychain_sign(macOS only): Binary to use identities in the macOS keychain for signing
Download the signing service zip file from https://bitbucket.org/twocanoes/signing-manager/downloads/ that is the same build number as the client you are deploying. The zip file contains 3 folders: macOS, Windows, and Linux. Each folder contains the platform specific binary and a sample configuration file.
Generate Self Signed SSL Certificate (optional)
In order to secure communications between the clients and the signing server, an SSL certificate is required. If you are not able to obtain an SSL certificate from a trust authority, a self signed SSL certificate can be used. To generate a self signed certificate, open Terminal in macOS and run this command:
openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.pem
You will be prompted for information about the certificate. All values except for Common Name can be left blank. For Common Name, enter the computer name of computer that will be hosting the signing service with an extension of
.local. For example:
server.pem and the
server.key to the platform-specific folder you downloaded in the prior step.
settings.json in the platform-specific folder with a text editor and update the sections as outlined below.
settings.json file has 3 top level elements:
api_keys: (Dictionary) Each dictionary key is an API key. The corresponding dictionary value for each is a text descriptor of that API key.
identities: (Array of dictionaries) Each dictionary has 3 keys:
cnis the subject name of a certificate.
certificatekey is the certificate in PEM format.
keyis the unencrypted private key in PEM format.
keychain_identity_fingerprints(optional) : (Array of dictionaries) Each dictionary must have a key called
sha1_hashwith a value that is a SHA1 hash (or fingerprint) of an identity in the macOS keychain. This key is only applicable if the signing service is running on macOS. If this key is defined and the service is started with the keychain option enabled (
-k), then the
identitieselement is not used and all signing operations are done with the macOS keychain of the Mac upon which the signing service is running.
keychain_identity_fingerprints dictionaries optionally can have an additional key called
api_keys that can be used to restrict access to some identities to a subset of API keys. The
api_keys should be defined as an array of API keys. Any identity that does not define
api_keys will be available to a valid request using any of the API keys defined on the top-level of
The API keys can be any unique string. It is recommended to use a UUID to guarantee that the API key is unique. A UUID can be generated by running
uuidgen in Terminal on macOS.
The identities arrays consists of a dictionary with 3 keys. To populate this dictionary from an identity in the macOS keychain, follow these steps:
- Open the macOS keychain that contains the macOS signing identity. Select the identity and choose File->Export Items...
- Save the exported identity as "SigningManagerID.p12". Make sure that the format to export is P12.
- Keychain Access will prompt for a passphrase to encrypt the P12. Create a P12 passphrase and enter it when prompted.
- Keychain Access will then prompt for the login password to export the identity. Enter the login password when prompted.
Windows and Linux installations require the identity to be put in the
settings.jsonfile. For macOS, the identities must be imported into the keychain on the signing service computer.
For Windows and Linux:
The P12 must now be converted to an unencrypted PEM file. Enter the following command in macOS Terminal to convert the P12 to a PEM text file, removing the passphrase:
openssl pkcs12 -in SigningManagerID.p12 -out SigningManagerID.pem -nodes
settings.json file and populate
key with the values in the exported pem file. Make sure to include the headers and footers of the certificate and private key (the lines that have BEGIN and END in them).
Install the exported identity to the keychain on the Mac that will run the signing service. In Keychain Access, open the certificate and copy the SHA-1 fingerprint of the certificate at the very bottom of the certificate. Add the fingerprint to the
keychain_identity_fingerprints array in the
settings.json file, removing all whitespace between the characters.
In Keychain Access, select the
My Certificates category and select the disclosure triangle next to the imported identity. Double click on the private key and select the
Access Control tab. Click
+ and select
keychain_binary in the macOS folder of the signing service. This gives access to "keychain_binary" to do signing operations without prompting for a password.
The service is now ready to be started. Open the command line interface and change to the directory that has the signing service binary and run the command below. If you are not using an SSL certificate to secure the signing service, do not use the
-s flag. If a network port besides 3000 is required, specify it with the
-p option and provide the port as the argument (for example
-p 3333). If you want to use the macOS Keychain option add
-k and add
macOS and Linux:
nohup ./signing_service -s &
Note that if you get an error message on macOS Catalina or later about not being able to check the binary for malware, you can clear the quarantine flag by running:
xattr -d com.apple.quarantine signing_service
After clearing the flag, try starting the service again.
A future release will provide a way to automatically start these services after reboot.
To verify the service is up and running, go a web browser on a different machine and enter the URL of the signing service. For instance, if the signing service is at 192.168.1.100, enter:
If you are using a self-signed certificate, you may be prompted to allow the connection. Once you allow it, you should see a success message.
Now that the signing service is running and accepting network connections, you can configure the macOS clients for signing operations. Configuration can be done either in the Preferences of the Signing Manager app or on the command line.
Launch the Signing Manager in
/Applications. If there are no preferences specified, the preferences window will automatically be shown. If it is not shown, select Preferences from the Signing Manager menu.
In the Preferences window, provide the URL to the signing service and an API key from
settings.json. If you are using a self-signed certificate for the signing service, select the
Trust Self Signed Certificates checkbox.
The preferences can be set using the command line. The command line tool is located in the application bundle. Run it with the
-h option to see the available options. Note that you must include the quotes due to the spaces in the application name.
"/Applications/Signing Manager.app/Contents/MacOS/Signing Manager" -h -s Save settings. Requires -i and -a. Optionally use -d. -i <api host url> Specify host for API signing operations. -a <api_key> Specify api key for accessing signing service. -u trust self-signed certificates. -d debug logging -r refresh and display available certificates. -p print configuation. -h this message.
-u options, set the preferences. For example, with a host URL of
https://signingserver.local:3000, an API key of
XYZ123, and trusting self-signed certificates:
"/Applications/Signing Manager.app/Contents/MacOS/Signing Manager" -s -i https://signingserver.local:3000 -a XYZ123 -u
To verify the settings, use the
"/Applications/Signing Manager.app/Contents/MacOS/Signing Manager" -p api_host: https://signingserver.local:3000 trust self signed: true debug: false API key: Set
Note that the API key is not shown, but can be found in the macOS keychain under
Once the settings have been entered, click OK.
Using Signing Manager
Now that the signing service has been set up and the client is configured, applications and packages can now be signed. If no certificates are showing in the main interface of Signing Manager, click
Refresh on the toolbar.
To refresh available certificates on the command line, run:
"/Applications/Signing Manager.app/Contents/MacOS/Signing Manager" -r
A list of available certificates and the SHA-1 fingerprints will be shown.
To sign an app, select a certificate in the main interface and click
Copy codesign command, then paste it into Terminal. Append the path to the application you want to sign and press return. For example:
codesign -fs "74FD9E670CFB7C906630B49FD26591CD66C66D79" ~/Documents/Projects/MyApp.app
Verify the signature by running codesign with the
codesign -dvvv ~/Documents/Projects/MyApp.app
To sign an installer package, select a certificate in the main interface and click
Copy productsign command, then paste it into Terminal. Replace
destination.pkg with a package to sign and a destination. For example:
productsign --sign "125F19515E25FA23CC1BA82E3E7A09D0A2097980" source.pkg destination.pkg
Verify the signature by double clicking on the signed package, then clicking on the certificate icon in the upper right corner of the first window of the installer.