So you want to sign your XPI package?


Author: Pete Collins
Company: Mozdev Group Inc.
Contact: pete at mozdevgroup dot com
URL: www.mozdevgroup.com
Date Modified: December 29, 2006

After a couple of days of pain, I've decided to write up a doc on how I was able to successfully sign an xpi using a test cert. For no better reason than I know I will forget by next week and honestly I wouldn't want to wish the pain I endured doing this on others.

[These docs are focused on Unix'y type systems]

For doing this on Windows: TJ's Docs

This doc is intended as an exercise to show how to sign an XPI package, you will need to obtain a valid certificate from an established certificate authority (CA) such as Verisign if you want to distribute signed XPI packages.

Addendum

If you already have a  class 3 object signing cert from a CA such as Verisign, then follow steps 1 and 2 and then move on to the Addendum.


Step 1 - Build NSS

First off you will need to fetch and compile the NSS tools you will need to do this. Sorry, there is no way around this.

There are some binary distributions here:

  ftp://ftp.mozilla.org/pub/mozilla.org/security/nss/releases/NSS_3_9_RTM/

But I decided to grab and compile them on my own as I am a Mozilla developer and we do such things ...

Build Instructions for NSS 3.9 Release

  http://www.mozilla.org/projects/security/pki/nss/nss-3.9/nss-3.9-build.html

Read over the above build instructions and follow to build NSS. One thing to keep in mind, some systems don't have gmake (it is simply called make) so obviously you would just use "make".  Type "make --version" to ensure you have GNU make installed.

Step 2 - Set up your Environment

Anyway, after you have successfully compiled the NSS tools, you will need to put them somewhere on your system. I didn't feel like having them installed in /usr/local so I did this from the tip of my Mozilla source tree.

  $ mkdir ~/nss
  $ cd dist/Linux2.4_x86_glibc_PTH_DBG.OBJ
  $ cp bin/* ~/nss
  $ cp lib/* ~/nss

Now I have all the NSS tools and libs I need in ~/nss.

Now, you will need to set up your env in order to use these tools.

  $ export PATH=$PATH:~/nss
  $ export LD_LIBRARY_PATH=~/nss

Step 3 - Create a database

Ok, before you even start, you need to set up a database using "certutil"

  $ cd ~
  $ mkdir test
  $ cd test
  $ mkdir db
  $ certutil -N -d db
    <enter a new password>

Step 4 - Create a Test Certificate

  $ signtool -G myTestCert -d db -p"mypassword"
    <answer the questions>
    y
    mycert
    my organization
    my software products
    my state
    my country
    pete
    myemail@mydomain.com

...

Exported certificate to x509.raw and x509.cacert

You should now see the files: "x509.cacert" and  "x509.raw"   x509.cacert will be used to sign your XPI package.

Let's make sure the cert is in the database:

  $ certutil -d db -L
[outputs]
myTestCert                                                   u,u,Cu

Step 5 - Prepare XPI Files for Signing
 
Now that we have a valid temporary test certificate we need some code to sign.

  $ mkdir test
  $ cd test/
  # copy over the xpi I want to test sign
  $ cp /mozdev/jslib/downloads/xpi/jslib_current.xpi .
  $ unzip jslib_current.xpi
  $ rm jslib_current.xpi
  $ cd ../

Step 6 - Actually sign the XPI

  $ signtool -d db -k myTestCert -p "mypass" test/

[output]

using certificate directory: db
Generating test//META-INF/manifest.mf file..
--> install.rdf
--> components/jslib-dom.js
--> components/jslib.xpt
--> components/jslib-service.js
--> install.js
--> chrome/jslib.jar
--> chrome/jsliblive/jsliblive.xul
--> chrome/jsliblive/contents.rdf
Generating zigbert.sf file..
tree "test/" signed successfully

Step 7 - Repackage the Signed XPI

Now if you got this far you are doing wonderfully well. Last step is to repackage the signed XPI.

  $ cd test
  $ zip test.xpi META-INF/zigbert.rsa
  $ zip -r -D test.xpi * -x META-INF/zigbert.rsa
  $ mv test.xpi ../
  $ cd ..

Step 8 - Install the Test certificate to test the XPI

This step requires you install the test certificate you generated into your browser.

  1. From your Mozilla based browser, browse your local file system to ~/test.
  2. Click on the link that says "x509.cacert" a "Downloading Certificates" dialog appears.
  3. Click on the checkbox that says "Trust this CA to identify software developers"
  4. Click "View" to view the test cert you created
  5. Click OK
Your test cert is now installed in your Mozilla browser. If you now click on the test.xpi file it will say "my organization" instead of "unsigned".

Now quickly go and remove the test certificate you installed:

  Edit->Preferences->Privacy and Security->Certificates->Authorities->my cert

Just click on "my cert" and then delete, then OK buttons.


Well that's it ...

Following these instruction will hopefully save you some time and more importantly unnecessary pain. 

--pete

Addendum

This section assumes that:

  1. You already have a class 3 object signing cert installed in your browser db.
  2. That you have followed the instruction of the CA and you can view your cert under "Your Certificates" in you browser security preferences.

To verify you have indeed properly installed the cert you obtained from your CA:

Mozilla Suite
edit->preferences->Privacy and Security->Certificates->Manage Certificates->Your Certificates


Firefox
edit->preferences->Advanced->View Certificates->Your Certificates

You should see your certificate listed there. If you don't then you haven't properly installed the certificate provided from you CA. The CA provides all the required docs to do this so please reread their docs.

If all this is correct, continue with the steps below.

Addendum Step 5 - Prepare XPI Files for Signing
 
Now that we have a valid object signing certificate obtained from a CA, we need some code to sign.

  $ mkdir test
  $ cd test/
  # copy over the xpi I want to test sign
  $ cp /mozdev/jslib/downloads/xpi/jslib_current.xpi .
  $ unzip jslib_current.xpi
  $ rm jslib_current.xpi


Addendum Step 6 - Actually sign the XPI

  $ signtool -d ~/.mozilla/default/erzu63ed.slt -k "Mozdev Group Inc.'s VeriSign, Inc. ID" -p "mypassword" .

[output]
using certificate directory: /home/petejc/.mozilla/.mozilla/default/erzu63ed.slt
Generating ./META-INF/manifest.mf file..
--> chrome.manifest
--> install.rdf
--> components/jslib-dom.js
--> components/jslib.xpt
--> components/jslib-service.js
--> install.js
--> chrome/jslib.jar
--> chrome/jsliblive/jsliblive.xul
--> chrome/jsliblive/contents.rdf
Generating zigbert.sf file..
tree "." signed successfully

Note: I am using the nickname "Mozdev Group Inc.'s VeriSign, Inc. ID". It is important to use the correct nickname, as it is the identifier of your cert. If you aren't sure what you nick is, then issue this command to look for it.

  $ certutil -L -d ~/.mozilla/default/erzu63ed.slt

[output]
Thawte Personal Freemail Issuing CA - Thawte Consulting      ,c,
Comodo Class 3 Security Services CA - GTE Corporation        ,c,
GeoTrust True Credentials CA 2 - Equifax Secure Inc.         ,c,
VeriSign Class 3 Code Signing 2004 CA - VeriSign, Inc.       c,,c
Personal Freemail RSA 2000.8.30 - Thawte Consulting          ,c,
Intranet Certificate Authority - GTE Corporation             ,c,
Mozdev Group Inc.'s VeriSign, Inc. ID u,u,u
As you can see my cert nickname listed above.


Addendum Step 7 - Repackage the Signed XPI

Now if you got this far you are doing wonderfully well. Last step is to repackage the signed XPI.

  $ zip test.xpi META-INF/zigbert.rsa
  $ zip -r -D test.xpi * -x META-INF/zigbert.rsa
  $ mv test.xpi ../
  $ cd ..
  $ ls


Since these steps are laborious,  the first thing I did was write a shell script to do all this automatically and use it as part of my build system as we tend to deliver signed xpi's to clients like factory work.

Good luck signing your packages ...

--pete