Monolith's release APK is built reproducibly: anyone can rebuild the apk from the public source code inside a pinned build environment and confirm, bit-for-bit via hash comparison, that the published APK contains exactly the code provided on Github.
Two different SHA-256 values are involved:
| Hash | Of what | Answers |
|---|---|---|
| Download hash | the signed APK on the website | "Do I have the same APK the developer published?" |
| Reproducible hash | the unsigned APK you rebuild here | "Prove that it was built from the Github source code" |
| Item | Value |
|---|---|
| Source | this repository |
| Build image | aronbasalt/monolith-build@sha256:2c3cb23203e54f5f83cc30dfb479a49e679a8bc27c431f176d392ea3704e8dee |
| Expected unsigned APK SHA-256 | 245dcfd1d02b0c94ccbd0aebac72327119cdc007cbc17b464a274b6e2909111c |
The build image is identified by digest, not by tag: a tag can be re-pointed, a digest is the content's fingerprint and cannot be swapped. It freezes the whole toolchain (JDK 17, Android build-tools 35.0.0, NDK 27.0.12077973, CMake 3.22.1, Gradle 8.13).
- Docker (the image targets
linux/amd64; on Apple Silicon it runs via emulation) - Internet connection
Download and unpack the source code from Github
docker pull aronbasalt/monolith-build@sha256:2c3cb23203e54f5f83cc30dfb479a49e679a8bc27c431f176d392ea3704e8deeRun from the repository root (the folder that contains gradlew). Mount the source
at exactly /src.
Linux / macOS:
docker run --rm --platform=linux/amd64 -v "$(pwd):/src" \
aronbasalt/monolith-build@sha256:2c3cb23203e54f5f83cc30dfb479a49e679a8bc27c431f176d392ea3704e8dee \
bash -lc "./gradlew --no-daemon clean assembleRelease && sha256sum app/build/outputs/apk/release/app-release-unsigned.apk"Windows (PowerShell):
docker run --rm --platform=linux/amd64 -v "${PWD}:/src" `
aronbasalt/monolith-build@sha256:2c3cb23203e54f5f83cc30dfb479a49e679a8bc27c431f176d392ea3704e8dee `
bash -lc "./gradlew --no-daemon clean assembleRelease && sha256sum app/build/outputs/apk/release/app-release-unsigned.apk"The printed SHA-256 must equal:
245dcfd1d02b0c94ccbd0aebac72327119cdc007cbc17b464a274b6e2909111c
A match means your independent build is bit-for-bit identical to the reference unsigned APK.
The public APK differs from your rebuild only by the signature. Confirm this by comparing with the signature excluded:
- the APK Signing Block (v2/v3)
META-INF/*.SF,META-INF/*.RSA,META-INF/*.EC,META-INF/*.MF(v1)
Recommended — apksigcopier (clear pass/fail). apksigcopier is a Python tool and
internally calls apksigner; neither ships in the build image, so install them inside
a throwaway container — this does not change the published image (it lives only in that
one container and is discarded with --rm). Put the downloaded signed APK at the repo root
as published.apk, then run:
docker run --rm -v "$(pwd):/work" \
aronbasalt/monolith-build@sha256:2c3cb23203e54f5f83cc30dfb479a49e679a8bc27c431f176d392ea3704e8dee \
bash -lc '
apt-get update -qq && apt-get install -y -qq python3-pip >/dev/null
pip3 install --quiet apksigcopier # if pip refuses: add --break-system-packages
ln -sf /opt/android-sdk/build-tools/35.0.0/apksigner /usr/local/bin/apksigner
apksigcopier compare /work/published.apk --unsigned /work/app/build/outputs/apk/release/app-release-unsigned.apk
echo "exit: $? (0 = identical apart from the signature = verified)"
'To inspect any remaining difference — diffoscope:
diffoscope <PUBLISHED_APK> app/build/outputs/apk/release/app-release-unsigned.apkNothing should differ other than the signature.
app/src/main/cpp/libs/arm64-v8a/libsodium.so is a prebuilt binary (from the
Kalium JNI bindings 2.0.2), committed to the repository with a documented SHA-256
(see app/src/main/cpp/libs/PROVENANCE.md). It is not compiled from source
here, so it is not independently reproducible — but being fixed in Git, it
contributes identically to every build. Trust is anchored via its SHA-256 and
the Kalium release.
- The comparison covers the unsigned APK content; the signature is intentionally excluded (only the developer holds the private signing key).
- The build image is the trust root and is pinned by digest. It is published
as a binary artifact and is not bit-for-bit rebuildable from the
Dockerfilealone, becauseaptandsdkmanagerfetch packages at image-build time. Verify the image by its digest to not rely on rebuilding it. - Verification is performed on
linux/amd64(the image enforces this platform).
Reproducibility setup behind this: pinned Gradle/AGP/NDK/CMake versions, Gradle
dependency verification (gradle/verification-metadata.xml), distributionSha256Sum
for the Gradle distribution, no VCS stamp (vcsInfo.include = false), neutral native
build flags (-ffile-prefix-map, --build-id=none), and a digest-pinned container
image.