The .zsync Format
What a control file contains, and what each field is for.
A .zsync control file is a short header of Key: value lines, a blank line,
then a packed table of per-block checksums.
zsync: 0.6.2
Filename: image.bin
MTime: Fri, 16 Oct 2026 14:40:35 +0000
Blocksize: 2048
Length: 50000
Hash-Lengths: 2,2,5
URL: https://example.com/image.bin
SHA-1: 3f786850e387550fdab836ed7e6dc881de23001b
<checksum table>The table follows the blank line immediately and is not line oriented, so a control file is binary after the header.
Header fields
| Field | Meaning |
|---|---|
zsync | Format version. |
Filename | The target's name, which a client may use for its output. |
MTime | Modification time, informational only. Nothing acts on it. |
Blocksize | Bytes per block. Must be a non-zero power of two. |
Length | The target's exact size. |
Hash-Lengths | seq_matches,rsum_bytes,checksum_bytes. |
URL | Where to fetch the target from. Repeatable, in preference order. |
SHA-1 | Digest of the target as a whole, 40 hex characters. |
Unknown fields are ignored, so a control file from a later revision still parses.
Blocksize must be a power of two because the matcher derives every block's
offset by shifting and slides its window by the same amount.
The checksum table
Each block contributes rsum_bytes + checksum_bytes bytes, with no padding
and no per-block length. The number of blocks follows from Length and
Blocksize, so a client knows how much to read before reading any of it.
The rolling checksum is a pair of 16-bit sums. a is the plain byte sum; b
weights each byte by how many bytes follow it, which is what makes b change
when content is reordered rather than merely added. Together they slide one
byte at a time, which is what makes scanning a multi-gigabyte file affordable.
The rolling checksum is stored big-endian and truncated from the high end of each field, so the widths are not interchangeable:
rsum_bytes | a | b |
|---|---|---|
| 1 | none | low byte only |
| 2 | none | all 16 bits |
| 3 | low byte | all 16 bits |
| 4 | all 16 bits | all 16 bits |
Because one and two byte entries record no a at all, a comparison has to go
through a mask rather than field by field. Both the matcher and its index mask
identically; if only one side were masked, the two would compute different
buckets and nothing would ever be found.
The strong checksum is the first checksum_bytes of the block's MD4 digest.
Values below four are refused on reading: they make a false block match cheap
enough to be worth attempting, and each one that slips through writes wrong
bytes into the target.
The final block
A target whose length is not a whole number of blocks has a short final block,
and the checksum table has no way to record a short one. Its checksum is
therefore taken over the real bytes followed by zeros up to Blocksize, and
every reader pads the same way. A control file that padded differently would
be unfindable in a copy that already holds the file.
Why SHA-1
SHA-1 is the authority on the finished file. Every block checksum in the
table can be satisfied individually and still not describe the target that was
promised, so the assembled result is hashed once at the end and compared.
MD4 and SHA-1 are fixed by the format and are not collision resistant. They identify content against accidental corruption and a mismatching origin, not an adversary who has chosen a collision.
Limits
A control file arrives from the network, and its header is a handful of bytes that decides how much memory a client allocates. Three caps bound it, each with a test:
- The header section is capped at 1 MiB. Without it a single unterminated
line, or an endless run of
URL:lines, decides how much memory the client spends. - The block count is capped at 2^26, a hundred-terabyte file at 2 KiB blocks. The count comes straight out of the header, so a three-line response could otherwise ask for a multi-gigabyte table.
- The checksum table is reserved for what has arrived rather than for what was claimed, so a tiny response cannot reserve a huge buffer before a single checksum has been read.
See also
The sidecar format, which rides alongside a control file.
2026 © All Rights Reserved.
- All the content is available under CC BY-SA 4.0, expect where otherwise stated.
- Source code is available on GitLab, licensed under Apache 2.0.
Last updated on
