Pull request 609: Add GPG signing for trusttunnel_client

Squashed commit of the following:

commit 0ed11c988f35f1b19ce7f6b726b76d6d7b8479f4
Author: Sergey Fionov <sfionov@adguard.com>
Date:   Tue Feb 3 13:41:27 2026 +0000

    Applied suggestion: fix version

commit ffb1463d8586f3875ecdddc571de8ceea6cfe653
Author: Zhavoronkov Aleksei <a.zhavoronkov@adguard.com>
Date:   Tue Feb 3 16:36:05 2026 +0300

    Add guide how to verify releases

commit 257c725db05cf8faa3a4687949ce0529d69fb1d4
Author: Zhavoronkov Aleksei <a.zhavoronkov@adguard.com>
Date:   Tue Feb 3 16:35:37 2026 +0300

    Update CHANGELOG

commit e9857b629b26eb850844e7f84df622b6b3d78ef7
Author: Zhavoronkov Aleksei <a.zhavoronkov@adguard.com>
Date:   Tue Feb 3 15:23:50 2026 +0300

    fix

commit c0e3376bc731c51415940060476d33367b27a347
Author: Zhavoronkov Aleksei <a.zhavoronkov@adguard.com>
Date:   Tue Feb 3 13:59:47 2026 +0300

    Add GPG signing for trusttunnel_client
This commit is contained in:
Aleksei Zhavoronkov
2026-02-03 14:47:31 +00:00
parent a6598f0fd9
commit 4e1757efed
5 changed files with 112 additions and 13 deletions
+2
View File
@@ -1,5 +1,7 @@
# CHANGELOG
- [Feature] Add GPG signing for TrustTunnel executables.
## 0.99.102
- Post-quantum cryptography is now enabled by default
+1
View File
@@ -93,4 +93,5 @@ Apache 2.0
- [Apple adapter](platform/apple/README.md)
- [Windows adapter](platform/windows/README.md)
- [Changelog](CHANGELOG.md)
- [Verifying releases](VERIFY_RELEASES.md)
- [License](LICENSE)
+58
View File
@@ -0,0 +1,58 @@
# Verifying TrustTunnelClient Releases
Since TrustTunnelClient v0.99.104 we sign the executable files we build so that you can verify they are really created by us and no one else. Inside an archive file there's a small file with .sig extension which contains the signature data. In a hypothetic situation when the binary file inside an archive is replaced by someone, you'll know that it isn't an official release from AdGuard.
## How to verify that the executable file was built by AdGuard?
1. Unpack the TrustTunnelClient archive file.
2. Import TrustTunnelClient public key from keyserver. For current release, run:
```text
gpg --keyserver 'keys.openpgp.org' --recv-key '28645AC9776EC4C00BCE2AFC0FE641E7235E2EC6'
```
The above command will print something similar to:
```text
gpg: key 0FE641E7235E2EC6: public key "AdGuard <devteam@adguard.com>" imported
gpg: Total number processed: 1
gpg: imported: 1
```
3. Verify. On Unix:
```text
gpg --verify trusttunnel_client/setup_wizard.sig
gpg --verify trusttunnel_client/trusttunnel_client.sig
```
On Windows (you might need to install PGP):
```text
gpg --verify trusttunnel_client/setup_wizard.exe.sig
gpg --verify trusttunnel_client/trusttunnel_client.exe.sig
```
You'll see something like this:
```text
gpg: assuming signed data in 'trusttunnel_client'
gpg: Signature made Mon 2 Feb 2026 19:30:55 MSK
gpg: using RSA key 28645AC9776EC4C00BCE2AFC0FE641E7235E2EC6
gpg: issuer "devteam@adguard.com"
gpg: Good signature from "AdGuard <devteam@adguard.com>" [ultimate]
```
Check the following:
- RSA key: must be 28645AC9776EC4C00BCE2AFC0FE641E7235E2EC6;
- Issuer name: must be AdGuard;
- E-mail address: must be devteam@adguard.com.
There may also be the following warning:
```text
gpg: WARNING: The key's User ID is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 2864 5AC9 776E C4C0 0BCE 2AFC 0FE6 41E7 235E 2EC6
```
+38 -2
View File
@@ -52,6 +52,12 @@ Linux build:
ARCHES=${ARCHES:-x86_64 aarch64 armv7 mips mipsel}
# Set up GPG for signing binaries
GPG_KEY=devteam@adguard.com
echo "${bamboo.gpgSecretKeyPart1}${bamboo.gpgSecretKeyPart2}"\
| awk '{ gsub(/\\n/, "\n"); print; }'\
| gpg --import --batch --yes
rustup +nightly component add rust-src
for ARCH in $ARCHES; do
@@ -87,8 +93,20 @@ Linux build:
pushd build_${ARCH}/trusttunnel
llvm-strip trusttunnel_client
llvm-strip setup_wizard
# Sign binaries with GPG
gpg --default_key "${GPG_KEY}" \
--detach_sig \
--passphrase "${bamboo.gpgPassword}" \
--pinentry-mode loopback \
trusttunnel_client
gpg --default_key "${GPG_KEY}" \
--detach_sig \
--passphrase "${bamboo.gpgPassword}" \
--pinentry-mode loopback \
setup_wizard
cp ${VPNLIBS_ROOT}/LICENSE .
tar zcf ${NAME}.tar.gz --transform "s,^,${NAME}/," trusttunnel_client setup_wizard LICENSE
# Include .sig files in the archive
tar zcf ${NAME}.tar.gz --transform "s,^,${NAME}/," trusttunnel_client trusttunnel_client.sig setup_wizard setup_wizard.sig LICENSE
mv ${NAME}.tar.gz ${ARTIFACTS_DIR}/
popd
done
@@ -138,6 +156,12 @@ Mac build:
bundle exec fastlane certs
VERSION=$(cat conandata.yml | grep "[0-9]*\.[0-9]*." | tail -1 | sed "s/\"//" | sed "s/\"\://" | sed "s/ //g")
# Set up GPG for signing binaries
GPG_KEY=devteam@adguard.com
echo "${bamboo.gpgSecretKeyPart1}${bamboo.gpgSecretKeyPart2}"\
| awk '{ gsub(/\\n/, "\n"); print; }'\
| gpg --import --batch --yes
ARCHES=${ARCHES:-x86_64 arm64}
for ARCH in $ARCHES; do
@@ -168,9 +192,21 @@ Mac build:
bundle exec fastlane notari id:"${CODESIGN_IDENTIFIER}" bundle:"${BIN_PATH}/setup_wizard"
bundle exec fastlane remove_certs || true
popd
# Sign binaries with GPG
gpg --default_key "${GPG_KEY}" \
--detach_sig \
--passphrase "${bamboo.gpgPassword}" \
--pinentry-mode loopback \
trusttunnel_client
gpg --default_key "${GPG_KEY}" \
--detach_sig \
--passphrase "${bamboo.gpgPassword}" \
--pinentry-mode loopback \
setup_wizard
cp ${REPO_ROOT}/LICENSE .
NAME=trusttunnel_client-v${VERSION}-macos-universal
tar zcf ${NAME}.tar.gz -s ",^,${NAME}/," trusttunnel_client setup_wizard LICENSE
# Include .sig files in the archive
tar zcf ${NAME}.tar.gz -s ",^,${NAME}/," trusttunnel_client trusttunnel_client.sig setup_wizard setup_wizard.sig LICENSE
popd
- script:
scripts:
+13 -11
View File
@@ -315,18 +315,18 @@ check_out_dir() {
set -e
}
# TODO: enable this once binaries are signed with gpg
# Function verify_hint prints a hint about how to verify the installation.
# verify_hint() {
# # Check if `.sig` file exists
# if [ -f "${output_dir}/${exe_name}.sig" ]
# then
# echo
# echo "To verify the installation, run the following command to import the public key and verify the signature:"
# echo " gpg --keyserver 'keys.openpgp.org' --recv-key '28645AC9776EC4C00BCE2AFC0FE641E7235E2EC6'"
# echo " gpg --verify ${output_dir}/${exe_name}.sig ${output_dir}/${exe_name}"
# fi
# }
verify_hint() {
exe_name=trusttunnel_client
# Check if `.sig` file exists
if [ -f "${output_dir}/${exe_name}.sig" ]
then
echo
echo "To verify the installation, run the following command to import the public key and verify the signature:"
echo " gpg --keyserver 'keys.openpgp.org' --recv-key '28645AC9776EC4C00BCE2AFC0FE641E7235E2EC6'"
echo " gpg --verify ${output_dir}/${exe_name}.sig ${output_dir}/${exe_name}"
fi
}
# Function remove_downloaded_package deletes the archive only if it was downloaded and not transferred.
remove_downloaded_package() {
@@ -627,3 +627,5 @@ handle_existing
unpack
report_success
verify_hint