This article is about digitally signing executable code and converting the required public/private key and X.509 certificate material between different formats using the OpenSSL toolkit. It adds to the information in my earlier article “Converting Microsoft .pvk Private Keys to Java Keystore”. If this kind of stuff makes your eyes glaze over, you might want to skip this one :-)
Benefits of Signing Applications on Mac OS X
The latest version 10.5 (Leopard) of Mac OS X adds the ability to digitally sign executable code. I wanted to do that with one of our Mac OS X applications, the image uploader for our snapmania Online Photo Manager.
Right now, the main user-visible benefit of signed applications is that accessing objects in the user’s Keychain no longer triggers this confirmation dialog after a new version of the application is installed:
I recently added Sparkle-based auto-updating to this application and the update user experience is now really smooth except for this Keychain dialog. Getting rid of it by digitally signing the application promises even less mental friction for the user.
Preparing the Certificate
The Apple developer tool used to sign an application is the codesign command line utility (check out its man page for details). In order to sign an application with it, you need a code signing certificate from a certificate authority trusted by the system. As noted in my earlier article, we already have such a certificate in the format used by Microsoft’s tools. Our provider in this case is the Thawte Code Signing CA and they are in Mac OS X’s list of trusted CAs.
codesign expects the certificate and associated private key in your keychain. The way to get them in there is by packaging them up in a PKCS#12 container file which Keychain can import. I’ll use the Swiss Army Knife of cryptography, the openssl command line tool, to do the conversion.
I had already converted the private key from Microsoft’s .pvk format into openssl RSA PEM format for the Java conversion the last time around. Let’s take a look:
$ openssl rsa -text < futurelab-codesign.privkey.rsa.pem Enter pass phrase: Private-Key: (2048 bit) ... fancy prime number ...
I didn’t have to convert the certificate for Java the last time because the Java tools can import Microsoft .spc (Software Publisher Certificate) files directly. It turns out that .spc files are PKCS#7 containers, so I can take a look at it with openssl’s pkcs7 command:
$ openssl pkcs7 -inform der -text -print_certs < futurelab-codesign.spc
I am checking out two things, namely if the certificate is still within its validity period and if the X.509 extensions for code signing are present:
Subject: C=CH, ST=ZH, L=Winterthur, O=futureLAB AG, OU=ENGINEERING, CN=futureLAB AG
Issuer: C=ZA, O=Thawte Consulting (Pty) Ltd., CN=Thawte Code Signing CA
Validity
Not Before: Nov 14 00:00:00 2007 GMT
Not After : Nov 25 23:59:59 2008 GMT
...
X509v3 extensions:
X509v3 Extended Key Usage:
Code Signing, Microsoft Commercial Code Signing
Netscape Cert Type:
Object Signing
In our case there are several certificates in the .spc file because it’s a “certificate chain” which includes the certificates of the intermediate subjects in the trust hierarchy. The one whose Subject: refers to our orgainzation is the actual code signing certificate we are going to use.
Now that I know that the certificate is valid, I can convert the entire certificate chain to a text file with a series of X.509 PEM format certificates:
openssl pkcs7 -inform der -print_certs \ < futurelab-codesigning.spc \ > futurelab-codesigning.cert.pem
With the private key and certificate data converted I can merge them into the PKCS#12 container:
openssl pkcs12 -export -inkey futurelab-codesign.privkey.rsa.pem \ -in futurelab-codesign.cert.pem \ -out futurelab-codesign.p12 Enter pass phrase for futurelab-codesign.privkey.rsa.pem: Enter Export Password: Verifying - Enter Export Password:
The “pass phrase” is what protects the contents of the RSA key input file, enter what you used when you created that file. The “Export Password” is something which you can choose freely here, it protects the private key in the PKCS#12 container.
Double-clicking the resulting .p12 file opens it in Keychain which will prompt for the export password used in the previous step. The imported certificate should look like this:
And again, it should have the code sign extension flags set:
Signing the Application
Signing the application with codesign is straightforward:
$ codesign -s 'futureLAB AG' Uploader.app
Verifying the signature:
$ codesign --verbose -v Uploader.app Uploader.app: valid on disk
I automated this in Xcode with an additional “Run Script” build phase that uses the variables $TARGET_BUILD_DIR and $WRAPPER_NAME:
The “Transition Notes” in Apple’s “Leopard Code Signing Release Notes” explain that the first update to a signed application version will trigger the Keychain dialog one last time:
Existing keychain items that allow access to a prior (unsigned) version of your application or tool will trigger a confirmation dialog when the system first encounters an updated signed version of your code. Upon user consent, the ACL is then rewritten to add access to your application gated by its code signature. No further dialogs should appear for that item afterwards, ever (unless you stop signing your updates). New items created by or for a signed application automatically have this benefit.
Resources
- Apple Code Signing Guide
- Leopard Code Signing Release Notes
- The openssl and codesign man pages
|


