This article describes how to sign your own Firefox extensions with a code-signing certificate on a Windows platform. It was developed from the linux article So you want to sign your XPI package? by MozDev Group's Pete Collins.
This article is a mirror of the original, with minor reformatting, some new info and all links updated in March 2010.
Get network security services
1. Download the latest Network Security Services (NSS) package from the Mozilla FTP site at
ftp://ftp.mozilla.org/pub/mozilla.or.../nss/releases/. For Windows, you'll want the
nss-3.11.4.zip package in the
NSS_3_11_4_RTM/msvc6.0/WINNT5.0_OPT.OBJ/ folder - it is by 2010 the only one with the right binaries.
2. Extract the contents of the archive file to a local folder. In my case it's
Get Netscape Portable Runtime
1. Download the latest Netscape Portable Runtime from the Mozilla FTP site:
http://ftp.mozilla.org/pub/mozilla.org/nspr/releases/. For Windows you'll want the nspr-4.6.zip package in the
2. Extract the contents of the archive file to a local folder. In my case it's
Add the NSS tools bin/ and lib/, and the NSPR lib/ directories to the system path. You can either set this permanently via Control Panel->System Properties->Advanced->Environment Variables->System Variables or do it each time you run the tools from the command-line (preferably using a batch file). Windows contains its own version of some of these files (e.g. certutil.exe) in the system directory (
\Windows\system32\) so ensure the new paths are first in the PATH search list.
C:\> set PATH=C:\Apps\nss-3.11.4\bin\;C:\Apps\nss-3.11.4\lib\;C:\Apps\nspr-4.6\lib\;%PATH%
An easier way is to copy everything from your new directories C:\Apps\nss-3.11.4\ and C:\Apps\nspr-4.6\ including sub directories to the same directory - fx C:\Apps\CodeSigning\ - and then run every command from that.
Initialize the certificate database
Decide which folder to create the certificate database in. Use this command to create it (note the trailing dot is required).
C:\Projects\CodeSigning\> certutil -N -d .
The dot will cause the database to be created in the current directory.
You will be prompted for the NSS Certificate database password - don't forget it!
C:\Projects\CodeSigning\> certutil -N -d . Enter a password which will be used to encrypt your keys. The password should be at least 8 characters long, and should contain at least one non-alphabetic character. Enter new password: Re-enter password:
Create a test certificate
Create a test certificate, using the -p option to set a password for the new certificate
C:\Projects\CodeSigning\> signtool -G myTestCert -d . -p"password" using certificate directory: . WARNING: Performing this operation while the browser is running could cause corruption of your security databases. If the browser is currently running, you should exit the browser before continuing this operation. Enter "y" to continue, or anything else to abort: y Enter certificate information. All fields are optional. Acceptable characters are numbers, letters, spaces, and apostrophes. certificate common name: XPI Test organization: TJworld organization unit: Software state or province: Nottingham country (must be exactly 2 characters): GB username: tj email address: email@example.com generated public/private key pair certificate request generated certificate has been signed certificate "myTestCert" added to database Exported certificate to x509.raw and x509.cacert.
x509.cacert will be used to sign your XPI package. Check that it exists on the file system and in the certificate database:
C:\Projects\CodeSigning\> dir x509* 14/12/2005 15:13 1,031 x509.cacert 14/12/2005 15:13 798 x509.raw C:\Projects\CodeSigning\> certutil -d . -L myTestCert u,u,Cu
Prepare XPI file for signing
Create a new folder just for signing, copy your existing XPI into it, unzip* it (maintaining paths), delete the XPI and return to the certificate-database folder.
*Assumes you have a zip utility available on your system path. This example is using the CygWin bin/zip.exe tool. You can use a graphical Zip tool provided it manages the internal sub-directory structure properly. An alternative is to use WinRar.
C:\Projects\CodeSigning\> md signed C:\Projects\CodeSigning\> copy C:\Projects\fsb\fsb.xpi signed 1 file(s) copied. C:\Projects\CodeSigning\> cd signed C:\Projects\CodeSigning\signed> unzip fsb.xpi Archive: fsb.xpi creating: chrome/ inflating: chrome.manifest inflating: chrome/fsb.jar inflating: install.rdf C:\Projects\CodeSigning\signed> del fsb.xpi C:\Projects\CodeSigning\signed> cd ..
C:\Projects\CodeSigning\> signtool -d . -k myTestCert -p "password" signed/ using certificate directory: . Generating signed//META-INF/manifest.mf file.. --> chrome/fsb.jar --> chrome.manifest --> install.rdf Generating zigbert.sf file.. tree "signed/" signed successfully
Change to the signed/ folder, create a new zip with the META-INF/zigbert.rsa file listed first, then add the remaining files.
C:\Projects\Certs\> cd signed C:\Projects\CodeSigning\signed\> zip fsb.xpi META-INF/zigbert.rsa adding: META-INF/zigbert.rsa (deflated 35%) C:\Projects\CodeSigning\signed> zip -r -D fsb.xpi * -x META-INF/zigbert.rsa adding: META-INF/manifest.mf (deflated 37%) adding: META-INF/zigbert.sf (deflated 40%) adding: chrome/fsb.jar (deflated 74%) adding: chrome.manifest (deflated 69%) adding: install.rdf (deflated 62%)
Test your certificate
To test your certificate, install it into your browser, and attempt to load the signed extension by following these steps:
1. Temporarily install the Test Certificate Authority into your Mozilla browser
Rename the x509.cacert file generated earlier to x509.cert
Import it into Mozilla Firefox as a Software Developer Certificate Authority.
Firefox 1.5: From the Tools menu choose Options->Advanced->Security->View Certificates->Authorities
Firefox 1.0: From the Tools menu choose Options->Advanced->Certificates->Manage Certificates->Authorities
Press the Import button.
Navigate to the folder containing x509.cert and choose it.
In the Downloading Certificate dialog, tick Trust this CA to identify software developers. and press the View button if you wish to examine the certificate more closely.
Press the OK button and you'll see your new certificate in the list of Authorities.
2. Attempt to install the signed extension
Either drag and drop or browse to and download the signed XPI. When the Mozilla Firefox Software Installation dialog appears the organisation name of the certificate will appear where Firefox usually displays unsigned.
Obtaining a valid software developer code-signing certificate
Now you know it all works, you need to add a real software developer's certificate to the NSS certificate database, and use that to sign the XPI. There are several issuers of software developer certificates, with the three key differentials: availability, cost and identity verification.
Many issuers will not provide a software developer certificate to individuals (how ridiculous) so you may have to search hard to find one that will, and who also has a CA root Authority installed in Mozilla Firefox. Without the certificate-issuers CA root certificate Mozilla Firefox will not confirm the validity of your certificate to users who want to install your extension. Ideally you want a certificate that has a root CA installed in all major platforms (Microsoft Windows, Sun Java, Mozilla/Netscape Firefox/Navigator, Opera) so you only use one certificate for signing all your software, no matter which platform it is for.
The cheapest universally supported (Mozilla, Java, Microsoft) certificate seems to be the Comodo Instant-SSL offering. You can get a free certificate for open-source developers from Unizeto Certum, in 2010 it is a Certum Level III CA.
Here are some current issuers:
- Comodo Instant-SSL Code Signing
- Digi-Sign Digi-Code
- GeoTrust Code Signing
- Thawte Code Signing (owned by Verisign)
- Unizeto Certum Code-signing (free certificates for open-source authors)
- Verisign Code Signing
You will need to apply for a Code Signing Certificate and satisfy the Issuer's identity verification procedures. They will then issue a signed certificate. When you receive the signed certificate it must be imported into the certificate database.
Hint: When applying for a certificate ensure that the Organisation (O) contains your name and not the Issuer's default text, because this is what is displayed to users.
For this guide I applied for a free certificate from Unizeto Certum. After completing the application process where I entered my details into the online application, I received an automated email requesting documentary evidence of my ID in the form of a photo-ID or similar. I have hi-resolution scanned images of my passport and drivers license for these situations so I placed them on my web-server temporarily in a hidden location and emailed Unizeto Certum with the details and location of the files. Within a few hours I received a confirmation email from a human accepting the ID images and giving me a hyperlink to the certifcate download area.
Install the certificate into Mozilla Firefox (which goes with the private key created earlier), and copy/paste the displayed certificate text into a new file called
C:\Projects\CodeSigning\Certum Code Signing.cer.
Installing real certificate
There are two steps required to install the new certificate in the Code Signing NSS certificate database.
1. Install the Issuer's Certificate Authority Root 2. Install your key and certificate
The root CA establishes the trust of your certificate. Many issuer's have multiple root CAs for different levels of trust. find out which one was used for your certificate and download it. You can view the details of your certificate in Mozilla Firefox and get this information from the Issued By Common Name (Unizeto Certum's free certificate CA is Certum Level III CA).
Download the Root CA and any intermediate certificates used to sign your certificate from the Issuer; their web site will have a link somewhere to their root CAs and public certificates. (Certum public key page). I downloaded the Certum Root CA and Certum Level III CA Digital ID for web and SSL/TLS Servers, copied the text and saved them to the files
C:\Projects\CodeSigning\Certum Root CA.cer and
C:\Projects\CodeSigning\Certum Level III CA.cer.
Open a command prompt (ensure the paths to the NSS tools are set as described above) in the CodeSigning folder, install the Issuer CA certificates, and check they have been added correctly.
C:\Projects\CodeSigning> certutil -A -n "Certum Root CA" -t "TC,TC,TC" -d . -i "Certum Root CA.cer" C:\Projects\CodeSigning> certutil -A -n "Certum Level III CA" -t "c,c,C" -d . -i "Certum Level III CA.cer" C:\Projects\CodeSigning> certutil -L -d . myTestCert u,u,Cu Certum Root CA CT,C,C Certum Level III CA CT,C,C
The name given to the newly issued certificate in the Mozilla Firefox keystore is not the easiest key alias in the world to remember, so I've added an additional step here that lets you rename it (its not just a simple rename operation, unfortunately).
To find the name, in Mozilla Firefox navigate to the Certificate Manager (described in Step 11), choose Your Certificates, select the new certificate, press View, choose Details and look at the first entry in the Certificate Fields tree-view.
My Unizeto Certum certificate is named "TJ's Unizeto Sp. z o.o. ID" but I want it to be called "Code Signing (Certum)".
The trick is to install the certificate (without the key) first and give your chosen nickname at that point. When the key/certificate pair is imported from Mozilla Firefox afterwards, the private key will be added but the certificate name will remain the same.
C:\Projects\CodeSigning> certutil -A -n "Code Signing (Certum)" -t "u,u,u" -d . -i "Certum Code Signing.cer" C:\Projects\CodeSigning> certutil -L -d . myTestCert u,u,Cu Certum Root CA CT,C,C Certum Level III CA CT,C,C Code Signing (Certum) ,, C:\Projects\CodeSigning> signtool -l -d . using certificate directory: . Object signing certificates --------------------------------------- myTestCert Issued by: myTestCert (XPI Test) Expires: Tue Mar 14, 2006 Code Signing (Certum) Issued by: Certum Level III CA (Certum Level III CA) Expires: Tue Mar 14, 2006 --------------------------------------- For a list including CA's, use "signtool -L"
Now you must export the new key/certificate pair from the Mozilla Firefox certificate database and into the NSS certificate database.
The hardest part is locating Mozilla's key database. It consists of two files named key3.db and cert8.db. They usually live in the Mozilla Firefox user profile folder. I found mine in
C:\Documents and Settings\TJ\Application Data\Mozilla\Firefox\Profiles\xxxxxxxx.default\ where xxxxxxxx is a random string of characters.
Here's the commands required to export it to a file, import it to the Code Signing database, and verify the signing attributes (u,u,u). Ensure you use the nickname of your certificate in place of mine, and the directory where your Mozilla Firefox key database files are:
C:\Projects\CodeSigning> pk12util -o "Certum Code Signing.pkcs12" -n "TJ's Unizeto Sp. z o.o. ID" -d "C:\Documents and Settings\TJ\Application Data\Mozilla\Firefox\Profiles\xxxxxxxx.default" Enter password for PKCS12 file: Re-enter password: pk12util: PKCS12 EXPORT SUCCESSFUL C:\Projects\CodeSigning> pk12util -i "Certum Code Signing.pkcs12" -d . Enter Password or Pin for "NSS Certificate DB": Enter password for PKCS12 file: pk12util: PKCS12 IMPORT SUCCESSFUL C:\Projects\CodeSigning> certutil -L -d . myTestCert u,u,Cu Certum Root CA CT,C,C Certum Level III CA c,c,C Code Signing (Certum) u,u,u
You should notice that the existing certificate has been updated.
Sign extension with real certificate
This is a repeat of the earlier steps using the real certificate's details. Here's the output on a test directory:
C:\Projects\CodeSigning>signtool -d . -k "Code Signing (Certum)" -p ******* test using certificate directory: . Generating test/META-INF/manifest.mf file.. --> test.txt Generating zigbert.sf file.. tree "test" signed successfully
Incorporating signing into your build process
You may want to incorporate these steps into your existing build process. I have a build.bat file that automates the creation of the jar and xpi files. This example is using the CygWin bin/zip.exe tool.
build.bat is placed in the extension's root folder. E.g.
/dev/fsb/build.bat /dev/fsb/install.rdf /dev/fsb/chrome.manifest /dev/fsb/chrome/ /dev/fsb/chrome/content/ /dev/fsb/chrome/locale/ /dev/fsb/chrome/skin/
Here it is with the code-signing steps included:
@echo off set x=%cd% echo Building %x%.xpi ... echo Started at %DATE% %TIME% > %x%\build.log md build\chrome cd chrome zip -r -0 "%x%.jar" * >> %x%\build.log move "%x%.jar" ..\build\chrome >> %x%\build.log cd .. copy install.rdf build >> %x%\build.log copy chrome.manifest build >>%x%\build.log signtool.exe -d C:\Projects\CodeSigning -k "Code Signing (Certum)" -p "password" build/ >> %x%\build.log cd build zip "%x%.xpi" META-INF/zigbert.rsa >> %x%\build.log zip -r -D "%x%.xpi" * -x META-INF/zigbert.rsa >> %x%\build.log rem copy "%x%.xpi" ..\..\..\http\fsb.xpi >> %x%\build.log move "%x%.xpi" ..\ >> %x%\build.log cd .. rd build /s/q echo Done.
Make sure to replace password with your NSS Certificate database password.
Alternatives to NSS/signtool
There are several alternatives to using signtool that might suit your needs better, however please note that these alternatives are unofficial third party products.
- Key Manager XUL Extension
- Wladimir Palant's Python Script (blog post)
- xpisign.py Python Script
- XPISigner Java Tool