ci(release): sign fdroid references v2/v3 only (no v1) for reproducibility
All checks were successful
ci / analyze (push) Successful in 1m14s
ci / test-commons-core (push) Successful in 45s
ci / test-app-seeds (push) Successful in 6m28s

The reproducible-build verify failed even after the /home/vagrant path fix
made every file identical: our reference APK carried a v1 (JAR) signature,
which adds META-INF/{MANIFEST.MF,*.SF,*.RSA} as three extra ZIP ENTRIES.
F-Droid's apksigcopier transplants only the v2/v3 signing block onto its
rebuild, so those 3 v1 entries make the reference's signed content differ
from F-Droid's build — apksigner then reports a v3 CHUNKED_SHA512 digest
mismatch though 'diff -r' shows no file differences. Proven by zipinfo: our
ref had 486 entries vs F-Droid's 483, the delta being exactly the v1 files;
the shared 483 are byte-identical. minSdk is 24 so v1 is never needed.
Sign v2/v3 only so the reference byte-matches F-Droid's rebuild.
This commit is contained in:
vjrj 2026-07-22 20:37:38 +02:00
parent 8818576ee8
commit 6c9de115e9

View file

@ -239,8 +239,16 @@ jobs:
fi
echo "$TANE_KEYSTORE_BASE64" | base64 -d > /tmp/ks.jks
out="/tmp/app-${ABI}-release.apk"
# v2/v3 only — NO v1 (JAR) signature. minSdk is 24, so v1 is never
# needed, and v1 adds META-INF/*.SF/*.RSA/MANIFEST.MF as zip ENTRIES
# that F-Droid's rebuild doesn't have. F-Droid's apksigcopier transplants
# only the v2/v3 signing block, so those extra v1 entries make the
# reference's signed content differ from F-Droid's rebuild (CHUNKED_SHA512
# mismatch) even when every file is identical. Dropping v1 makes the
# reference byte-match F-Droid's build so the signature copy verifies.
"$apksigner" sign --ks /tmp/ks.jks --ks-key-alias "$TANE_KEY_ALIAS" \
--ks-pass "pass:$TANE_KEYSTORE_PASSWORD" --key-pass "pass:$TANE_KEY_PASSWORD" \
--v1-signing-enabled false --v2-signing-enabled true --v3-signing-enabled true \
--out "$out" "$f"
# Prove the signer cert matches AllowedAPKSigningKeys.
"$apksigner" verify --print-certs "$out" | grep -i 'SHA-256' || true
@ -357,8 +365,16 @@ jobs:
fi
echo "$TANE_KEYSTORE_BASE64" | base64 -d > /tmp/ks.jks
out="/tmp/app-${ABI}-release.apk"
# v2/v3 only — NO v1 (JAR) signature. minSdk is 24, so v1 is never
# needed, and v1 adds META-INF/*.SF/*.RSA/MANIFEST.MF as zip ENTRIES
# that F-Droid's rebuild doesn't have. F-Droid's apksigcopier transplants
# only the v2/v3 signing block, so those extra v1 entries make the
# reference's signed content differ from F-Droid's rebuild (CHUNKED_SHA512
# mismatch) even when every file is identical. Dropping v1 makes the
# reference byte-match F-Droid's build so the signature copy verifies.
"$apksigner" sign --ks /tmp/ks.jks --ks-key-alias "$TANE_KEY_ALIAS" \
--ks-pass "pass:$TANE_KEYSTORE_PASSWORD" --key-pass "pass:$TANE_KEY_PASSWORD" \
--v1-signing-enabled false --v2-signing-enabled true --v3-signing-enabled true \
--out "$out" "$f"
"$apksigner" verify --print-certs "$out" | grep -i 'SHA-256' || true
rm -f /tmp/ks.jks
@ -473,8 +489,16 @@ jobs:
fi
echo "$TANE_KEYSTORE_BASE64" | base64 -d > /tmp/ks.jks
out="/tmp/app-${ABI}-release.apk"
# v2/v3 only — NO v1 (JAR) signature. minSdk is 24, so v1 is never
# needed, and v1 adds META-INF/*.SF/*.RSA/MANIFEST.MF as zip ENTRIES
# that F-Droid's rebuild doesn't have. F-Droid's apksigcopier transplants
# only the v2/v3 signing block, so those extra v1 entries make the
# reference's signed content differ from F-Droid's rebuild (CHUNKED_SHA512
# mismatch) even when every file is identical. Dropping v1 makes the
# reference byte-match F-Droid's build so the signature copy verifies.
"$apksigner" sign --ks /tmp/ks.jks --ks-key-alias "$TANE_KEY_ALIAS" \
--ks-pass "pass:$TANE_KEYSTORE_PASSWORD" --key-pass "pass:$TANE_KEY_PASSWORD" \
--v1-signing-enabled false --v2-signing-enabled true --v3-signing-enabled true \
--out "$out" "$f"
"$apksigner" verify --print-certs "$out" | grep -i 'SHA-256' || true
rm -f /tmp/ks.jks