This page contains instructions for verifying that Telegram's open source code is exactly the same as the code that is used to build the apps that are available in the App Store, Google Play and directly on the Telegram website.
Warning: Telegram supports reproducible builds as of version 5.13. Bear in mind that, at this stage, the verification process should be considered experimental. We will be updating our apps and these instructions to make this process as straightforward as possible.
Please read the relevant notes and troubleshooting section carefully.
Docker can be obtained here. Once the installation is complete, log into your Docker account > Settings > Resources > Advanced and configure the amount of resources Docker may use:
We recommend using the maximum amount allowed by your system's hardware, in order to speed up the build time.
You can find the version/build number and the source (website, Play Store, Huawei Store) at the bottom of the Settings page. Note that Telegram supports reproducible builds starting with version 5.13.
The commit tag to checkout source code for the example above will be release-9.3.3_3026
.
Please make sure that you're using the correct version and build number of the version you want to check (and not the one from this example ).
Open Terminal, run the commands:git clone https://github.com/DrKLO/Telegram.git $HOME/telegram-android
cd $HOME/telegram-android
git checkout release-{VERSION AND BUILD NUMBER FROM STEP 2}
For our example, the command would be:git checkout release-5.13.0_1821
Open Terminal, run the commands:cd $HOME/telegram-android
docker build -t telegram-build .
docker run --rm -v "$PWD":/home/source telegram-build
These commands will produce 3 different APKs and 2 bundles:
/apk/afat/standalone/app.apk
– used for direct downloads from telegram.org/android/apk/afat/elease/app.apk
– the playstore version/apk/afat/release/app-huawei.apk
– used exclusively for the Huawei store
bundle/bundleAfat_SDK23Release/TMessagesProj_App-bundleAfat_SDK23-release.aab
bundle/bundleAfatRelease/TMessagesProj_App-bundleAfat-release.aab
These APKs can be found in:$HOME/telegram-android/TMessagesProj/build/outputs/apk/afat/
Use the folder name from Step 4 to find the correct folder that holds the same APK as installed on your device. For example, for the Play Store version, the path to your APK will be:
$HOME/telegram-android/TMessagesProj/build/outputs/apk/afat/release/app.apk
Copy this APK to the root source directory by running this command in Terminal:cp $HOME/telegram-android/TMessagesProj/build/outputs/apk/afat/release/app.apk $HOME/telegram-android/telegram_built.apk
You will need adb for this step.
If you downloaded your APK directly from Telegram's website, use the package name
org.telegram.messenger.web
in this step. To verify the Google Play APK, useorg.telegram.messenger
.
Connect your device to the computer, open Terminal, run the commands:adb shell pm path org.telegram.messenger
The output will look something like this:package:/data/app/org.telegram.messenger-_zOSURFEx2GpHM8UDF_PVg==/base.apk
By using this information, pull the APK from your device to $HOME/telegram-android using command:adb pull /data/app/org.telegram.messenger-_zOSURFEx2GpHM8UDF_PVg==/base.apk $HOME/telegram-android/telegram_store.apk
To compare Direct and Huawei Store versions, open Terminal, run the commands:cd $HOME/telegram-android
python apkdiff.py telegram_store.apk telegram_built.apk
If the APKs are the same, you will seeAPKs are the same!
Play Store versions built from a bundle will be marked as 'store bundled'. To verify such builds, use:
python apkfrombundle.py telegram_bundle.aab telegram_store.apk
If anything goes wrong, you will see this:
If your APKs don't match, please make sure that you chose the correct code version and the right SDK.
Check out the Troubleshooting section first in case you run into trouble.
The verification process for iOS builds is, unfortunately, a lot more complex than for Android. The two main issues with Apple's current policies and infrastructure are as follows:
Apple insists on using FairPlay encryption to “protect” even free and open source apps from “app pirates” which makes obtaining the executable code of apps impossible without a jailbroken device. To solve this issue, Apple would simply need to allow submitting unencryptable binaries to the App Store. This would not affect security since the code would still be signed – and would enable anyone to check the integrity of apps supporting reproducible builds without endangering the integrity and security of their devices.
Building your own reproducible binaries is difficult because macOS doesn't support containers like Docker. If Apple followed in the footsteps of Linux (and even Microsoft!) and added container support, it would eliminate the need for steps 1-3 in the guide below.
As things stand now, you'll need a jailbroken device, at least 1,5 hours and approximately 90GB of free space to properly set up a virtual machine for the verification process.
To provide a stable and easily reproducible environment, Telegram iOS builds are compiled on a virtual machine.
git clone https://github.com/ali-fareed/darwin-containers.git
Check versions.json for information on the relevant macOS and Xcode versions.
./darwin-containers fetch
Download the appropriate macOS restore image (e.g. 13.6):
./darwin-containers fetch "macOS 13.6"
Create a new OS image:
./darwin-containers create --source "macOS 13.6" --tag "macos-13.0-xcode-{XCODE_VERSION}" --manual
Follow the installation instructions. Set username to containerhost
and password to containerhost
.
Enable Remote Login and allow full disk access for remote users.
Connect to the guest VM using SSH with username containerhost
and password containerhost
.
Create the directory ~/.ssh
and set up the authorized_keys
using the public key string printed by the darwin-containers create
command earlier.
Upload the appropriate version of Xcode via scp
and install to /Applications. Run it at least once to complete installation. Don't forget to download the iOS SDK.
Shut down the guest OS.
python3 -u build-system/Make/Make.py remote-build --darwinContainers="path-to-darwin-containers-script" --darwinContainersHost="unix://$HOME/.darwin-containers.sock" --configurationPath="build-system/appstore-configuration.json" --codesigningInformationPath=build-system/fake-codesigning --configuration=release_arm64
For more information see:
build-system/Make/RemoteBuild.py
.gitlab-ci.yml
lane verify_beta_testflight
git clone --recursive https://github.com/TelegramMessenger/telegram-ios.git $HOME/telegram-ios
cd $HOME/telegram-ios
git checkout release-${VERSION_NUMBER}
E.g., git checkout release-7.3
. Please note that you need to check out the whole git history as the build version depends on the number of commits in the repository.
This step requires a jailbroken device equipped with tools for decrypting apps. We‘d love to make this process more simple but that’s what you get for using Apple tech.
Runpython3 tools/ipadiff.py build/artifacts/Telegram.ipa PATH-TO-THE-IPA-FILE-FROM-STEP-9
In case of a successful comparison, you will get a text along these lines:
IPAs are equal, except for the files that can't currently be checked:
Excluded files that couldn't be checked due to being encrypted:
PlugIns/SiriIntents.appex/SiriIntents
PlugIns/Widget.appex/Widget
PlugIns/NotificationContent.appex/NotificationContent
PlugIns/NotificationService.appex/NotificationService
PlugIns/Share.appex/Share
IPAs contain Watch directory with a Watch app which can't be checked currently.
IPAs contain .car (Asset Catalog) files that are compiled by the App Store and can't currently be checked:
Frameworks/TelegramUI.framework/Assets.car
Assets.car
IPAs contain .nib (compiled Interface Builder) files that are compiled by the App Store and can't currently be checked:
Base.lproj/LaunchScreen.nib
In case of any mismatches, you'll get a detailed report.
You will get a warning if the archive created in Step 5 contains encrypted files. If all these files are in the PlugIns
subfolder, they represent various system extensions (e.g. external sharing, Siri). Decrypting such files using existing ways of receiving app archives via Jailbreak is non-trivial (but we're working on resolving this issue). If you do manage to decrypt them, e.g. on iOS 8, they will be matched.
Files with the .car
extension are app resource archives (images, sounds) which were compiled and processed specifically for the target device. The App Store processes them in non-trivial ways, we're planning on getting rid of them in future versions.
The LaunchScreen.nib
file is an empty file containing a description of the interface which is displayed by the system before the app is launched. It is processed by the App Store in a non-trivial way but doesn't contain any code and therefore may be ignored.
If you encounter any issues with obtaining the code, building and comparing the apps, please contact us at @BotSupport and include the hashtag #reproducibleBuilds
with your message describing the problem.
Make sure that you checkout the correct version of the code.
Make sure that you build the app using the right SDK.
If the gradle version used in the Dockerfile is not available anymore and building of the Docker image fails, wait for a Dockerfile update or update manually to lastest available version.