1# Purpose: Pack a Chromium extension directory into crx3 format
2#
3# Sources:
4# https://stackoverflow.com/a/18709204
5# https://cs.chromium.org/chromium/src/components/crx_file/crx3.proto?l=1&rcl=09de3b4e1e13cf10e431ba119b179169cde289fe
6#
7# Modified by Andrew Lorimer, August 2019
8#
9
10description="\e[34m$(basename "$0")\e[0m
11Pack a Chromium extension into CRX3 format
12
13"
14usageshort="\e[1mUSAGE:\e[0m
15 $(basename "$0") [-s src_dir] [-p private_key] [-d output.crx]\n"
16usage="
17\e[1mOPTIONS:\e[0m
18 -s, --source
19 Directory containing all source files to be included in extension.
20 Default: ./src
21
22 -d, --destination
23 Name of a file where generated crx file will be placed. Extisting files will be overwritten.
24 Default: ./build/extension.crx
25
26 -p, --private
27 Location of the private key file.
28 Default: ./extension.pem
29
30 -n, --name
31 Use this as the file name instead of \"extension\" in the above file paths.
32
33 -h, --help
34 Show this help message\n"
35
36dir="$(pwd -P)/src"
37name=$(basename $(pwd -P))
38key=$(pwd -P)/$name.pem
39
40while [ $# -gt 0 ]; do
41 case "$1" in
42 -h|--help)
43 printf "$description$usageshort$usage"
44 exit
45 ;;
46 -s|--source)
47 dir=(${2-})
48 echo "Using source directory $dir"
49 shift
50 ;;
51 -d|--destination)
52 out=(${2-})
53 echo "Generating crx output at $out"
54 shift
55 ;;
56 -p|--private)
57 key=(${2-})
58 shift
59 ;;
60 -n|--name)
61 name=(${2-})
62 shift
63 ;;
64 --)
65 break
66 ;;
67 *)
68 printf "\x1b[31mInvalid argument $1\x1b[0m\n\n"
69 printf "$usageshort"
70 exit 1
71 ;;
72 esac
73 shift
74done
75
76if [ -z $out ]; then out="$name.crx"; fi
77pub="$name.pub"
78sig="$name.sig"
79zip="$name.zip"
80tosign="$name.presig"
81binary_crx_id="$name.crxid"
82trap 'rm -f "$pub" "$sig" "$zip" "$tosign" "$binary_crx_id"' EXIT
83
84printf "Building $(realpath --relative-to=`pwd` $dir) to $(realpath --relative-to=`pwd` $out) with private key $(realpath --relative-to=`pwd` $key)\n"
85
86# Zip crx directory
87printf "\tZipping source directory\n"
88cwd=$(pwd -P)
89(cd "$dir" && zip -qr -9 -X "$cwd/$zip" .)
90
91
92# Extract crx id
93printf "\tExtracting crx id\n"
94{
95 openssl rsa -in "$key" -pubout -outform der | openssl dgst -sha256 -binary -out "$binary_crx_id"
96} &> /dev/null
97truncate -s 16 "$binary_crx_id"
98
99# Generate file to sign
100printf "\tSigning crx file\n"
101(
102 printf "CRX3 SignedData"
103 echo "00 12 00 00 00 0A 10" | xxd -r -p
104 cat "$binary_crx_id" "$zip"
105) > "$tosign"
106
107openssl dgst -sha256 -binary -sign "$key" < "$tosign" > "$sig" # Signature
108openssl rsa -pubout -outform DER < "$key" > "$pub" 2>/dev/null # Public key
109
110crmagic_hex="43 72 32 34" # Cr24
111version_hex="03 00 00 00" # 3
112header_length="45 02 00 00"
113header_chunk_1="12 AC 04 0A A6 02"
114header_chunk_2="12 80 02"
115header_chunk_3="82 F1 04 12 0A 10"
116(
117 echo "$crmagic_hex $version_hex $header_length $header_chunk_1" | xxd -r -p
118 cat "$pub"
119 echo "$header_chunk_2" | xxd -r -p
120 cat "$sig"
121 echo "$header_chunk_3" | xxd -r -p
122 cat "$binary_crx_id" "$zip"
123) > "$out"
124printf "\tWrote $out\n"