mirror of
https://github.com/f-droid/fdroidserver.git
synced 2025-11-04 22:40:29 +03:00
Merge branch 'apksigner-entry-jar' into 'master'
use apksigner to sign index-v2 with modern, supported algorithms Closes #1005 See merge request fdroid/fdroidserver!1134
This commit is contained in:
commit
39c1b11a14
8 changed files with 173 additions and 46 deletions
|
|
@ -125,7 +125,7 @@ ubuntu_lts_ppa:
|
||||||
- ./run-tests
|
- ./run-tests
|
||||||
|
|
||||||
|
|
||||||
# Test using Ubuntu/bionic LTS (supported til 2022) with all depends
|
# Test using Ubuntu/bionic LTS (supported til April, 2023) with all depends
|
||||||
# from pypi. The venv is used to isolate the dist tarball generation
|
# from pypi. The venv is used to isolate the dist tarball generation
|
||||||
# environment from the clean install environment.
|
# environment from the clean install environment.
|
||||||
ubuntu_bionic_pip:
|
ubuntu_bionic_pip:
|
||||||
|
|
@ -145,6 +145,11 @@ ubuntu_bionic_pip:
|
||||||
- tar tzf dist/fdroidserver-*.tar.gz
|
- tar tzf dist/fdroidserver-*.tar.gz
|
||||||
# back to bare machine to act as user's install machine
|
# back to bare machine to act as user's install machine
|
||||||
- $pip install --upgrade pip setuptools wheel # make this go away: "error: invalid command 'bdist_wheel'"
|
- $pip install --upgrade pip setuptools wheel # make this go away: "error: invalid command 'bdist_wheel'"
|
||||||
|
|
||||||
|
- export ANDROID_HOME=/opt/android-sdk
|
||||||
|
- $pip install sdkmanager
|
||||||
|
- sdkmanager 'build-tools;30.0.0'
|
||||||
|
|
||||||
- $pip install dist/fdroidserver-*.tar.gz
|
- $pip install dist/fdroidserver-*.tar.gz
|
||||||
- tar xzf dist/fdroidserver-*.tar.gz
|
- tar xzf dist/fdroidserver-*.tar.gz
|
||||||
- cd fdroidserver-*
|
- cd fdroidserver-*
|
||||||
|
|
|
||||||
|
|
@ -87,9 +87,10 @@ FDROID_PATH = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
|
||||||
# this is the build-tools version, aapt has a separate version that
|
# this is the build-tools version, aapt has a separate version that
|
||||||
# has to be manually set in test_aapt_version()
|
# has to be manually set in test_aapt_version()
|
||||||
MINIMUM_AAPT_BUILD_TOOLS_VERSION = '26.0.0'
|
MINIMUM_AAPT_BUILD_TOOLS_VERSION = '26.0.0'
|
||||||
|
# 30.0.0 is the first version to support --v4-signing-enabled.
|
||||||
# 26.0.2 is the first version recognizing md5 based signatures as valid again
|
# 26.0.2 is the first version recognizing md5 based signatures as valid again
|
||||||
# (as does android, so we want that)
|
# (as does android, so we want that)
|
||||||
MINIMUM_APKSIGNER_BUILD_TOOLS_VERSION = '26.0.2'
|
MINIMUM_APKSIGNER_BUILD_TOOLS_VERSION = '30.0.0'
|
||||||
|
|
||||||
VERCODE_OPERATION_RE = re.compile(r'^([ 0-9/*+-]|%c)+$')
|
VERCODE_OPERATION_RE = re.compile(r'^([ 0-9/*+-]|%c)+$')
|
||||||
|
|
||||||
|
|
@ -3412,6 +3413,18 @@ def get_min_sdk_version(apk):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def get_apksigner_smartcardoptions(smartcardoptions):
|
||||||
|
if '-providerName' in smartcardoptions.copy():
|
||||||
|
pos = smartcardoptions.index('-providerName')
|
||||||
|
# remove -providerName and it's argument
|
||||||
|
del smartcardoptions[pos]
|
||||||
|
del smartcardoptions[pos]
|
||||||
|
replacements = {'-storetype': '--ks-type',
|
||||||
|
'-providerClass': '--provider-class',
|
||||||
|
'-providerArg': '--provider-arg'}
|
||||||
|
return [replacements.get(n, n) for n in smartcardoptions]
|
||||||
|
|
||||||
|
|
||||||
def sign_apk(unsigned_path, signed_path, keyalias):
|
def sign_apk(unsigned_path, signed_path, keyalias):
|
||||||
"""Sign and zipalign an unsigned APK, then save to a new file, deleting the unsigned.
|
"""Sign and zipalign an unsigned APK, then save to a new file, deleting the unsigned.
|
||||||
|
|
||||||
|
|
@ -3429,16 +3442,7 @@ def sign_apk(unsigned_path, signed_path, keyalias):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if config['keystore'] == 'NONE':
|
if config['keystore'] == 'NONE':
|
||||||
apksigner_smartcardoptions = config['smartcardoptions'].copy()
|
signing_args = get_apksigner_smartcardoptions(config['smartcardoptions'])
|
||||||
if '-providerName' in apksigner_smartcardoptions:
|
|
||||||
pos = config['smartcardoptions'].index('-providerName')
|
|
||||||
# remove -providerName and it's argument
|
|
||||||
del apksigner_smartcardoptions[pos]
|
|
||||||
del apksigner_smartcardoptions[pos]
|
|
||||||
replacements = {'-storetype': '--ks-type',
|
|
||||||
'-providerClass': '--provider-class',
|
|
||||||
'-providerArg': '--provider-arg'}
|
|
||||||
signing_args = [replacements.get(n, n) for n in apksigner_smartcardoptions]
|
|
||||||
else:
|
else:
|
||||||
signing_args = ['--key-pass', 'env:FDROID_KEY_PASS']
|
signing_args = ['--key-pass', 'env:FDROID_KEY_PASS']
|
||||||
apksigner = config.get('apksigner', '')
|
apksigner = config.get('apksigner', '')
|
||||||
|
|
|
||||||
|
|
@ -858,7 +858,7 @@ def make_v2(apps, packages, repodir, repodict, requestsdict, fdroid_signing_key_
|
||||||
logging.debug(_('index-v2 must have a signature, use `fdroid signindex` to create it!'))
|
logging.debug(_('index-v2 must have a signature, use `fdroid signindex` to create it!'))
|
||||||
else:
|
else:
|
||||||
signindex.config = common.config
|
signindex.config = common.config
|
||||||
signindex.sign_index(repodir, json_name, signindex.HashAlg.SHA256)
|
signindex.sign_index(repodir, json_name)
|
||||||
|
|
||||||
|
|
||||||
def make_v1(apps, packages, repodir, repodict, requestsdict, fdroid_signing_key_fingerprints):
|
def make_v1(apps, packages, repodir, repodict, requestsdict, fdroid_signing_key_fingerprints):
|
||||||
|
|
@ -1345,7 +1345,7 @@ def make_v0(apps, apks, repodir, repodict, requestsdict, fdroid_signing_key_fing
|
||||||
os.remove(signed)
|
os.remove(signed)
|
||||||
else:
|
else:
|
||||||
signindex.config = common.config
|
signindex.config = common.config
|
||||||
signindex.sign_jar(signed)
|
signindex.sign_jar(signed, use_old_algs=True)
|
||||||
|
|
||||||
# Copy the repo icon into the repo directory...
|
# Copy the repo icon into the repo directory...
|
||||||
icon_dir = os.path.join(repodir, 'icons')
|
icon_dir = os.path.join(repodir, 'icons')
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import os
|
||||||
import time
|
import time
|
||||||
import zipfile
|
import zipfile
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from enum import Enum
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from . import _
|
from . import _
|
||||||
|
|
@ -34,29 +33,27 @@ options = None
|
||||||
start_timestamp = time.gmtime()
|
start_timestamp = time.gmtime()
|
||||||
|
|
||||||
|
|
||||||
HashAlg = Enum("SHA1", "SHA256")
|
def sign_jar(jar, use_old_algs=False):
|
||||||
|
"""Sign a JAR file with the best available algorithm.
|
||||||
|
|
||||||
|
The current signing method uses apksigner to sign the JAR so that
|
||||||
|
it will automatically select algorithms that are compatible with
|
||||||
|
Android SDK 23, which added the most recent algorithms:
|
||||||
|
https://developer.android.com/reference/java/security/Signature
|
||||||
|
|
||||||
def sign_jar(jar, hash_algorithm=None):
|
This signing method uses then inherits the default signing
|
||||||
"""Sign a JAR file with Java's jarsigner.
|
algothim settings, since Java and Android both maintain those.
|
||||||
|
That helps avoid a repeat of being stuck on an old signing
|
||||||
|
algorithm. That means specifically that this call to apksigner
|
||||||
|
does not specify any of the algorithms.
|
||||||
|
|
||||||
|
The old indexes must be signed by SHA1withRSA otherwise they will
|
||||||
|
no longer be compatible with old Androids.
|
||||||
|
|
||||||
This method requires a properly initialized config object.
|
This method requires a properly initialized config object.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if hash_algorithm == HashAlg.SHA256:
|
if use_old_algs:
|
||||||
args = [
|
|
||||||
config['jarsigner'],
|
|
||||||
'-keystore',
|
|
||||||
config['keystore'],
|
|
||||||
'-storepass:env',
|
|
||||||
'FDROID_KEY_STORE_PASS',
|
|
||||||
'-digestalg',
|
|
||||||
'SHA-256',
|
|
||||||
'-sigalg',
|
|
||||||
'SHA256withRSA',
|
|
||||||
jar,
|
|
||||||
config['repo_keyalias'],
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
# This does use old hashing algorithms, i.e. SHA1, but that's not
|
# This does use old hashing algorithms, i.e. SHA1, but that's not
|
||||||
# broken yet for file verification. This could be set to SHA256,
|
# broken yet for file verification. This could be set to SHA256,
|
||||||
# but then Android < 4.3 would not be able to verify it.
|
# but then Android < 4.3 would not be able to verify it.
|
||||||
|
|
@ -78,16 +75,46 @@ def sign_jar(jar, hash_algorithm=None):
|
||||||
args += config['smartcardoptions']
|
args += config['smartcardoptions']
|
||||||
else: # smardcards never use -keypass
|
else: # smardcards never use -keypass
|
||||||
args += ['-keypass:env', 'FDROID_KEY_PASS']
|
args += ['-keypass:env', 'FDROID_KEY_PASS']
|
||||||
|
else:
|
||||||
|
# https://developer.android.com/studio/command-line/apksigner
|
||||||
|
args = [
|
||||||
|
config['apksigner'],
|
||||||
|
'sign',
|
||||||
|
'--min-sdk-version',
|
||||||
|
'23', # enable all current algorithms
|
||||||
|
'--max-sdk-version',
|
||||||
|
'24', # avoid future incompatible algorithms
|
||||||
|
# disable all APK signature types, only use JAR sigs aka v1
|
||||||
|
'--v1-signing-enabled',
|
||||||
|
'true',
|
||||||
|
'--v2-signing-enabled',
|
||||||
|
'false',
|
||||||
|
'--v3-signing-enabled',
|
||||||
|
'false',
|
||||||
|
'--v4-signing-enabled',
|
||||||
|
'false',
|
||||||
|
'--ks',
|
||||||
|
config['keystore'],
|
||||||
|
'--ks-pass',
|
||||||
|
'env:FDROID_KEY_STORE_PASS',
|
||||||
|
'--ks-key-alias',
|
||||||
|
config['repo_keyalias'],
|
||||||
|
]
|
||||||
|
if config['keystore'] == 'NONE':
|
||||||
|
args += common.get_apksigner_smartcardoptions(config['smartcardoptions'])
|
||||||
|
else: # smardcards never use --key-pass
|
||||||
|
args += ['--key-pass', 'env:FDROID_KEY_PASS']
|
||||||
|
args += [jar]
|
||||||
env_vars = {
|
env_vars = {
|
||||||
'FDROID_KEY_STORE_PASS': config['keystorepass'],
|
'FDROID_KEY_STORE_PASS': config['keystorepass'],
|
||||||
'FDROID_KEY_PASS': config.get('keypass', ""),
|
'FDROID_KEY_PASS': config.get('keypass', ""),
|
||||||
}
|
}
|
||||||
p = common.FDroidPopen(args, envs=env_vars)
|
p = common.FDroidPopen(args, envs=env_vars)
|
||||||
if p.returncode != 0:
|
if p.returncode != 0:
|
||||||
raise FDroidException("Failed to sign %s!" % jar)
|
raise FDroidException("Failed to sign %s: %s" % (jar, p.output))
|
||||||
|
|
||||||
|
|
||||||
def sign_index(repodir, json_name, hash_algorithm=None):
|
def sign_index(repodir, json_name):
|
||||||
"""Sign index-v1.json to make index-v1.jar.
|
"""Sign index-v1.json to make index-v1.jar.
|
||||||
|
|
||||||
This is a bit different than index.jar: instead of their being index.xml
|
This is a bit different than index.jar: instead of their being index.xml
|
||||||
|
|
@ -109,7 +136,11 @@ def sign_index(repodir, json_name, hash_algorithm=None):
|
||||||
jar_file = os.path.join(repodir, name + '.jar')
|
jar_file = os.path.join(repodir, name + '.jar')
|
||||||
with zipfile.ZipFile(jar_file, 'w', zipfile.ZIP_DEFLATED) as jar:
|
with zipfile.ZipFile(jar_file, 'w', zipfile.ZIP_DEFLATED) as jar:
|
||||||
jar.write(index_file, json_name)
|
jar.write(index_file, json_name)
|
||||||
sign_jar(jar_file, hash_algorithm)
|
|
||||||
|
if json_name in ('index.xml', 'index-v1.json'):
|
||||||
|
sign_jar(jar_file, use_old_algs=True)
|
||||||
|
else:
|
||||||
|
sign_jar(jar_file)
|
||||||
|
|
||||||
|
|
||||||
def status_update_json(signed):
|
def status_update_json(signed):
|
||||||
|
|
@ -165,7 +196,7 @@ def main():
|
||||||
json_name = 'entry.json'
|
json_name = 'entry.json'
|
||||||
index_file = os.path.join(output_dir, json_name)
|
index_file = os.path.join(output_dir, json_name)
|
||||||
if os.path.exists(index_file):
|
if os.path.exists(index_file):
|
||||||
sign_index(output_dir, json_name, HashAlg.SHA256)
|
sign_index(output_dir, json_name)
|
||||||
logging.info('Signed ' + index_file)
|
logging.info('Signed ' + index_file)
|
||||||
signed.append(index_file)
|
signed.append(index_file)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -450,7 +450,7 @@ class CommonTest(unittest.TestCase):
|
||||||
sourcefile = os.path.join(sourcedir, f)
|
sourcefile = os.path.join(sourcedir, f)
|
||||||
testfile = os.path.join(testsdir, f)
|
testfile = os.path.join(testsdir, f)
|
||||||
shutil.copy(sourcefile, testsdir)
|
shutil.copy(sourcefile, testsdir)
|
||||||
fdroidserver.signindex.sign_jar(testfile)
|
fdroidserver.signindex.sign_jar(testfile, use_old_algs=True)
|
||||||
# these should be resigned, and therefore different
|
# these should be resigned, and therefore different
|
||||||
self.assertNotEqual(
|
self.assertNotEqual(
|
||||||
open(sourcefile, 'rb').read(), open(testfile, 'rb').read()
|
open(sourcefile, 'rb').read(), open(testfile, 'rb').read()
|
||||||
|
|
@ -872,6 +872,9 @@ class CommonTest(unittest.TestCase):
|
||||||
self.assertFalse(os.path.isfile(unsigned))
|
self.assertFalse(os.path.isfile(unsigned))
|
||||||
self.assertTrue(fdroidserver.common.verify_apk_signature(signed))
|
self.assertTrue(fdroidserver.common.verify_apk_signature(signed))
|
||||||
|
|
||||||
|
@unittest.skipUnless(
|
||||||
|
os.path.exists('tests/SystemWebView-repack.apk'), "file too big for sdist"
|
||||||
|
)
|
||||||
def test_resign_apk(self):
|
def test_resign_apk(self):
|
||||||
"""When using apksigner, it should resign signed APKs"""
|
"""When using apksigner, it should resign signed APKs"""
|
||||||
config = fdroidserver.common.read_config(fdroidserver.common.options)
|
config = fdroidserver.common.read_config(fdroidserver.common.options)
|
||||||
|
|
@ -2455,8 +2458,42 @@ class CommonTest(unittest.TestCase):
|
||||||
self.assertTrue(os.path.exists(f), f + ' was created')
|
self.assertTrue(os.path.exists(f), f + ' was created')
|
||||||
self.assertFalse(is_repo_file(f), f + ' not repo file')
|
self.assertFalse(is_repo_file(f), f + ' not repo file')
|
||||||
|
|
||||||
|
def test_get_apksigner_smartcardoptions(self):
|
||||||
|
testdir = tempfile.mkdtemp(
|
||||||
|
prefix=inspect.currentframe().f_code.co_name, dir=self.tmpdir
|
||||||
|
)
|
||||||
|
os.chdir(testdir)
|
||||||
|
with open('config.yml', 'w') as fp:
|
||||||
|
d = {
|
||||||
|
'smartcardoptions': '-storetype PKCS11'
|
||||||
|
' -providerName SunPKCS11-OpenSC'
|
||||||
|
' -providerClass sun.security.pkcs11.SunPKCS11'
|
||||||
|
' -providerArg opensc-fdroid.cfg'
|
||||||
|
}
|
||||||
|
yaml.dump(d, fp)
|
||||||
|
config = fdroidserver.common.read_config()
|
||||||
|
fdroidserver.common.config = config
|
||||||
|
self.assertTrue(isinstance(d['smartcardoptions'], str))
|
||||||
|
self.assertTrue(isinstance(config['smartcardoptions'], list))
|
||||||
|
self.assertEqual(
|
||||||
|
[
|
||||||
|
'--ks-type',
|
||||||
|
'PKCS11',
|
||||||
|
'--provider-class',
|
||||||
|
'sun.security.pkcs11.SunPKCS11',
|
||||||
|
'--provider-arg',
|
||||||
|
'opensc-fdroid.cfg',
|
||||||
|
],
|
||||||
|
fdroidserver.common.get_apksigner_smartcardoptions(
|
||||||
|
config['smartcardoptions']
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def test_get_smartcardoptions_list(self):
|
def test_get_smartcardoptions_list(self):
|
||||||
os.chdir(self.tmpdir)
|
testdir = tempfile.mkdtemp(
|
||||||
|
prefix=inspect.currentframe().f_code.co_name, dir=self.tmpdir
|
||||||
|
)
|
||||||
|
os.chdir(testdir)
|
||||||
with open('config.yml', 'w') as fp:
|
with open('config.yml', 'w') as fp:
|
||||||
fp.write(
|
fp.write(
|
||||||
textwrap.dedent(
|
textwrap.dedent(
|
||||||
|
|
@ -2491,7 +2528,10 @@ class CommonTest(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_smartcardoptions_spaces(self):
|
def test_get_smartcardoptions_spaces(self):
|
||||||
os.chdir(self.tmpdir)
|
testdir = tempfile.mkdtemp(
|
||||||
|
prefix=inspect.currentframe().f_code.co_name, dir=self.tmpdir
|
||||||
|
)
|
||||||
|
os.chdir(testdir)
|
||||||
with open('config.yml', 'w') as fp:
|
with open('config.yml', 'w') as fp:
|
||||||
fp.write(
|
fp.write(
|
||||||
textwrap.dedent(
|
textwrap.dedent(
|
||||||
|
|
@ -2519,7 +2559,10 @@ class CommonTest(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_smartcardoptions_config_py(self):
|
def test_get_smartcardoptions_config_py(self):
|
||||||
os.chdir(self.tmpdir)
|
testdir = tempfile.mkdtemp(
|
||||||
|
prefix=inspect.currentframe().f_code.co_name, dir=self.tmpdir
|
||||||
|
)
|
||||||
|
os.chdir(testdir)
|
||||||
with open('config.py', 'w') as fp:
|
with open('config.py', 'w') as fp:
|
||||||
fp.write(
|
fp.write(
|
||||||
textwrap.dedent(
|
textwrap.dedent(
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,17 @@ if use_apksigner; then
|
||||||
grep -F '<application id=' repo/index.xml > /dev/null
|
grep -F '<application id=' repo/index.xml > /dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------#
|
||||||
|
echo_header "TODO remove once buildserver image is upgraded to bullseye with apksigner"
|
||||||
|
|
||||||
|
if java -version 2>&1 | grep -F 1.8.0; then
|
||||||
|
echo "Skipping the rest because they require apksigner 30.0.0+ which does not run on Java8"
|
||||||
|
echo SUCCESS
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------#
|
#------------------------------------------------------------------------------#
|
||||||
echo_header "test UTF-8 metadata"
|
echo_header "test UTF-8 metadata"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import logging
|
||||||
import optparse
|
import optparse
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
@ -17,7 +18,7 @@ print('localmodule: ' + localmodule)
|
||||||
if localmodule not in sys.path:
|
if localmodule not in sys.path:
|
||||||
sys.path.insert(0, localmodule)
|
sys.path.insert(0, localmodule)
|
||||||
|
|
||||||
from fdroidserver import common, signindex, update
|
from fdroidserver import apksigcopier, common, signindex, update
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
|
@ -69,6 +70,8 @@ class SignindexTest(unittest.TestCase):
|
||||||
signindex.sign_index(str(self.repodir), 'index-v1.json')
|
signindex.sign_index(str(self.repodir), 'index-v1.json')
|
||||||
|
|
||||||
def test_signindex(self):
|
def test_signindex(self):
|
||||||
|
if common.find_apksigner({}) is None: # TODO remove me for buildserver-bullseye
|
||||||
|
self.skipTest('SKIPPING test_signindex, apksigner not installed!')
|
||||||
os.mkdir('archive')
|
os.mkdir('archive')
|
||||||
metadata = Path('metadata')
|
metadata = Path('metadata')
|
||||||
metadata.mkdir()
|
metadata.mkdir()
|
||||||
|
|
@ -96,6 +99,34 @@ class SignindexTest(unittest.TestCase):
|
||||||
signindex.main()
|
signindex.main()
|
||||||
for f in index_files:
|
for f in index_files:
|
||||||
self.assertTrue(f.exists(), '%s should exist!' % f)
|
self.assertTrue(f.exists(), '%s should exist!' % f)
|
||||||
|
self.assertFalse(os.path.exists('index-v2.jar')) # no JAR version of this file
|
||||||
|
|
||||||
|
# index.jar aka v0 must by signed by SHA1withRSA
|
||||||
|
f = 'repo/index.jar'
|
||||||
|
common.verify_jar_signature(f)
|
||||||
|
self.assertIsNone(apksigcopier.extract_v2_sig(f, expected=False))
|
||||||
|
cp = subprocess.run(
|
||||||
|
['jarsigner', '-verify', '-verbose', f], stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
self.assertTrue(b'SHA1withRSA' in cp.stdout)
|
||||||
|
|
||||||
|
# index-v1.jar must by signed by SHA1withRSA
|
||||||
|
f = 'repo/index-v1.jar'
|
||||||
|
common.verify_jar_signature(f)
|
||||||
|
self.assertIsNone(apksigcopier.extract_v2_sig(f, expected=False))
|
||||||
|
cp = subprocess.run(
|
||||||
|
['jarsigner', '-verify', '-verbose', f], stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
self.assertTrue(b'SHA1withRSA' in cp.stdout)
|
||||||
|
|
||||||
|
# entry.jar aka index v2 must by signed by a modern algorithm
|
||||||
|
f = 'repo/entry.jar'
|
||||||
|
common.verify_jar_signature(f)
|
||||||
|
self.assertIsNone(apksigcopier.extract_v2_sig(f, expected=False))
|
||||||
|
cp = subprocess.run(
|
||||||
|
['jarsigner', '-verify', '-verbose', f], stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
self.assertFalse(b'SHA1withRSA' in cp.stdout)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
|
|
@ -1165,6 +1165,8 @@ class UpdateTest(unittest.TestCase):
|
||||||
|
|
||||||
fdroidserver.common.options = Options
|
fdroidserver.common.options = Options
|
||||||
config = fdroidserver.common.read_config(fdroidserver.common.options)
|
config = fdroidserver.common.read_config(fdroidserver.common.options)
|
||||||
|
if 'apksigner' not in config: # TODO remove me for buildserver-bullseye
|
||||||
|
self.skipTest('SKIPPING test_update_with_AllowedAPKSigningKeys, apksigner not installed!')
|
||||||
config['repo_keyalias'] = 'sova'
|
config['repo_keyalias'] = 'sova'
|
||||||
config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
|
config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
|
||||||
config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
|
config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue