Skip to content

Reproducible Builds

2-4601 edited this page Mar 31, 2016 · 31 revisions

Reproducible Builds

TL;DR

You can just use these instructions from the official announcement at Open Whisper System's blog:

# Clone the Signal Android source repository
$ git clone https://github.com/WhisperSystems/Signal-Android.git && cd Signal-Android

# Check out the release tag for the version you'd like to compare
$ git checkout v[the version number]

# Build using the Docker environment
$ docker run --rm -v $(pwd):/project -w /project whispersystems/signal-android:0.2 ./gradlew clean assembleRelease

# Verify the APKs
$ apkdiff/apkdiff.py build/output/apks/project-release-unsigned.apk path/to/SignalFromPlay.apk

Introduction

Since version 3.15.0 Signal for Android has supported reproducible builds. This is achieved by replicating the build environment as a Docker container. You'll need to build and run the container, compile Signal inside the container and then compare the resulted APK to the APK that is distributed in the Google Play Store.

The command line parts in this guide are written for Linux in mind but with little modifications you can adapt them to OS X and Windows. In the following sections we will use 3.15.2 as an example Signal version. You'll just need to replace all occurrences of 3.15.2 with the version number you are about to verify.

Getting Google Play Store APK

First make sure that the Signal version you want to verify is installed on your Android device. You'll need adb for this part.

Plug your device to your computer and run:

user@host:$ adb shell pm path org.thoughtcrime.securesms
package:/data/app/org.thoughtcrime.securesms-1/base.apk

The output will tell you where the Signal APK is located in your device.

Now using this information, pull the APK from your device to your computer's home directory:

user@host:$ adb pull /data/app/org.thoughtcrime.securesms-1/base.apk ~/Signal-3.15.2-from-Google-Play.apk

We will use this APK in the final part when we compare it with the self-built APK from GitHub.

Installing Docker

Install Docker by following the instructions for your platform at https://docs.docker.com/engine/installation/

Your platform might also have its own preferred way of installing Docker. E.g. Ubuntu has its own Docker package (docker.io) if you do not want to follow Docker's instructions.

In the following sections we will assume that your Docker installation works without issues. So after installing, please make sure that everything is running smoothly before continuing.

Building a Docker container for Signal

Grabbing the Dockerfile

First you will need the Dockerfile for Signal Android. It comes bundled with Signal's source code. The Dockerfile contains instructions on how to automatically build a container for Signal. You just need to run it and it builds itself.

In this guide we will grab the Signal source as a zip file from https://github.com/WhisperSystems/Signal-Android/releases and use the Dockerfile from there. (This same source directory will also be used later in this guide.)

user@host:$ cd ~
user@host:$ wget https://github.com/WhisperSystems/Signal-Android/archive/v3.15.2.zip
user@host:$ unzip v3.15.2.zip

Building the container

Create an empty directory and copy the Dockerfile there:

user@host:$ cd ~
user@host:$ mkdir signal-build-context
user@host:$ cd signal-build-context
user@host:$ cp ~/Signal-Android-3.15.2/Dockerfile .

While still inside the signal-build-context directory, build the container image based on the Dockerfile:

user@host:$ docker build --file Dockerfile --tag signal-android .

Wait a few years for the build to finish... 👷

(Depending on your computer and network connection, this may take several minutes.)

📆 😴

After the build has finished, you may wish to list your containers to see that it's really there:

user@host:$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
signal-android      latest              c6b84450b896        46 seconds ago      2.94 GB
ubuntu              14.04.3             8693db7e8a00        9 weeks ago         187.9 MB

Compiling Signal inside the container

Next we will run the container, grab Signal's source code and compile Signal.

Run your newly built Signal container and get a terminal session inside it:

user@host:$ docker run --name signal --interactive --tty signal-android

Now you are inside the container.

Grab Signal Android source code from GitHub and go to the repository directory:

root@container:# cd ~
root@container:# git clone https://github.com/WhisperSystems/Signal-Android.git
root@container:# cd Signal-Android

Before you can compile, you must ensure that you are at the right commit. In other words you must checkout to the version you wish to verify (here we are verifying 3.15.2):

root@container:# git checkout --quiet v3.15.2

Now you may compile the release APK by running:

root@container:# ./gradlew assembleRelease

This will take a few minutes 😴

Checking if the APKs match

After the build has completed successfully, we can now compare if the APKs match. You can do this either inside the Signal container or in your host OS. Note that copying files from your host system to a Docker container only works with Docker versions >=1.8. However the other direction works with older versions too, so we will use this way in this guide.

While keeping your Signal container running, open a terminal in your host system and run:

user@host:$ docker cp signal:/root/Signal-Android/build/outputs/apk/Signal-Android-release-unsigned.apk ~

Finally, using the apkdiff.py tool (comes with the Signal source you downloaded in the beginning) compare the two APKs. Remember that in the beginning you copied the Google Play Store APK from your device to your home directory. And just now you compiled an APK from the GitHub source and copied that package to your home directory:

user@host:$ ~/Signal-Android-3.15.2/apkdiff/apkdiff.py ~/Signal-3.15.2-from-Google-Play.apk ~/Signal-Android-release-unsigned.apk
APKs match!

If you get APKs match!, you have successfully created a matching build. Congratulations! ✨

If you get APKs don't match!, you did something wrong in the previous steps. Carefully go through them once more and compare again. If they still don't match, it's possible that the Dockerfile is out of date. Check it and build a new container if necessary. If you still can't get a match, you are probably in a dream. Wake up and try again. If you get yet another fail, this guide might be outdated. Ask if other people are experiencing the same issue (they probably are and there's some trivial explanation why it's not working).

Troubleshooting

If you cannot get things to work, please do not open an issue at the tracker or comment on an existing issue. Instead, ask for help at https://whispersystems.discoursehosting.net/c/development