• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<div id="pageData-name" class="pageData">CRX Package Format</div>
2<div id="pageData-showTOC" class="pageData">true</div>
3
4<p>
5CRX files are ZIP files with a special header and the <code>.crx</code> file
6extension.
7</p>
8
9<h2>Package header</h2>
10
11<p>
12The header contains the author's public key and the extension's signature.
13The signature is generated from the ZIP file using SHA-1 with the
14author's private key. The header requires a little-endian byte ordering with
154-byte alignment. The following table describes the fields of
16the <code>.crx</code> header in order:
17</p>
18
19<table>
20  <tr>
21    <th>Field</th><th>Type</th><th>Length</th><th>Value</th><th>Description</th>
22  </tr>
23  <tr>
24    <td><em>magic number</em></td><td>char[]</td><td>32 bits</td><td>Cr24</td>
25    <td>
26      Chrome requires this constant at the beginning of every <code>.crx</code>
27      package.
28    </td>
29  </tr>
30  <tr>
31    <td><em>version</em></td><td>unsigned&nbsp;int</td><td>32 bits</td><td>2</td>
32    <td>The version of the <code>*.crx</code> file format used (currently 2).</td>
33  </tr>
34  <tr>
35    <td><em>public key length</em></td><td>unsigned&nbsp;int</td><td>32 bits</td>
36    <td><i>pubkey.length</i></td>
37    <td>
38      The length of the RSA public key in <em>bytes</em>.
39    </td>
40  </tr>
41  <tr>
42    <td><em>signature length</em></td><td>unsigned&nbsp;int</td><td>32 bits</td>
43    <td><i>sig.length</i></td>
44    <td>
45      The length of the signature in <em>bytes</em>.
46    </td>
47  </tr>
48  <tr>
49    <td><em>public key</em></td><td>byte[]</td><td><i>pubkey.length</i></i></td>
50    <td><i>pubkey.contents</i></td>
51    <td>
52      The contents of the author's RSA public key, formatted as an X509
53      SubjectPublicKeyInfo block.
54    </td>
55  </tr>
56  <tr>
57    <td><em>signature</em></td><td>byte[]</td><td><i>sig.length</i></td>
58    <td><i>sig.contents</i></td>
59    <td>
60      The signature of the ZIP content using the author's private key. The
61      signature is created using the RSA algorithm with the SHA-1 hash function.
62    </td>
63  </tr>
64</table>
65
66<h2>Extension contents</h2>
67
68<p>
69The extension's ZIP file is appended to the <code>*.crx</code> package after the
70header. This should be the same ZIP file that the signature in the header
71was generated from.
72</p>
73
74<h2>Example</h2>
75
76<p>
77The following is an example hex dump from the beginning of a <code>.crx</code>
78file.
79</p>
80
81<pre>
8243 72 32 34   # "Cr24" -- the magic number
8302 00 00 00   # 2 -- the crx format version number
84A2 00 00 00   # 162 -- length of public key in bytes
8580 00 00 00   # 128 -- length of signature in bytes
86...........   # the contents of the public key
87...........   # the contents of the signature
88...........   # the contents of the zip file
89
90</pre>
91
92<h2 id="scripts">Packaging scripts</h2>
93<p>
94Members of the community have written the following scripts to package
95<code>.crx</code> files.
96</p>
97
98<h3 id="ruby">Ruby</h3>
99<blockquote>
100<a href="http://github.com/Constellation/crxmake">github: crxmake</a>
101</blockquote>
102
103<h3>Bash</h3>
104<pre>
105#!/bin/bash -e
106#
107# Purpose: Pack a Chromium extension directory into crx format
108
109if test $# -ne 2; then
110  echo "Usage: crxmake.sh &lt;extension dir&gt; &lt;pem path&gt;"
111  exit 1
112fi
113
114dir=$1
115key=$2
116name=$(basename "$dir")
117crx="$name.crx"
118pub="$name.pub"
119sig="$name.sig"
120zip="$name.zip"
121trap 'rm -f "$pub" "$sig" "$zip"' EXIT
122
123# zip up the crx dir
124cwd=$(pwd -P)
125(cd "$dir" && zip -qr -9 -X "$cwd/$zip" .)
126
127# signature
128openssl sha1 -sha1 -binary -sign "$key" < "$zip" > "$sig"
129
130# public key
131openssl rsa -pubout -outform DER < "$key" > "$pub" 2>/dev/null
132
133byte_swap () {
134  # Take "abcdefgh" and return it as "ghefcdab"
135  echo "${1:6:2}${1:4:2}${1:2:2}${1:0:2}"
136}
137
138crmagic_hex="4372 3234" # Cr24
139version_hex="0200 0000" # 2
140pub_len_hex=$(byte_swap $(printf '%08x\n' $(ls -l "$pub" | awk '{print $5}')))
141sig_len_hex=$(byte_swap $(printf '%08x\n' $(ls -l "$sig" | awk '{print $5}')))
142(
143  echo "$crmagic_hex $version_hex $pub_len_hex $sig_len_hex" | xxd -r -p
144  cat "$pub" "$sig" "$zip"
145) > "$crx"
146echo "Wrote $crx"
147</pre>
148
149