How Chromium Packages and Signs CRX3 Extension Archives
This article provides a quick overview of how the Chromium web browser packages and cryptographically signs CRX3 extension archives to verify file integrity and authenticity during installation. It covers the binary layout of the CRX3 file format, the generation of Protocol Buffer headers, the cryptographic signing process, and the step-by-step verification routine the browser executes before loading an extension.
The CRX3 Binary Structure
A CRX3 file is a standard ZIP archive prepended with a specialized binary header. The file is structured sequentially in five distinct parts:
- Magic Number (4 bytes): Always set to the ASCII
characters
Cr24, which identifies the file to the browser as a Chromium extension. - Version (4 bytes): A little-endian integer set to
3, indicating the CRX3 format. - Header Length (4 bytes): A little-endian integer specifying the exact byte length of the upcoming CRX3 header.
- CRX3 Header (Variable length): A binary data block serialized using Google's Protocol Buffers (Protobuf) that holds public keys, signatures, and extension identity data.
- Archive Payload (Variable length): The standard ZIP
archive containing the extension's source files, assets, and the
manifest.jsonfile.
Packaging and Identity Generation
The packaging process begins by compressing the extension’s directory into a standard ZIP file. Next, the packaging tool uses a private cryptographic key (either RSA-2048 or ECDSA P-256) to establish the extension's identity.
Chromium derives the extension's unique CRX ID from the public key
corresponding to this private key. It computes a SHA-256 hash of the
public key (formatted as a SubjectPublicKeyInfo structure) and takes the
first 16 bytes (128 bits) of that hash. In the browser UI, these 16
bytes are encoded into a 32-character string using the letters
a through p instead of standard hexadecimal
characters.
During packaging, the raw 16-byte CRX ID is placed inside a Protobuf
message called SignedData.
The Cryptographic Signing Process
To prevent tampering, the CRX3 format signs both the extension's identity metadata and the ZIP archive together. Rather than signing the ZIP file in isolation, the packager constructs a specific byte stream to feed into the SHA-256 signature algorithm. This stream consists of:
- A static ASCII prefix string:
CRX3 SignedData\x00(including the null terminator). - The 4-byte little-endian length of the serialized
SignedDatamessage. - The serialized
SignedDataProtobuf message (which holds the 16-byte CRX ID). - The entire ZIP archive payload.
The packager hashes this combined stream with SHA-256 and signs the
hash using the private key. The resulting cryptographic signature and
the accompanying public key are bundled into a Protobuf structure called
an AsymmetricKeyProof.
Finally, the AsymmetricKeyProof and the
SignedData are combined into the master
CrxFileHeader Protobuf message. Because the header accepts
multiple proofs, a CRX3 file can hold signatures from both the original
developer and the Chrome Web Store simultaneously. The packager writes
the magic number, version, header size, serialized
CrxFileHeader, and ZIP payload to the disk to complete the
CRX3 file.
Integrity Verification During Installation
When a user attempts to install a CRX3 file, Chromium runs a strict verification process before it extracts any files from the ZIP payload:
- Format Validation: Chromium reads the first 12
bytes to ensure the
Cr24magic number is present, the version is3, and the header length is valid without exceeding the total file size. - Header Deserialization: The browser reads the byte
range specified by the header length and parses the
CrxFileHeaderProtobuf. If the Protobuf is malformed, installation aborts immediately. - Key-to-ID Binding Check: Chromium extracts the
SignedDatato read the expected 16-byte CRX ID. It then loops through theAsymmetricKeyProofentries in the header, hashes the provided public key using SHA-256, and confirms that the first 16 bytes of the hash match the CRX ID in theSignedData. This prevents an attacker from stripping a valid signature and replacing it with their own key pair. - Signature Verification: Chromium reconstructs the
signed data stream in memory using the
CRX3 SignedData\x00prefix, theSignedDatalength, theSignedDatabytes, and the appended ZIP archive. It uses the public key from the header to verify the cryptographic signature against this data stream. - Publisher Proof Verification: Depending on browser security policies, Chromium may also require a verified signature matching the hardcoded public key of the Chrome Web Store, proving the extension was officially distributed.
If a single byte in the ZIP payload or the SignedData
header was altered after signing, the reconstructed hash will not match
the decrypted signature. Chromium will detect this mismatch, reject the
file as corrupted or tampered with, and halt the installation before the
ZIP archive is ever unpacked.