Verify a Titlan download

Three checks: the signing certificate, the release artifact hash, and the reproducible build.

1. The signing certificate

Every official Titlan release is signed with one release certificate. This certificate does not rotate: a Titlan APK signed by any other certificate is not an official release. Its SHA-256 fingerprint, as the two common tools print it:

As keytool prints it:

EC:DD:E6:C1:76:29:D7:44:7C:62:17:13:7B:27:B0:AF:9F:91:5D:C6:C5:CA:CF:8C:38:FF:02:D0:B2:2C:8A:E0

As apksigner --print-certs prints it:

ecdde6c17629d7447c6217137b27b0af9f915dc6c5cacf8c38ff02d0b22c8ae0

Check the APK you downloaded (called titlan.apk below) with either tool. apksigner ships with the Android SDK build tools; keytool ships with the JDK.

apksigner verify --print-certs titlan.apk
keytool -printcert -jarfile titlan.apk

Compare the certificate SHA-256 digest that the command prints with the value above. If it differs, the file was not signed with the Titlan release certificate: do not install it.

2. Release artifacts

Titlan downloads are published only on GitHub Releases. Each release entry publishes the signed APK together with its SHA-256, beside the CycloneDX software bills of materials (protocol core, relay, and the app's dependency closure), the reproducibility report, and the build provenance attestation, so the download and its proof sit side by side.

Compute the hash of the file you downloaded and compare it with the SHA-256 on that release's entry:

sha256sum titlan.apk

This page does not repeat per-release hashes; the release entry is the authoritative place for them.

3. Reproducible builds

The repository's reproducible-build script is what CI runs on every push and in every tagged build. What it does:

Hashes are comparable across machines only when built from the same canonical path with the same pinned toolchains; the repository's build documentation lists the pins. CI builds are unsigned by design: signing happens offline, outside the repository and CI, and the signed APK's SHA-256 is published with the release.

To reproduce a release yourself, check out the tagged commit, install the pinned toolchains, and run the script. Its report can then be compared with the reproducibility report published for that release.

Further reading