Skip to main content
Signal has supported reproducible builds since version 3.15.0. The process lets you independently verify that the app distributed through the Play Store (or the Signal website) is built from exactly the source code in the public repository — with no hidden modifications.

How it works

Signal is distributed as an Android App Bundle. The Play Store uses the bundle to generate a set of device-specific APKs that include only the resources needed for a given device. Reproducing the build and comparing those APKs to what is installed on a device is the core of the verification process. The build environment is captured as a Docker image. Because the image pins all build tool versions, Java version, NDK, and SDK components, anyone who builds the image from the same Dockerfile gets a bit-for-bit identical compiler toolchain. Combined with Signal’s deterministic build configuration, the compiled output is reproducible.

The Dockerfile

The Dockerfile in reproducible-builds/ is the authoritative description of the build environment:
Key pinned components:
  • Base image: Ubuntu Jammy, pinned by digest
  • JDK: OpenJDK 17
  • Android SDK: API level 36, build-tools 35.0.0
  • NDK: 28.0.13004108
  • CMake: 3.22.1

Prerequisites

Before you start, install the following tools: Enable Developer Options and USB Debugging on the Android device you want to verify. Connect the device and confirm it is visible:

Step-by-step verification

1

Set up directories

Create a working directory to hold the APKs you will compare:
2

Check your Signal version

In the Signal app go to Settings → Help and note the version number, for example 7.7.0. All subsequent commands use this version.
3

Clone the exact version

Tags follow the pattern v<version>:
4

Build the Docker image

This step downloads and installs all SDK components. It may take several minutes on first run.
5

Build the app bundle

Run the Gradle build inside the container. The container mounts the repository root and runs as your local user to avoid permission issues:
The output bundle is at app/build/outputs/bundle/playProdRelease/Signal-Android-play-prod-release.aab.
6

Generate device-specific APKs from the bundle

With your device connected, use bundletool to generate the APKs that match your device:
Move the split APKs up one level and discard the bundle:
7

Pull the APKs from your device

You should now have a apks-from-device/ directory containing base.apk and one or more split_config.*.apk files.
8

Compare the APKs

Install the apkdiff dependencies and run the comparison:
Then compare each pair (adjust ABI and density names to match your device):
Each successful comparison ends with APKs match!.

Verifying the website APK

For users without Play Store access, Signal provides a universal APK at signal.org/android/apk. The website build is a single larger APK rather than an app bundle, which simplifies comparison to one pair of APKs. Build with assembleWebsiteProdRelease instead:
Output is at app/build/outputs/apk/websiteProdRelease/. Compare that APK directly to the one downloaded from the website (or pulled from the device).

The reproducible-builds/ directory

apkdiff.py knows how to compare APK internals correctly: APKs are zip archives, so a naive byte-for-byte diff would fail due to zip metadata differences. The script unpacks both APKs, skips files that are intentionally different between Play Store and self-built versions (signing information, stamp-cert-sha256), and compares the remaining entries.

Troubleshooting

  • Verify you checked out the exact git tag matching the version on your device.
  • Confirm you are comparing the right pairs: base-to-base, ABI-to-ABI, density-to-density.
  • Rebuild the Docker image from scratch (docker build --no-cache) — the Dockerfile may have changed between versions.
  • Check open issues in case a known mismatch is being tracked.
  • Ensure Docker has sufficient memory (at least 4 GB recommended).
  • Make sure the repo was cloned cleanly at the exact tag — a dirty working tree can affect build outputs.
  • Check that the --user flag matches your local UID/GID to avoid permission issues with Gradle caches.
Google’s public bundletool release does not yet support v3.1 APK signature schemes. You may need to build bundletool from source. Track progress on bundletool issue #369.

Code Transparency (extra credit)

In addition to the full reproducible build check, you can run a faster Code Transparency verification. This checks that the APK on your device was signed with Signal’s transparency key after being submitted to the Play Store:
Confirm the certificate fingerprint in the output matches:
Code Transparency is a weaker check than the full reproducible build process. It verifies the APK was not modified after Signal submitted it, but it does not verify that the submitted code matches the public git repository. The full reproducible build process covers both.