From cf64cdec78899e69df55dab0341d2098acfe30e8 Mon Sep 17 00:00:00 2001 From: Tom Cooks Date: Sun, 11 Oct 2026 04:05:03 -0400 Subject: Build unsigned; sign with apksigner to avoid the PKDS signing block --- app/build.gradle.kts | 32 +++----------------------------- tools/build-release.sh | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 29 deletions(-) create mode 100755 tools/build-release.sh diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c539960..473dd7f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,18 +1,7 @@ -import java.util.Properties - plugins { id("com.android.application") } -// Release signing is read from keystore.properties (git-ignored, present only on -// the maintainer's machine). CI (e.g. F-Droid) builds an unsigned APK. -val keystorePropertiesFile = rootProject.file("keystore.properties") -val keystoreProperties = Properties().apply { - if (keystorePropertiesFile.exists()) { - keystorePropertiesFile.inputStream().use { load(it) } - } -} - android { namespace = "com.tomcooks.reccoon" @@ -36,30 +25,15 @@ android { } } - signingConfigs { - if (keystorePropertiesFile.exists()) { - create("release") { - storeFile = file(keystoreProperties.getProperty("storeFile")) - storePassword = keystoreProperties.getProperty("storePassword") - keyAlias = keystoreProperties.getProperty("keyAlias") - keyPassword = keystoreProperties.getProperty("keyPassword") - } - } - } - buildTypes { debug { isMinifyEnabled = false } release { isMinifyEnabled = false - // Signed with the maintainer's key when keystore.properties is - // present; unsigned otherwise so F-Droid/CI signs it itself. - signingConfig = if (keystorePropertiesFile.exists()) { - signingConfigs.getByName("release") - } else { - null - } + // Built unsigned on purpose. Sign with tools/build-release.sh, which + // uses the SDK apksigner instead of AGP: AGP adds a "Dependency + // metadata" (PKDS) signing block that F-Droid's scanner rejects. proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" diff --git a/tools/build-release.sh b/tools/build-release.sh new file mode 100755 index 0000000..588caa2 --- /dev/null +++ b/tools/build-release.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Build and sign a release APK with the maintainer key. +# +# Signing is done with the Android SDK apksigner rather than AGP: AGP adds a +# "Dependency metadata" (PKDS) block to the APK signing block, which F-Droid's +# scanner rejects. The content of the APK is unchanged either way. +# +# Needs keystore.properties in the repo root (git-ignored), with: +# storeFile=... storePassword=... keyAlias=... keyPassword=... +set -euo pipefail +cd "$(dirname "$0")/.." + +PROPS=keystore.properties +if [ ! -f "$PROPS" ]; then + echo "Missing $PROPS (keystore path + passwords). See README-BACKUP.txt." >&2 + exit 1 +fi + +VERSION=$(sed -nE 's/.*versionName *= *"(.*)".*/\1/p' app/build.gradle.kts | head -1) +KS=$(sed -nE 's/^storeFile=(.*)$/\1/p' "$PROPS") +ALIAS=$(sed -nE 's/^keyAlias=(.*)$/\1/p' "$PROPS") +export RECCOON_STORE_PASS=$(sed -nE 's/^storePassword=(.*)$/\1/p' "$PROPS") +export RECCOON_KEY_PASS=$(sed -nE 's/^keyPassword=(.*)$/\1/p' "$PROPS") + +SDK="${ANDROID_HOME:-$(sed -nE 's/^sdk\.dir=(.*)$/\1/p' local.properties)}" +APKSIGNER=$(ls -1 "$SDK"/build-tools/*/apksigner 2>/dev/null | sort -V | tail -1) +if [ ! -x "$APKSIGNER" ]; then + echo "apksigner not found under $SDK/build-tools" >&2 + exit 1 +fi + +echo "==> Building unsigned release ($VERSION)" +./gradlew :app:assembleRelease + +UNSIGNED=app/build/outputs/apk/release/app-release-unsigned.apk +[ -f "$UNSIGNED" ] || UNSIGNED=app/build/outputs/apk/release/app-release.apk +OUT="releases/RECCoon-${VERSION}.apk" +mkdir -p releases dist + +echo "==> Signing with $APKSIGNER" +"$APKSIGNER" sign --ks "$KS" --ks-key-alias "$ALIAS" \ + --ks-pass env:RECCOON_STORE_PASS --key-pass env:RECCOON_KEY_PASS \ + --out "$OUT" "$UNSIGNED" +cp "$OUT" dist/ + +echo "==> Result" +"$APKSIGNER" verify --print-certs "$OUT" | grep -E "DN:|SHA-256 digest" | head -3 +sha256sum "$OUT" -- cgit v1.2.3