mirror of
https://github.com/f-droid/fdroidserver.git
synced 2025-09-14 06:52:39 +03:00
publish: always use apksigner to sign APKs, closes #880
This commit is contained in:
parent
08cde5c2e6
commit
50f0534d87
1 changed files with 38 additions and 73 deletions
|
@ -3001,7 +3001,7 @@ def _zipalign(unsigned_apk, aligned_apk):
|
||||||
|
|
||||||
|
|
||||||
def apk_implant_signatures(apkpath, signaturefile, signedfile, manifest):
|
def apk_implant_signatures(apkpath, signaturefile, signedfile, manifest):
|
||||||
"""Implats a signature from metadata into an APK.
|
"""Implants a signature from metadata into an APK.
|
||||||
|
|
||||||
Note: this changes there supplied APK in place. So copy it if you
|
Note: this changes there supplied APK in place. So copy it if you
|
||||||
need the original to be preserved.
|
need the original to be preserved.
|
||||||
|
@ -3061,82 +3061,47 @@ def get_min_sdk_version(apk):
|
||||||
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
|
||||||
|
|
||||||
Use apksigner for making v2 and v3 signature for apks with targetSDK >=30 as
|
NONE is a Java keyword used to configure smartcards as the
|
||||||
otherwise they won't be installable on Android 11/R.
|
keystore. Otherwise, the keystore is a local file.
|
||||||
|
https://docs.oracle.com/javase/7/docs/technotes/guides/security/p11guide.html#KeyToolJarSigner
|
||||||
|
|
||||||
Otherwise use jarsigner for v1 only signatures until we have apksig v2/v3
|
When using smartcards, apksigner does not use the same options has
|
||||||
signature transplantig support.
|
Java/keytool/jarsigner (-providerName, -providerClass,
|
||||||
|
-providerArg, -storetype). apksigner documents the options as
|
||||||
When using jarsigner we need to manually select the hash algorithm,
|
--ks-provider-class and --ks-provider-arg. Those seem to be
|
||||||
apksigner does this automatically. Apksigner also does the zipalign for us.
|
accepted but fail when actually making a signature with weird
|
||||||
|
internal exceptions. We use the options that actually work. From:
|
||||||
SHA-256 support was added in android-18 (4.3), before then, the only options were MD5
|
https://geoffreymetais.github.io/code/key-signing/#scripting
|
||||||
and SHA1. This aims to use SHA-256 when the APK does not target
|
|
||||||
older Android versions, and is therefore safe to do so.
|
|
||||||
|
|
||||||
https://issuetracker.google.com/issues/36956587
|
|
||||||
https://android-review.googlesource.com/c/platform/libcore/+/44491
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
apk = _get_androguard_APK(unsigned_path)
|
if config['keystore'] == 'NONE':
|
||||||
if apk.get_effective_target_sdk_version() >= 30:
|
apksigner_smartcardoptions = config['smartcardoptions'].copy()
|
||||||
if config['keystore'] == 'NONE':
|
if '-providerName' in apksigner_smartcardoptions:
|
||||||
# NOTE: apksigner doesn't like -providerName/--provider-name at all, don't use that.
|
pos = config['smartcardoptions'].index('-providerName')
|
||||||
# apksigner documents the options as --ks-provider-class and --ks-provider-arg
|
# remove -providerName and it's argument
|
||||||
# those seem to be accepted but fail when actually making a signature with
|
del apksigner_smartcardoptions[pos]
|
||||||
# weird internal exceptions. Those options actually work.
|
del apksigner_smartcardoptions[pos]
|
||||||
# From: https://geoffreymetais.github.io/code/key-signing/#scripting
|
replacements = {'-storetype': '--ks-type',
|
||||||
apksigner_smartcardoptions = config['smartcardoptions'].copy()
|
'-providerClass': '--provider-class',
|
||||||
if '-providerName' in apksigner_smartcardoptions:
|
'-providerArg': '--provider-arg'}
|
||||||
pos = config['smartcardoptions'].index('-providerName')
|
signing_args = [replacements.get(n, n) for n in apksigner_smartcardoptions]
|
||||||
# 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:
|
|
||||||
signing_args = ['--key-pass', 'env:FDROID_KEY_PASS']
|
|
||||||
if not find_apksigner():
|
|
||||||
raise BuildException(_("apksigner not found, it's required for signing!"))
|
|
||||||
cmd = [find_apksigner(), 'sign',
|
|
||||||
'--ks', config['keystore'],
|
|
||||||
'--ks-pass', 'env:FDROID_KEY_STORE_PASS']
|
|
||||||
cmd += signing_args
|
|
||||||
cmd += ['--ks-key-alias', keyalias,
|
|
||||||
'--in', unsigned_path,
|
|
||||||
'--out', signed_path]
|
|
||||||
p = FDroidPopen(cmd, envs={
|
|
||||||
'FDROID_KEY_STORE_PASS': config['keystorepass'],
|
|
||||||
'FDROID_KEY_PASS': config.get('keypass', "")})
|
|
||||||
if p.returncode != 0:
|
|
||||||
raise BuildException(_("Failed to sign application"), p.output)
|
|
||||||
os.remove(unsigned_path)
|
|
||||||
else:
|
else:
|
||||||
|
signing_args = ['--key-pass', 'env:FDROID_KEY_PASS']
|
||||||
if get_min_sdk_version(apk) < 18:
|
if not find_apksigner():
|
||||||
signature_algorithm = ['-sigalg', 'SHA1withRSA', '-digestalg', 'SHA1']
|
raise BuildException(_("apksigner not found, it's required for signing!"))
|
||||||
else:
|
cmd = [find_apksigner(), 'sign',
|
||||||
signature_algorithm = ['-sigalg', 'SHA256withRSA', '-digestalg', 'SHA-256']
|
'--ks', config['keystore'],
|
||||||
if config['keystore'] == 'NONE':
|
'--ks-pass', 'env:FDROID_KEY_STORE_PASS']
|
||||||
signing_args = config['smartcardoptions']
|
cmd += signing_args
|
||||||
else:
|
cmd += ['--ks-key-alias', keyalias,
|
||||||
signing_args = ['-keypass:env', 'FDROID_KEY_PASS']
|
'--in', unsigned_path,
|
||||||
|
'--out', signed_path]
|
||||||
cmd = [config['jarsigner'], '-keystore', config['keystore'],
|
p = FDroidPopen(cmd, envs={
|
||||||
'-storepass:env', 'FDROID_KEY_STORE_PASS']
|
'FDROID_KEY_STORE_PASS': config['keystorepass'],
|
||||||
cmd += signing_args
|
'FDROID_KEY_PASS': config.get('keypass', "")})
|
||||||
cmd += signature_algorithm
|
if p.returncode != 0:
|
||||||
cmd += [unsigned_path, keyalias]
|
raise BuildException(_("Failed to sign application"), p.output)
|
||||||
p = FDroidPopen(cmd, envs={
|
os.remove(unsigned_path)
|
||||||
'FDROID_KEY_STORE_PASS': config['keystorepass'],
|
|
||||||
'FDROID_KEY_PASS': config.get('keypass', "")})
|
|
||||||
if p.returncode != 0:
|
|
||||||
raise BuildException(_("Failed to sign application"), p.output)
|
|
||||||
|
|
||||||
_zipalign(unsigned_path, signed_path)
|
|
||||||
os.remove(unsigned_path)
|
|
||||||
|
|
||||||
|
|
||||||
def verify_apks(signed_apk, unsigned_apk, tmp_dir):
|
def verify_apks(signed_apk, unsigned_apk, tmp_dir):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue