Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License, and code samples are licensed under the BSD License.
©2012 Google
CRX files are ZIP files with a special header and the .crx
file
extension.
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 .crx
header in order:
Field | Type | Length | Value | Description |
---|---|---|---|---|
magic number | char[] | 32 bits | Cr24 |
Chrome requires this constant at the beginning of every .crx
package.
|
version | unsigned int | 32 bits | 2 | The version of the *.crx file format used (currently 2). |
public key length | unsigned int | 32 bits | pubkey.length | The length of the RSA public key in bytes. |
signature length | unsigned int | 32 bits | sig.length | The length of the signature in bytes. |
public key | byte[] | pubkey.length | pubkey.contents | The contents of the author's RSA public key, formatted as an X509 SubjectPublicKeyInfo block. |
signature | byte[] | sig.length | sig.contents | 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. |
The extension's ZIP file is appended to the *.crx
package after the
header. This should be the same ZIP file that the signature in the header
was generated from.
The following is an example hex dump from the beginning of a .crx
file.
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
Members of the community have written the following scripts to package
.crx
files.
github: crxmake
#!/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"