Html程序  |  149行  |  3.93 KB

<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&nbsp;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&nbsp;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&nbsp;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 &lt;extension dir&gt; &lt;pem path&gt;"
  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>