Verifying Reproducibility of jp2a

Reproducible Builds

A software build is reproducible if using the same source code and by following the same build instructions in a specific build environment, bit-by-bit identical copies of expected output can be obtained by anyone.

Although reproducible builds are desirable for a number of reasons, the ability to verify that the build output corresponds exactly to the source code is a major benefit.

jp2a

jp2a is a JPEG to ASCII conversion library written in C. I’ve used it in an Image Processing project, and for some other fun stuff. Its source code can be found here. It is listed as a reproducible package by Reproducible Builds here.

But how do we determine that ourselves? The solution is to build the software in a deterministic build environment, and verify that the binary it produces has the same cryptographic checksum when built at different times, on different machines by different people.

The Build Environment

It is important to create a build environment for the process, that can be set-up again with ease, and does not introduce any sources of indeterminism. Containers are an excellent choice for this purpose. Here, I set up a Docker container to build jp2a from source. The Dockerfile to create the image is

FROM debian:9.4
LABEL author="Ayush Dwivedi"
RUN apt-get update && apt-get install -y \
make \
automake \
autoconf \
build-essential \
git-core \
gcc \
libcurl4-openssl-dev \
libjpeg-dev \
libncurses5-dev
RUN mkdir build
WORKDIR build
RUN git clone -b reproducibility-test https://github.com/aydwi/jp2a.git
WORKDIR jp2a
RUN autoreconf -vi
RUN ./configure --with-jpeg-prefix=/usr/local \
--with-curl-config=`which curl-config`
RUN make -j

It starts from a base image (Debian Stretch), installs required dependencies, specifies a fixed build path, gets the source code via git clone, and then follows the instructions required to compile from source. The image created by this Dockerfile contains the binary (named jp2a) inside /build/jp2a/src/.

We wish to verify the integrity of this binary primarily, because the .deb archive of the library is just this binary packaged in a format specified by Debian.

How to Run

Make sure Docker is installed.

  1. Create a Dockerfile, preferably in a new directory, using the contents mentioned in the previous section.

  2. Run docker build -t jp2a-test .

  3. After the image is built, create an instance of this image (a container) by running
    docker run --name jp2a -t jp2a-test

  4. Use docker cp to extract the binary and save it as jp2a by running
    docker cp jp2a:/build/jp2a/src/jp2a jp2a

  5. Check the SHA-256 hash with sha256sum jp2a

  6. Make sure to stop the container with docker stop jp2a.

Results

The SHA-256 hash, obtained after each of the several different test runs is - 6c50c4bef3fcac2a5e777d85c587c2653d9d1672195d3e9666efe89575ed1769 jp2a

This process can be followed on your own machine, and the obtained hash should match this value. It will further confirm that this binary is indeed reproducible.

If the build path is changed, the two separate binaries will not give identical hash values, and thus output will not remain reproducible. Setting different flags during compilation can also lead to the same situation. Such differences can be identified with the tool diffoscope, and wherever possible, be worked upon.

As of now, jp2a can be built reproducibly in a deterministic build environment.