#! /bin/sh # Pack a Chromium extension directory into CRX3 format # usage: crxmake EXTENSION_DIR KEY_FILE OUT_FILE set -efu dir=$(realpath "$1") key=$(realpath "$2") out=$(realpath "$3") name=$(basename "$dir") crx="$name.crx" pub="$name.pub" sig="$name.sig" zip="$name.zip" tosign="$name.presig" binary_crx_id="$name.crxid" key_size=$( openssl rsa -text -noout -in "$key" | sed -n 's/^.*Private-Key:.*\<\([0-9]\+\)\>\s*bit.*$/\1/p' ) workdir=$(mktemp -d -t crxmake.XXXXXXXX) oldworkdir=$PWD cd "$workdir" trap 'cd "$oldworkdir" && rm -fR "$workdir"' EXIT # zip up the crx dir (cd "$dir" && zip -qr -9 -X "$workdir/$zip" .) #extract crx id openssl rsa -in "$key" -pubout -outform der 2>/dev/null | openssl dgst -sha256 -binary -out "$binary_crx_id" truncate -s 16 "$binary_crx_id" #generate file to sign ( # echo "$crmagic_hex $version_hex $header_length $pub_len_hex $sig_len_hex" printf "CRX3 SignedData" echo "00 12 00 00 00 0A 10" | xxd -r -p cat "$binary_crx_id" "$zip" ) > "$tosign" # signature openssl dgst -sha256 -binary -sign "$key" < "$tosign" > "$sig" # public key openssl rsa -pubout -outform DER < "$key" > "$pub" 2>/dev/null crmagic_hex="43 72 32 34" # Cr24 version_hex="03 00 00 00" # 3 case $key_size in 1024) header_length="41 01 00 00" header_chunk_1="12 A8 02 0A A2 01" header_chunk_2="12 80 01" ;; 2048) header_length="45 02 00 00" header_chunk_1="12 AC 04 0A A6 02" header_chunk_2="12 80 02" ;; 4096) header_length="45 04 00 00" header_chunk_1="12 AC 08 0A A6 04" header_chunk_2="12 80 04" ;; *) echo "Error: $key has unsupported key size: $key_size" >&2 exit 2 esac header_chunk_3="82 F1 04 12 0A 10" ( echo "$crmagic_hex $version_hex $header_length $header_chunk_1" | xxd -r -p cat "$pub" echo "$header_chunk_2" | xxd -r -p cat "$sig" echo "$header_chunk_3" | xxd -r -p cat "$binary_crx_id" "$zip" ) > "$crx" mv "$crx" "$out"