Field Notes

concept

Source-to-binary correspondence

Source-to-binary correspondence is the property that a distributed executable was actually built from a specific, inspectable version of its source code. It answers a question that ordinary code signing does not: not “who shipped this binary” but “does this binary match the source I can read.” The distinction matters because most of the trust people place in open-source software rests on the source, while the artifact they run is the binary. If nothing links the two, the source’s openness guarantees nothing about the code executing on the device.

What code signing does and does not prove

A digital signature over a binary establishes two things: integrity in transit, so tampering after signing is detectable, and continuity of publisher, so a later update can be tied to whoever signed the previous one. It does not establish that the signed binary corresponds to any particular source tree. A developer who signs an artifact on their own machine vouches for continuity, not correspondence.

This gap is not hypothetical. A compromised build machine, a malicious step injected into a CI pipeline, or a deliberately divergent private build all produce a validly signed binary that diverges from the public source, and the signature reveals none of it. “Open source on paper” names exactly this situation: the source is published and auditable, yet no mechanism ties the shipped binary to it.

Reproducible builds as the bridge

Reproducible builds close the gap. When a build is deterministic, an independent party can compile the same source and obtain a byte-identical artifact. Correspondence then becomes checkable by anyone, rather than asserted by the publisher.

The strongest deployed form combines reproducibility with developer signing. A rebuilder compiles from public source, fetches the developer’s own signed binary, and publishes it only if the two are identical apart from the signature block the rebuilder cannot produce. The result carries both properties at once: the developer’s signature for continuity, and a verified match for correspondence. This is strictly stronger than either a bare developer-signed binary, which proves only continuity, or a rebuilder-signed binary, which proves correspondence but breaks signing continuity with the upstream developer.

Why the trusted-party count misleads

A common argument evaluates distribution models by counting trusted parties and prefers the model with fewer of them. The count treats every party as a pure liability. It misses that a rebuilder is not only a party one must trust but a party that performs verification no one else performs. For a reproducibly built app, the rebuilder does not add trust in the developer’s build; it reduces that trust to a checkable claim. The honest comparison is therefore not “two parties versus one” but “a binary verifiable against source versus a binary taken on faith.” Naming the party without naming the work it does inflates a security improvement into a liability.

Correspondence is checked at a moment, not held forever

The guarantee is established when an artifact is published and becomes harder to re-establish as time passes. Verifying correspondence means running the build again, so it depends on Rebuildability, which erodes as dependencies are delisted, source repositories disappear, and toolchains leave their distributions.

The first measurement of that erosion, rebuilding F-Droid versions that had passed a check when published, completed 83.7% of builds and found 94% of those still bitwise identical, with missing dependencies causing about three quarters of the failures.1 Correspondence held wherever it could still be tested; what shrank was the set that could be tested. A note relying on a past verification result should therefore say when the check was performed, because “this binary corresponds to that source” is a claim about an audit that happened, not a property the artifact carries indefinitely.

See Android app distribution trust models for how this property distinguishes concrete Android channels, and where each one places the correspondence guarantee.

Built on 2 sources (2 external).

Working out connections…