• 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>
5 CRX files are ZIP files with a special header and the <code>.crx</code> file
6 extension.
7 </p>
8 
9 <h2>Package header</h2>
10 
11 <p>
12 The header contains the author's public key and the extension's signature.
13 The signature is generated from the ZIP file using SHA-1 with the
14 author's private key. The header requires a little-endian byte ordering with
15 4-byte alignment. The following table describes the fields of
16 the <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>
69 The extension's ZIP file is appended to the <code>*.crx</code> package after the
70 header. This should be the same ZIP file that the signature in the header
71 was generated from.
72 </p>
73 
74 <h2>Example</h2>
75 
76 <p>
77 The following is an example hex dump from the beginning of a <code>.crx</code>
78 file.
79 </p>
80 
81 <pre>
82 43 72 32 34   # "Cr24" -- the magic number
83 02 00 00 00   # 2 -- the crx format version number
84 A2 00 00 00   # 162 -- length of public key in bytes
85 80 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>
94 Members 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 
109 if test $# -ne 2; then
110   echo "Usage: crxmake.sh &lt;extension dir&gt; &lt;pem path&gt;"
111   exit 1
112 fi
113 
114 dir=$1
115 key=$2
116 name=$(basename "$dir")
117 crx="$name.crx"
118 pub="$name.pub"
119 sig="$name.sig"
120 zip="$name.zip"
121 trap 'rm -f "$pub" "$sig" "$zip"' EXIT
122 
123 # zip up the crx dir
124 cwd=$(pwd -P)
125 (cd "$dir" && zip -qr -9 -X "$cwd/$zip" .)
126 
127 # signature
128 openssl sha1 -sha1 -binary -sign "$key" < "$zip" > "$sig"
129 
130 # public key
131 openssl rsa -pubout -outform DER < "$key" > "$pub" 2>/dev/null
132 
133 byte_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 
138 crmagic_hex="4372 3234" # Cr24
139 version_hex="0200 0000" # 2
140 pub_len_hex=$(byte_swap $(printf '%08x\n' $(ls -l "$pub" | awk '{print $5}')))
141 sig_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"
146 echo "Wrote $crx"
147 </pre>
148 
149