<div id="pageData-name" class="pageData">CRX Package Format</div> <div id="pageData-showTOC" class="pageData">true</div> <p> CRX files are ZIP files with a special header and the <code>.crx</code> file extension. </p> <h2>Package header</h2> <p> The header contains the author's public key and the extension's signature. The signature is generated from the ZIP file using SHA-1 with the author's private key. The header requires a little-endian byte ordering with 4-byte alignment. The following table describes the fields of the <code>.crx</code> header in order: </p> <table> <tr> <th>Field</th><th>Type</th><th>Length</th><th>Value</th><th>Description</th> </tr> <tr> <td><em>magic number</em></td><td>char[]</td><td>32 bits</td><td>Cr24</td> <td> Chrome requires this constant at the beginning of every <code>.crx</code> package. </td> </tr> <tr> <td><em>version</em></td><td>unsigned int</td><td>32 bits</td><td>2</td> <td>The version of the <code>*.crx</code> file format used (currently 2).</td> </tr> <tr> <td><em>public key length</em></td><td>unsigned int</td><td>32 bits</td> <td><i>pubkey.length</i></td> <td> The length of the RSA public key in <em>bytes</em>. </td> </tr> <tr> <td><em>signature length</em></td><td>unsigned int</td><td>32 bits</td> <td><i>sig.length</i></td> <td> The length of the signature in <em>bytes</em>. </td> </tr> <tr> <td><em>public key</em></td><td>byte[]</td><td><i>pubkey.length</i></i></td> <td><i>pubkey.contents</i></td> <td> The contents of the author's RSA public key, formatted as an X509 SubjectPublicKeyInfo block. </td> </tr> <tr> <td><em>signature</em></td><td>byte[]</td><td><i>sig.length</i></td> <td><i>sig.contents</i></td> <td> The signature of the ZIP content using the author's private key. The signature is created using the RSA algorithm with the SHA-1 hash function. </td> </tr> </table> <h2>Extension contents</h2> <p> The extension's ZIP file is appended to the <code>*.crx</code> package after the header. This should be the same ZIP file that the signature in the header was generated from. </p> <h2>Example</h2> <p> The following is an example hex dump from the beginning of a <code>.crx</code> file. </p> <pre> 43 72 32 34 # "Cr24" -- the magic number 02 00 00 00 # 2 -- the crx format version number A2 00 00 00 # 162 -- length of public key in bytes 80 00 00 00 # 128 -- length of signature in bytes ........... # the contents of the public key ........... # the contents of the signature ........... # the contents of the zip file </pre> <h2 id="scripts">Packaging scripts</h2> <p> Members of the community have written the following scripts to package <code>.crx</code> files. </p> <h3 id="ruby">Ruby</h3> <blockquote> <a href="http://github.com/Constellation/crxmake">github: crxmake</a> </blockquote> <h3>Bash</h3> <pre> #!/bin/bash -e # # Purpose: Pack a Chromium extension directory into crx format if test $# -ne 2; then echo "Usage: crxmake.sh <extension dir> <pem path>" exit 1 fi dir=$1 key=$2 name=$(basename "$dir") crx="$name.crx" pub="$name.pub" sig="$name.sig" zip="$name.zip" trap 'rm -f "$pub" "$sig" "$zip"' EXIT # zip up the crx dir cwd=$(pwd -P) (cd "$dir" && zip -qr -9 -X "$cwd/$zip" .) # signature openssl sha1 -sha1 -binary -sign "$key" < "$zip" > "$sig" # public key openssl rsa -pubout -outform DER < "$key" > "$pub" 2>/dev/null byte_swap () { # Take "abcdefgh" and return it as "ghefcdab" echo "${1:6:2}${1:4:2}${1:2:2}${1:0:2}" } crmagic_hex="4372 3234" # Cr24 version_hex="0200 0000" # 2 pub_len_hex=$(byte_swap $(printf '%08x\n' $(ls -l "$pub" | awk '{print $5}'))) sig_len_hex=$(byte_swap $(printf '%08x\n' $(ls -l "$sig" | awk '{print $5}'))) ( echo "$crmagic_hex $version_hex $pub_len_hex $sig_len_hex" | xxd -r -p cat "$pub" "$sig" "$zip" ) > "$crx" echo "Wrote $crx" </pre>