From accdd65f91e2850cc071b45258ddbed483618e09 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 19 Apr 2024 23:22:51 +0200 Subject: [PATCH] also handle APKs entirely without JAR/v1 signatures future-proofing! --- MANIFEST.in | 1 + tests/common.TestCase | 23 ++++++++++++++++++++++- tests/issue-1128-min-sdk-30-poc.apk | Bin 0 -> 10728 bytes 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/issue-1128-min-sdk-30-poc.apk diff --git a/MANIFEST.in b/MANIFEST.in index 05a022b2..ee15b587 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -591,6 +591,7 @@ include tests/index.TestCase include tests/init.TestCase include tests/install.TestCase include tests/IsMD5Disabled.java +include tests/issue-1128-min-sdk-30-poc.apk include tests/janus.apk include tests/keystore.jks include tests/key-tricks.py diff --git a/tests/common.TestCase b/tests/common.TestCase index 52522b14..4739ddab 100755 --- a/tests/common.TestCase +++ b/tests/common.TestCase @@ -1039,6 +1039,7 @@ class CommonTest(unittest.TestCase): ('org.bitbucket.tickytacky.mirrormirror_3.apk', 'org.bitbucket.tickytacky.mirrormirror', 3, '1.0.2'), ('org.bitbucket.tickytacky.mirrormirror_4.apk', 'org.bitbucket.tickytacky.mirrormirror', 4, '1.0.3'), ('org.dyndns.fules.ck_20.apk', 'org.dyndns.fules.ck', 20, 'v1.6pre2'), + ('issue-1128-min-sdk-30-poc.apk', 'org.fdroid.ci', 1, '1.0'), ('urzip.apk', 'info.guardianproject.urzip', 100, '0.1'), ('urzip-badcert.apk', 'info.guardianproject.urzip', 100, '0.1'), ('urzip-badsig.apk', 'info.guardianproject.urzip', 100, '0.1'), @@ -1154,6 +1155,7 @@ class CommonTest(unittest.TestCase): return apk.get_effective_target_sdk_version() self.assertEqual(4, get_minSdkVersion('bad-unicode-πÇÇ现代通用字-български-عربي1.apk')) + self.assertEqual(30, get_minSdkVersion('issue-1128-min-sdk-30-poc.apk')) self.assertEqual(14, get_minSdkVersion('org.bitbucket.tickytacky.mirrormirror_1.apk')) self.assertEqual(14, get_minSdkVersion('org.bitbucket.tickytacky.mirrormirror_2.apk')) self.assertEqual(14, get_minSdkVersion('org.bitbucket.tickytacky.mirrormirror_3.apk')) @@ -1164,6 +1166,7 @@ class CommonTest(unittest.TestCase): self.assertEqual(4, get_minSdkVersion('urzip-badsig.apk')) self.assertEqual(4, get_minSdkVersion('urzip-release.apk')) self.assertEqual(4, get_minSdkVersion('urzip-release-unsigned.apk')) + self.assertEqual(27, get_minSdkVersion('v2.only.sig_2.apk')) self.assertEqual(3, get_minSdkVersion('repo/com.politedroid_3.apk')) self.assertEqual(3, get_minSdkVersion('repo/com.politedroid_4.apk')) self.assertEqual(3, get_minSdkVersion('repo/com.politedroid_5.apk')) @@ -3033,6 +3036,16 @@ APKS_WITH_JAR_SIGNATURES = ( '7eabd8c15de883d1e82b5df2fd4f7f769e498078e9ad6dc901f0e96db77ceac3', ), ) +APKS_WITHOUT_JAR_SIGNATURES = ( + ( + 'issue-1128-min-sdk-30-poc.apk', # APK v3 Signature only + '09350d5f3460a8a0ea5cf6b68ccd296a58754f7e683ba6aa08c19be8353504f3', + ), + ( + 'v2.only.sig_2.apk', + '32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6', + ), +) class SignerExtractionTest(unittest.TestCase): @@ -3090,7 +3103,7 @@ class SignerExtractionTest(unittest.TestCase): unittest.skipUnless(self.apksigner, 'requires apksigner to run') pat = re.compile(r'\s[0-9a-f]{64}\s') cmd = [self.apksigner, 'verify', '--print-certs'] - for apk, fingerprint in APKS_WITH_JAR_SIGNATURES: + for apk, fingerprint in APKS_WITH_JAR_SIGNATURES + APKS_WITHOUT_JAR_SIGNATURES: output = subprocess.check_output(cmd + [apk], text=True) self.assertEqual( fingerprint, @@ -3106,6 +3119,14 @@ class SignerExtractionTest(unittest.TestCase): f'apk_signer_fingerprint should match stored fingerprint for {apk}', ) + def test_apk_signer_fingerprint_without_v1_apks(self): + for apk, fingerprint in APKS_WITHOUT_JAR_SIGNATURES: + self.assertEqual( + fingerprint, + fdroidserver.common.apk_signer_fingerprint(apk), + f'apk_signer_fingerprint should match stored fingerprint for {apk}', + ) + def test_get_first_signer_certificate_with_unsigned_jar(self): self.assertIsNone( fdroidserver.common.get_first_signer_certificate('signindex/unsigned.jar') diff --git a/tests/issue-1128-min-sdk-30-poc.apk b/tests/issue-1128-min-sdk-30-poc.apk new file mode 100644 index 0000000000000000000000000000000000000000..bef0297f49ef90014471bb39874b2de93af98884 GIT binary patch literal 10728 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 literal 0 HcmV?d00001