diff options
| author | Albin <albin@mullvad.net> | 2022-12-12 16:18:55 +0100 |
|---|---|---|
| committer | Albin <albin@mullvad.net> | 2022-12-12 16:18:55 +0100 |
| commit | f33bcb2c74a8b805286c8effa432521d8f16b7ba (patch) | |
| tree | 646ea4b906bef18fc9e30db467bbc6f6015fa04e /android | |
| parent | 41d084b2d94ad68390b60a5f200f001500c352d4 (diff) | |
| parent | 42852a1066793fc5b2d719d0bdd64c1d9b277766 (diff) | |
| download | mullvadvpn-f33bcb2c74a8b805286c8effa432521d8f16b7ba.tar.xz mullvadvpn-f33bcb2c74a8b805286c8effa432521d8f16b7ba.zip | |
Merge branch 'update-android-container-build-instructions'
Diffstat (limited to 'android')
| -rw-r--r-- | android/BuildInstructions.md | 242 | ||||
| -rw-r--r-- | android/docker/README.md | 96 | ||||
| -rw-r--r-- | android/docker/adopt-openjdk-apt-key.pgp | 53 |
3 files changed, 131 insertions, 260 deletions
diff --git a/android/BuildInstructions.md b/android/BuildInstructions.md index bc0e362454..7bc458614b 100644 --- a/android/BuildInstructions.md +++ b/android/BuildInstructions.md @@ -1,150 +1,170 @@ -These instructions are for building the app for Android **under Linux**. +# Build instructions -# Set up build environment +This document aims to explain how to build the Mullvad Android app. It's strongly recommended and +primarily supported to build the app using the provided container, as it ensures the correct build +environment. -These instructions are probably not complete. If you find something more that needs installing -on your platform please submit an issue or a pull request. +## Build with provided container (recommended) -- Docker is required to build `wireguard-go`. Follow the - [instructions](https://docs.docker.com/engine/install/debian/) for your distribution. +This can easily be achieved by running the [containerized-build.sh](../building/containerized-build.sh) +script, which helps using the correct tag and mounting volumes. The script relies on [podman](https://podman.io/getting-started/installation.html) +by default, however another container runner such as [docker](https://docs.docker.com/get-started/) +can be used by setting the `CONTAINER_RUNNER` environment variable. -- Install a protobuf compiler (version 3 and up), it can be installed on most major Linux distros - via the package name `protobuf-compiler`. An additional package might also be required depending - on Linux distro: - - `protobuf-devel` on Fedora. - - `libprotobuf-dev` on Debian/Ubuntu. +### Debug build +Run the following command to trigger a full debug build: +```bash +../building/containerized-build.sh android --dev-build +``` -- Install `gcc` +### Release build +1. Configure a signing key by following [these instructions](#configure-signing-key). +2. Run the following command after setting the `ANDROID_CREDENTIALS_DIR` enviroment variable to the +directory configured in step 1: +```bash +../building/containerized-build.sh android --app-bundle +``` -## Android toolchain +## Build without* the provided container (not recommended) -- Install the JDK +Building without the provided container requires installing multiple Sdk:s and toolchains, and is +therefore not recommended. - ```bash - sudo apt install zip openjdk-8-jdk-headless - ``` +*: A container is still used to build `wireguard-go`. -- Install the SDK - - The SDK should be placed in a separate directory, like for example `~/android` or `/opt/android`. - This directory should be exported as the `$ANDROID_HOME` environment variable. +### Setup build enviroment +These steps explain how to manually setup the build environment on a Linux system. - ```bash - cd /opt/android # Or some other directory to place the Android SDK - export ANDROID_HOME=$PWD +#### 1. Install `docker` +Docker is required to build `wireguard-go`. Follow the installation [instructions](https://docs.docker.com/engine/install/debian/) +for your distribution. - wget https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip - unzip commandlinetools-linux-6609375_latest.zip - ./tools/bin/sdkmanager "platforms;android-33" "build-tools;33.0.0" "platform-tools" - ``` +#### 2. Install `protobuf-compiler` +Install a protobuf compiler (version 3 and up), it can be installed on most major Linux distros via +the package name `protobuf-compiler`. An additional package might also be required depending on +Linux distro: +- `protobuf-devel` on Fedora. +- `libprotobuf-dev` on Debian/Ubuntu. - If `sdkmanager` fails to find the SDK root path, pass the option `--sdk_root=$ANDROID_HOME` - to the command above. +#### 3. Install `gcc` -- Install the NDK +#### 4. Install Android toolchain - The NDK should be placed in a separate directory, which can be inside the `$ANDROID_HOME` or in a - completely separate path. The extracted directory must be exported as the `$ANDROID_NDK_HOME` - environment variable. +- Install the JDK + ```bash + sudo apt install zip openjdk-11-jdk + ``` - ```bash - cd "$ANDROID_HOME" # Or some other directory to place the Android NDK - wget https://dl.google.com/android/repository/android-ndk-r20b-linux-x86_64.zip - unzip android-ndk-r20b-linux-x86_64.zip +- Install the SDK - cd android-ndk-r20b - export ANDROID_NDK_HOME="$PWD" - ``` + The SDK should be placed in a separate directory, like for example `~/android` or `/opt/android`. + This directory should be exported as the `$ANDROID_HOME` environment variable. -## Configuring Rust + Note: if `sdkmanager` fails to find the SDK root path, pass the option `--sdk_root=$ANDROID_HOME` + to the command above. -- Get the latest **stable** Rust toolchain via [rustup.rs](https://rustup.rs/). + ```bash + cd /opt/android # Or some other directory to place the Android SDK + export ANDROID_HOME=$PWD -### Install Rust Android targets + wget https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip + unzip commandlinetools-linux-6609375_latest.zip + ./tools/bin/sdkmanager "platforms;android-33" "build-tools;30.0.2" "platform-tools" + ``` -Some environment variables must be exported so that some Rust dependencies can be -cross-compiled correctly: -``` -export NDK_TOOLCHAIN_DIR="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin" -export AR_aarch64_linux_android="$NDK_TOOLCHAIN_DIR/aarch64-linux-android-ar" -export AR_armv7_linux_androideabi="$NDK_TOOLCHAIN_DIR/arm-linux-androideabi-ar" -export AR_x86_64_linux_android="$NDK_TOOLCHAIN_DIR/x86_64-linux-android-ar" -export AR_i686_linux_android="$NDK_TOOLCHAIN_DIR/i686-linux-android-ar" -export CC_aarch64_linux_android="$NDK_TOOLCHAIN_DIR/aarch64-linux-android21-clang" -export CC_armv7_linux_androideabi="$NDK_TOOLCHAIN_DIR/armv7a-linux-androideabi21-clang" -export CC_x86_64_linux_android="$NDK_TOOLCHAIN_DIR/x86_64-linux-android21-clang" -export CC_i686_linux_android="$NDK_TOOLCHAIN_DIR/i686-linux-android21-clang" -``` +- Install the NDK -```bash -rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android -``` + The NDK should be placed in a separate directory, which can be inside the `$ANDROID_HOME` or in a + completely separate path. The extracted directory must be exported as the `$ANDROID_NDK_HOME` + environment variable. -### Set up cargo to use the correct linker and archiver + ```bash + cd "$ANDROID_HOME" # Or some other directory to place the Android NDK + wget https://dl.google.com/android/repository/android-ndk-r20b-linux-x86_64.zip + unzip android-ndk-r20b-linux-x86_64.zip -This block assumes you installed everything under `/opt/android`, but you can install it wherever -you want as long as the `ANDROID_HOME` variable is set accordingly. + cd android-ndk-r20b + export ANDROID_NDK_HOME="$PWD" + ``` -Add to `~/.cargo/config.toml`: -``` -[target.aarch64-linux-android] -ar = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar" -linker = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang" +#### 5. Install and configure Rust toolchain -[target.armv7-linux-androideabi] -ar = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar" -linker = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang" +- Get the latest **stable** Rust toolchain via [rustup.rs](https://rustup.rs/). -[target.x86_64-linux-android] -ar = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android-ar" -linker = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang" +- Configure Android cross-compilation targets. This can be done by setting the following +environment variables: + ``` + export NDK_TOOLCHAIN_DIR="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin" + export AR_aarch64_linux_android="$NDK_TOOLCHAIN_DIR/aarch64-linux-android-ar" + export AR_armv7_linux_androideabi="$NDK_TOOLCHAIN_DIR/arm-linux-androideabi-ar" + export AR_x86_64_linux_android="$NDK_TOOLCHAIN_DIR/x86_64-linux-android-ar" + export AR_i686_linux_android="$NDK_TOOLCHAIN_DIR/i686-linux-android-ar" + export CC_aarch64_linux_android="$NDK_TOOLCHAIN_DIR/aarch64-linux-android21-clang" + export CC_armv7_linux_androideabi="$NDK_TOOLCHAIN_DIR/armv7a-linux-androideabi21-clang" + export CC_x86_64_linux_android="$NDK_TOOLCHAIN_DIR/x86_64-linux-android21-clang" + export CC_i686_linux_android="$NDK_TOOLCHAIN_DIR/i686-linux-android21-clang" + ``` -[target.i686-linux-android] -ar = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android-ar" -linker = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android21-clang" -``` +- Install Android targets + ```bash + rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android + ``` -# Building a debug build +- Set up cargo to use the correct linker and archiver -Run `build-apk.sh` with `--dev-build` to build the Rust daemon and the UI in debug mode and sign the -APK with automatically generated debug keys: -```bash -../build-apk.sh --dev-build -``` + This block assumes you installed everything under `/opt/android`, but you can install it wherever + you want as long as the `ANDROID_HOME` variable is set accordingly. -If the above fails with an error related to compression, try allowing more memory to the JVM: -```bash -echo "org.gradle.jvmargs=-Xmx4608M" >> ~/.gradle/gradle.properties -./gradlew --stop -``` + Add to `~/.cargo/config.toml`: + ``` + [target.aarch64-linux-android] + ar = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar" + linker = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang" -# Building a release build + [target.armv7-linux-androideabi] + ar = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar" + linker = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang" -## Configure signing key + [target.x86_64-linux-android] + ar = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android-ar" + linker = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang" -In order to build release APKs, they need to be signed. First, a signing key must be generated and -stored in a keystore file. In the example below, the keystore file will be -`/home/user/app-keys.jks` and will contain a key called `release`. + [target.i686-linux-android] + ar = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android-ar" + linker = "/opt/android/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android21-clang" + ``` -``` -keytool -genkey -v -keystore /home/user/app-keys.jks -alias release -keyalg RSA -keysize 4096 -validity 10000 +### Debug build +Run the following command to build a debug build: +```bash +../build-apk.sh --dev-build ``` -Fill in the requested information to generate the key and the keystore file. Suppose the file was -protected by a password `keystore-password` and the key with a password `key-password`. This -information should then be added to the `android/keystore.properties` file: +### Release build +1. Configure a signing key by following [these instructions](#configure-signing-key). +2. Move, copy or symlink the directory from step 1 to [./credentials/](./credentials/) (`<repository>/android/credentials/`). +3. Run the following command to build: + ```bash + ../build-apk.sh --app-bundle + ``` -``` -keyAlias = release -keyPassword = key-password -storeFile = /home/user/app-keys.jks -storePassword = keystore-password -``` +## Configure signing key +1. Create a directory to store the signing key, keystore and its configuration: + ``` + export ANDROID_CREDENTIALS_DIR=/tmp/credentials + mkdir -p $ANDROID_CREDENTIALS_DIR + ``` -## Building and packaging the app +2. Generate a key/keystore named `app-keys.jks` in `ANDROID_CREDENTIALS_DIR` and make sure to write +down the used passwords: + ``` + keytool -genkey -v -keystore $ANDROID_CREDENTIALS_DIR/app-keys.jks -alias release -keyalg RSA -keysize 4096 -validity 10000 + ``` -Running the `build-apk.sh` script will build the necessary Rust daemon for all supported ABIs and -build the final APK: -```bash -../build-apk.sh -``` +3. Create a file named `keystore.properties` in `ANDROID_CREDENTIALS_DIR`. Enter the following, but +replace `key-password` and `keystore-password` with the values from step 2: + ```bash + keyAlias = release + keyPassword = key-password + storePassword = keystore-password + ``` diff --git a/android/docker/README.md b/android/docker/README.md deleted file mode 100644 index 4594f65466..0000000000 --- a/android/docker/README.md +++ /dev/null @@ -1,96 +0,0 @@ -# Docker image to build the Android - -This folder contains the necessary files to create a Docker image that can be used to build the -Android app without having to configure the local environment first. The image contains the -Android SDK, the Android NDK, the patched Go compiler, the Rust compiler and the necessary -configuration to allow the app to build. - -To build the image, the following command can be used while inside this directory: - -``` -docker build -t mullvad/mullvadvpn-app-android . -``` - -After the image has been built, it can be used to build the Android app. Given that the source code -[repository](https://github.com/mullvad/mullvadvpn-app) was checkout out on -`/home/user/mullvadvpn-app`, the following command will build the APK there: - -``` -docker run \ - --rm \ - -it \ - --name mullvad-android-build \ - -v /home/user/mullvadvpn-app:/project \ - -w /project \ - mullvad/mullvadvpn-app-android -``` - -The container can be configured to build the native libraries for a subset of the supported -architectures by setting the `ARCHITECTURES` environment variable. The supported architecuters are: - -- 64-bit ARMv8: `aarch64` -- 32-bit ARMv7: `armv7` -- 64-bit x86-64: `x86_64` -- 32-bit x86: `i686` - -The example below builds only for 64-bit ARM and x86-64: - -``` -docker run \ - --rm \ - -it \ - -e ARCHITECTURES="aarch64 x86_64" \ - --name mullvad-android-build \ - -v /home/user/mullvadvpn-app:/project \ - -w /project \ - mullvad/mullvadvpn-app-android -``` - -## Speeding up the build with caches - -To speed up the build, some cache files for Cargo and Gradle can be reused between builds. There are -two options to configure reusing those files: creating directories for them in the repository or -creating separate volumes. - -### Using extra directories inside the repository - -Two directories can be created inside the repository, `.gradle-home` and `.cargo-home`. When -building, they can be configured to be used by the build using environment variables -(`GRADLE_USER_HOME` and `CARGO_HOME`). The following command shows how to run the build container -using the extra directories: - -``` -docker run \ - --rm \ - -it \ - --name mullvad-android-build \ - -v /home/user/mullvadvpn-app:/project \ - -e GRADLE_USER_HOME=/project/.gradle-home \ - -e CARGO_HOME=/project/.cargo-home \ - -w /project \ - mullvad/mullvadvpn-app-android -``` - -### Using Docker volumes - -Some extra volumes can be used to cache Cargo and Gradle data. The following commands set up those -volumes and runs the build container using them: - -``` -# Run these commands once -docker volume create cargo-git -docker volume create cargo-registry -docker volume create gradle-cache - -# Run this command every time to build -docker run \ - --rm \ - -it \ - --name mullvad-android-build \ - -v /home/user/mullvadvpn-app:/project \ - -v cargo-git:/root/.cargo/git \ - -v cargo-registry:/root/.cargo/registry \ - -v gradle-cache:/root/.gradle \ - -w /project \ - mullvad/mullvadvpn-app-android -``` diff --git a/android/docker/adopt-openjdk-apt-key.pgp b/android/docker/adopt-openjdk-apt-key.pgp deleted file mode 100644 index 7ae2ce4a22..0000000000 --- a/android/docker/adopt-openjdk-apt-key.pgp +++ /dev/null @@ -1,53 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1 - -mQINBFzII+8BEADS8rE0HAdET6h2LjpRbN22+JRzFzD1LvqWFOIozLZ5hA8tAIM4 -dNhTbzMt/evgVi+Qvo+VpwINPYNPVfavWXK3PsiI6tmgECq62ODuyzS3+TBOVZ6G -RIGVoIWCqvW8gz3CBl5MzUp0iw4uv4cZYI1XJKz9CmOUzoxiCTchs2dFW9UI//AZ -A6mFVRNG0siIjEOhUON1GygHiSlKh9L5UGZfwnXwBt6B9bOdzstBoQqAIIqoRIFw -3Qi/N1VFif00h9nkvanGmhLzvqoQdPrfuw9Z0c+rqUpfgx9foUzs3BNQL2RqLBd3 -VcF2mXKdiIrsCJw2n65ORzxGvIcZ9cVt+G4DWThhVsGo963WAO5XyybbdtrV0uoz -tVL2z9WahUdwoS2Y92R4r2ciose1GbaonrDHb9LXCic1thRt2I+dQ2PA8h8boSAb -4rfsTA9MbEe8hp7wxDOtE5OPXu3GF0FL8tMxf+/8ZhIHzJaAB5+QbnBJCy44XfMK -Lh/k0dfz+NEx9pg1yYIJ1hsysNsb6r0+UuEU/k2Qy/cOLXXZYKdSHtKNxTvf9PKy -HIX1kT6muUGj97S+7T0zD7Tq6WEqwZAAIlWUO5H0KmiPotugF/ahnWEYxRVCQuBf -Iw1RZVLHVsptdcd/CF/fmlR+k3KO8h6F+At1N17ToZ0Uyq+sRz1HvVS75QARAQAB -tE1BZG9wdE9wZW5KREsgKHVzZWQgZm9yIHB1Ymxpc2hpbmcgUlBNIGFuZCBERUIg -ZmlsZXMpIDxhZG9wdG9wZW5qZGtAZ21haWwuY29tPokCOAQTAQIAIgUCXMgj7wIb -AwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQisOykXSIXAOQShAAqjye6sT+ -/fTsAbkpE055kjb9GSNBLPuPG9eCnn86hl1ge9vSBHfBC/GF4e7Q9BL0QK+rfq07 -1g8UBgdg0Vwx8VZuRR5pzIdr1FWyE0JTyUcOpTsxz5KwA8SEFodN912ajAaVwDm7 -W9Z47bPNFqFjLLqTuNInRxHqQfrytCPQY73HW/bwU0xYPupyF/nQ0qxJYPH3tK1b -zBvyVIR4mq5p1275fieLdywsIREeP/gwuR//QB48L4ZOmIQ5EE/Pq/tCK02FwMqR -U61H+YAjsPaA+1OQuvzWysQhBjhd9hxqBawO/U45oVdoYa1WsX0uwKAIVe33Ib8G -41OxwLlfLWhgQKDa3USpolNf6Qtj3cHQEB61XD7v9B6XbnPV1Wf65VJzyUJdYXQl -Rzr9zH+r9S/BeB+rCR7eljafYBvIAibmSYq9Cfsji2+bUjVRXGZos4SZNNa4xs/g -52o7L5B5PSNFr0zzNDcY24Pha1a7nlYc/hWnZ0YtSQsAxaPXj9MpxKQX8q+eCakY -CYN73zGoc4ILJfYVd6jxkcoWrRrvQxp3m/IujAJMm/6ZbSeYdGENtTsQHsnEo0de -8CcSUkQg3GX9xQXlZhH8D0WWnRm4n/KJ+pi82wiU9z99nTSq75TrvBmKCT+J8V1B -uVCzNXsk7zsTOwBEKU/4YSEZC+YeW2iyp765Ag0EXMgj7wEQAN304lBCDHd4oIsl -s9+B+N9ET5+/W2rUDt9tljB/uzJiifcVyDyFiMn5KKpWO/nTlPU3PRluupR+TdgX -kFM6Ogyqce7SPMHL5L3r1NzS565SISUOljuBFftlva/LRAsCcSBjvR0D2ycwejW1 -Ctv0lPAf8K0HvA8OlKFTUXJUkFG/43kMZvv4f3URfMZ72nhLyz+rApWX3HuEZvFl -BhdZPFXf/SHuKSSeVFIoNbMVwnccDFpC9eGdD/GD+0CEhxPzFGy27zjbehIQOHqq -zJCAELdlFIs4t3kRg5TVwe7lod+pCZNN+VKynx4cKGJP891UR8UO67YRlq/FCB6+ -npVnyHKF9bBM8ZGwG/UnIpFyL0rr4PPoQ9R5RoMz/e7TCRCW0fMPK3USoKsICKgr -CCtQIuTKO6oIRFe868uzt4KCkkbD/S/fqFz5ZA65fFnm776h9cFBxXFPWiCWp57S -Ji91z7hG0Hkut0CPM6EGSilq9am0LuzJv7RlOYv/pOQMoqGUUtiFWf3gYn8IaFgr -9LVeC5/djZj4I/BSLRJaHfhaHoNScL63tighnUbj6uDeCjpe6C2rwSPWulLAIqF6 -r2ZByLi2hBkyrJnMC2Ew4PH9AMPkyZMDFJ3qSNZiUgwIny+4jYZxfxdTspvZa7dT -kLk0Uw1McyV8SkSqHaxafulwEbHnABEBAAGJAh8EGAECAAkFAlzII+8CGwwACgkQ -isOykXSIXANq2hAAkyeNuWadGqieKA/rxX53hPvxAjYmCt6uyXJiq55/9A8FHCf6 -OZE2rF9z0zCy5F6O8S5mieK0c+7DrU06YHrippya3WMldLSn5X6Zh13vNJE8PhG0 -Aw6GQSKHz9C2jD3ScZsbUsEiXEM8WLQVC0VpcNXvNgGBY4eK1dwi4jI+YnqLS1Pm -xsVlh1oMAeqDRSgz1qznj+2ziKlQvBTSfTURchWsuQK9SBxpnUUmmwzPI9aZX07i -WVdbkqVqhB3oH50pP4aclYtxjXU778Wpe7stbGFnGHFm6rClC6keUO6rohM1eU1d -yMD4XQDWLIbpCSVNyd+uJTyqIwJcAgGnZ3g4HnVmbY2iTrWIgaAwFEoGU7B+iEVI -1ob5c9y085e8UKB7QXv1lb/XXCkE2EWPR2tDbU0Fsip20jNULSq8cQbrSSnDt2lw -jLyNTiMDUHhVHnuMNktJ2sOwrNAwATlZHftDSxEoj3Y0XAsdVEbMyRvcxdpb8QDR -4pezrAGj+TlzzqnItDmHhElSxyCf5wbTy5vBEfFNiBRtz0WCmnmnsr61GWH7xtEi -TDmj/BvGxRwE2a0IEwl5ASTIGzxxHKQm7VIOxd9fwYBkuCrNtylc4mw+g8w0lhpt -HCm81Da4TubPdAgobrQGlnMVDmgAcN20+RakdKamaki/c5u+pAvEkYNLvlM= -=SQlh ------END PGP PUBLIC KEY BLOCK----- - |
