M464 loudness leveling (steps 4–8), APK distribution and security baseline adoptions #136

Merged
bvandeusen merged 12 commits from dev into main 2026-10-06 23:11:36 -04:00
Showing only changes of commit 40dd5bb52c - Show all commits
+25 -9
View File
@@ -523,23 +523,39 @@ jobs:
-PMINSTREL_VERSION_NAME=${{ steps.ver.outputs.name }} \ -PMINSTREL_VERSION_NAME=${{ steps.ver.outputs.name }} \
-PMINSTREL_VERSION_CODE=${{ steps.ver.outputs.code }} -PMINSTREL_VERSION_CODE=${{ steps.ver.outputs.code }}
# The APK every phone updates from must carry the release key: Android # The APK every phone updates from must carry THE release key: Android
# updates an app in place only when the signer matches. Gradle signs # updates an app in place only when the signer matches, so an APK
# with the release key or leaves the APK unsigned, so this catches a # signed by any other key (debug, a regenerated keystore, a swapped
# wrong key, an unsigned build and a debug signer before anything # secret) reaches no installed phone. The certificate's digest is
# publishes (family idea #5103, practice 3). apksigner, not keytool: # pinned below; it is public, not a secret. Gradle signs with the
# keytool prints nothing for a v2-only APK. # release key or leaves the APK unsigned, and an unsigned build fails
# here too, as there is no app-release.apk to verify (family idea
# #5103, practice 3). apksigner, not keytool: keytool prints nothing
# for a v2-only APK.
#
# Rotating the key on purpose means every install must be removed and
# reinstalled; change the digest here in the same commit.
- name: The APK carries the release key - name: The APK carries the release key
shell: bash shell: bash
env:
# CN=Minstrel, O=FabledSword. Read from run 8446 (#5116).
RELEASE_CERT_SHA256: 43d183307bc46b821789d90444a960b137f78f2166ff431efb2406d0fceaf612
run: | run: |
set -euo pipefail set -euo pipefail
sdk="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}" sdk="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}"
signer="$(ls "$sdk"/build-tools/*/apksigner 2>/dev/null | sort -V | tail -1 || true)" signer="$(ls "$sdk"/build-tools/*/apksigner 2>/dev/null | sort -V | tail -1 || true)"
test -n "$signer" || { echo "::error::no apksigner under '$sdk/build-tools'"; exit 1; } test -n "$signer" || { echo "::error::no apksigner under '$sdk/build-tools'"; exit 1; }
certs="$("$signer" verify --print-certs app/build/outputs/apk/release/app-release.apk)" certs="$("$signer" verify --print-certs app/build/outputs/apk/release/app-release.apk)"
printf '%s\n' "$certs" | grep -E 'Signer #1 certificate (DN|SHA-256 digest)' printf '%s\n' "$certs" | grep -E '^Signer #[0-9]+ certificate (DN|SHA-256 digest)'
if printf '%s' "$certs" | grep -q 'CN=Android Debug'; then # One signer, and it is ours. A second signer would be a lineage or
echo "::error::the release APK is signed with a debug key" # a mistake; either way not something to ship unexamined.
digests="$(printf '%s\n' "$certs" | sed -n 's/^Signer #[0-9]* certificate SHA-256 digest: //p')"
if [ "$digests" != "$RELEASE_CERT_SHA256" ]; then
if printf '%s' "$certs" | grep -q 'CN=Android Debug'; then
echo "::error::the release APK is signed with a debug key"
else
echo "::error::the release APK is not signed by the release key: got '${digests//$'\n'/ }', want ${RELEASE_CERT_SHA256}"
fi
exit 1 exit 1
fi fi