Let’s take a signed XPI apart and see what’re required to build a tool like XPISigner
We’ll use the Google Toolbar for Firefox as an example. It’s already signed and we can see it works when we download it.

Save off the xpi file from http://dl.google.com/firefox/google-toolbar.xpi
Using Java's jar command view the contents of the archive
C:demo>jar tvf google-toolbar-win.xpi
3247 Tue Feb 20 12:33:50 GMT 2007 META-INF/zigbert.rsa
573920 Sat Feb 17 15:01:32 GMT 2007 chrome/google-toolbar.jar
2599 Sat Feb 17 15:01:32 GMT 2007 chrome.manifest
7824 Sat Feb 17 15:01:32 GMT 2007 components/bootstrap.js
4578 Sat Feb 17 15:01:32 GMT 2007 components/googletoolbar.xpt
1126 Sat Feb 17 15:01:32 GMT 2007 components/metrics.xpt
351232 Sat Feb 17 15:01:32 GMT 2007 components/googletoolbar.dll
138752 Sat Feb 17 15:01:32 GMT 2007 components/metrics.dll
4340 Sat Feb 17 15:01:32 GMT 2007 defaults/preferences/options.js
2005 Sat Feb 17 15:01:32 GMT 2007 defaults/custombuttons/toolbar.google.com_CTK0Y7F4MTG6NKYH03WT.xml
6697 Sat Feb 17 15:01:32 GMT 2007 defaults/custombuttons/toolbar.google.com_J66T77NJDBMW4FEUU7FA.xml
7667 Sat Feb 17 15:01:32 GMT 2007 defaults/custombuttons/toolbar.google.com_O8Y91YHB24Z6SR0SGYSK.xml
22486 Sat Feb 17 15:01:32 GMT 2007 defaults/contenthandling/doc.ico
2446 Sat Feb 17 15:01:32 GMT 2007 install.rdf
544031 Sat Feb 17 15:01:32 GMT 2007 lib/toolbar.js
7789 Sat Feb 17 15:01:32 GMT 2007 LICENSE.txt
2303 Tue Feb 20 12:33:50 GMT 2007 META-INF/manifest.mf
2411 Tue Feb 20 12:33:50 GMT 2007 META-INF/zigbert.sf
The jar command lists the files in the order they were found in the archive. This is important as it plays a role in how Firefox determines that the archive is signed. Tools like WinZIP will re-order the listing by path.
There are 3 files of intrest to this investigation:
META-INF/zigbert.rsa is a PKCS#7 detached
signature.
META-INF/manifest.mf is a jar file manifest
META-INF/zigber.sf is a manifest of manifest.mf
The reason that zigbert.rsa must be at the start of the archive is so that Firefox can determine if the archive is signed and display the signer's Organization in the confirmation dialog.
Firefox downloads just enough of the archive to extract the first entry from it. If that entry is zigbert.rsa and it is a well-formed PKCS#7 signature then the signer's Distinguished Name is taken from the signer info and the organization is displayed.
e.g., the full Distinguished Name for the google signing certificate is
CN = Google Inc
OU = Digital ID Class 3 - Netscape Object Signing
O = Google Inc
L = Mountain View
S = California
C = US
The signer must be either in the Firefox certificate store or be signed by a CA in the certificate store
This way the user is told that the xpi is signed and who signed it, before the complete archive is downloaded. If the user cancels at this point then no more of the file is downloaded.
When the user accepts the xpi for installation it is downloaded. Once the download is completed Firefox finishes the verification steps.
Each file in the archive is extracted and the MD5 and SHA-1 hashes are calculated. The values are checked against the ones stored in manifest.mf. If there is a mismatch then verification fails. If there are more (or less) files files in the archive than listed in the manifest then verification fails.
If the manifest has been checked successfully then the signature manifest (zigbert.sf) is checked. The manifest.mf is split into sections based on blank lines. Each section has it's MD5 and SHA-1 hash calculated and compared to the corresponding values in zigbert.sf. If any of the entries do not match then verification fails.
The contents of zigbert.sf is used to verify the PKCS#7 signature in zigbert.rsa.
If that signature verifies and the certificate used to sign zigbert.rsa verifies against the Firefox certificate store then the xpi is staged for installation.
Recent Comments