fix: qualify mobile Cloud viewer and companion downloads

This commit is contained in:
archipelago
2026-10-05 14:41:08 -04:00
parent daac47cac4
commit 5aa74d0513
22 changed files with 1173 additions and 197 deletions
+10 -3
View File
@@ -71,15 +71,22 @@ echo "publish-companion-apk: zipalign + sign (v1+v2+v3)…" >&2
"$SIGNED"
# 4. Verify all three schemes (min-sdk 21 forces the v1 path to be exercised).
VERIFY="$("$APKSIGNER" verify -v --min-sdk-version 21 "$SIGNED" 2>&1)"
VERIFY="$("$APKSIGNER" verify -v --min-sdk-version 21 --print-certs "$SIGNED" 2>&1)"
for scheme in "v1 scheme" "v2 scheme" "v3 scheme"; do
if ! printf '%s\n' "$VERIFY" | grep -iq "$scheme.*: true"; then
if ! grep -iq "$scheme.*: true" <<< "$VERIFY"; then
echo "publish-companion-apk: ERROR — $scheme NOT present after signing. Aborting." >&2
printf '%s\n' "$VERIFY" | grep -iE "scheme" >&2
exit 1
fi
done
echo "publish-companion-apk: verified v1 + v2 + v3 signatures." >&2
# The existing shared companion identity must survive updates. Verifying a new
# certificate's mathematical validity alone does not establish upgrade compatibility.
EXPECTED_SIGNER_SHA256="d622e07e7f474246e8e2bcee828ca9bf6c6cdf9434c065c58fe89bb4eec2664d"
if ! grep -iq "Signer #1 certificate SHA-256 digest: $EXPECTED_SIGNER_SHA256" <<< "$VERIFY"; then
echo "publish-companion-apk: ERROR — signing identity differs from the existing companion. Aborting." >&2
exit 1
fi
echo "publish-companion-apk: verified v1 + v2 + v3 signatures and existing signer." >&2
# 5. Publish.
mkdir -p "$(dirname "$DEST")"
@@ -0,0 +1,41 @@
"""Run the publisher's actual verifier block, including noisy apksigner output."""
import os
import pathlib
import subprocess
import tempfile
import unittest
ROOT = pathlib.Path(__file__).resolve().parents[2]
SCRIPT = (ROOT / 'scripts/publish-companion-apk.sh').read_text()
BLOCK = SCRIPT[SCRIPT.index('# 4. Verify'):SCRIPT.index('# 5. Publish')]
CERT = 'd622e07e7f474246e8e2bcee828ca9bf6c6cdf9434c065c58fe89bb4eec2664d'
GOOD = '\n'.join(f'Verified using {v} scheme (test): true' for v in ['v1', 'v2', 'v3']) + '\nSigner #1 certificate SHA-256 digest: ' + CERT
class VerificationTests(unittest.TestCase):
def check(self, output, code=0):
with tempfile.TemporaryDirectory() as tmp:
root = pathlib.Path(tmp)
verifier = root / 'apksigner'
verifier.write_text('#!/bin/sh\ncat "$TEST_VERIFY_OUTPUT"\nexit "$TEST_VERIFY_CODE"\n')
verifier.chmod(0o700)
(root / 'output').write_text(output)
env = dict(os.environ, APKSIGNER=str(verifier), SIGNED=str(root / 'test.apk'),
TEST_VERIFY_OUTPUT=str(root / 'output'), TEST_VERIFY_CODE=str(code))
return subprocess.run(['bash', '-c', 'set -euo pipefail\n' + BLOCK], env=env, capture_output=True, text=True).returncode
def test_noisy_valid_apk_does_not_fail_from_grep_sigpipe(self):
# Reproduces pipefail+grep -q exit141 after an otherwise valid APK.
self.assertEqual(self.check(GOOD + '\n' + 'WARNING: compatible signature algorithm\n' * 4000), 0)
def test_all_three_schemes_are_required(self):
for version in ['v1', 'v2', 'v3']:
with self.subTest(version=version):
self.assertNotEqual(self.check(GOOD.replace(f'{version} scheme (test): true', f'{version} scheme (test): false')), 0)
def test_wrong_signing_identity_fails(self):
self.assertNotEqual(self.check(GOOD.replace(CERT, '0' * 64)), 0)
def test_verifier_failure_is_never_accepted(self):
self.assertNotEqual(self.check(GOOD, 1), 0)
if __name__ == '__main__':
unittest.main()