1
0
mirror of https://gitlab.com/fdroid/fdroidserver.git synced 2024-07-04 16:30:12 +02:00

Merge branch 'smartcard_hsm' into 'master'

switch publish to common.sign_apk and support smartcard HSMs for app signing

See merge request fdroid/fdroidserver!782
This commit is contained in:
Hans-Christoph Steiner 2020-08-17 10:09:35 +00:00
commit 6258a939e6
5 changed files with 65 additions and 55 deletions

View File

@ -3045,13 +3045,16 @@ def sign_apk(unsigned_path, signed_path, keyalias):
else:
signature_algorithm = ['-sigalg', 'SHA256withRSA', '-digestalg', 'SHA-256']
p = FDroidPopen([config['jarsigner'], '-keystore', config['keystore'],
'-storepass:env', 'FDROID_KEY_STORE_PASS',
'-keypass:env', 'FDROID_KEY_PASS']
+ signature_algorithm + [unsigned_path, keyalias],
cmd = [config['jarsigner'], '-keystore', config['keystore'],
'-storepass:env', 'FDROID_KEY_STORE_PASS']
if config['keystore'] == 'NONE':
cmd += config['smartcardoptions']
else:
cmd += '-keypass:env', 'FDROID_KEY_PASS'
p = FDroidPopen(cmd + signature_algorithm + [unsigned_path, keyalias],
envs={
'FDROID_KEY_STORE_PASS': config['keystorepass'],
'FDROID_KEY_PASS': config['keypass'], })
'FDROID_KEY_PASS': config.get('keypass', "")})
if p.returncode != 0:
raise BuildException(_("Failed to sign application"), p.output)
@ -3064,7 +3067,7 @@ def verify_apks(signed_apk, unsigned_apk, tmp_dir):
One of the inputs is signed, the other is unsigned. The signature metadata
is transferred from the signed to the unsigned apk, and then jarsigner is
used to verify that the signature from the signed apk is also varlid for
used to verify that the signature from the signed apk is also valid for
the unsigned one. If the APK given as unsigned actually does have a
signature, it will be stripped out and ignored.
@ -3342,26 +3345,33 @@ def genkeystore(localconfig):
env_vars = {'LC_ALL': 'C.UTF-8',
'FDROID_KEY_STORE_PASS': localconfig['keystorepass'],
'FDROID_KEY_PASS': localconfig['keypass']}
p = FDroidPopen([config['keytool'], '-genkey',
'-keystore', localconfig['keystore'],
'-alias', localconfig['repo_keyalias'],
'-keyalg', 'RSA', '-keysize', '4096',
'-sigalg', 'SHA256withRSA',
'-validity', '10000',
'-storepass:env', 'FDROID_KEY_STORE_PASS',
'-keypass:env', 'FDROID_KEY_PASS',
'-dname', localconfig['keydname'],
'-J-Duser.language=en'], envs=env_vars)
'FDROID_KEY_PASS': localconfig.get('keypass', "")}
cmd = [config['keytool'], '-genkey',
'-keystore', localconfig['keystore'],
'-alias', localconfig['repo_keyalias'],
'-keyalg', 'RSA', '-keysize', '4096',
'-sigalg', 'SHA256withRSA',
'-validity', '10000',
'-storepass:env', 'FDROID_KEY_STORE_PASS',
'-dname', localconfig['keydname'],
'-J-Duser.language=en']
if localconfig['keystore'] == "NONE":
cmd += localconfig['smartcardoptions']
else:
cmd += '-keypass:env', 'FDROID_KEY_PASS'
p = FDroidPopen(cmd, envs=env_vars)
if p.returncode != 0:
raise BuildException("Failed to generate key", p.output)
os.chmod(localconfig['keystore'], 0o0600)
if localconfig['keystore'] != "NONE":
os.chmod(localconfig['keystore'], 0o0600)
if not options.quiet:
# now show the lovely key that was just generated
p = FDroidPopen([config['keytool'], '-list', '-v',
'-keystore', localconfig['keystore'],
'-alias', localconfig['repo_keyalias'],
'-storepass:env', 'FDROID_KEY_STORE_PASS', '-J-Duser.language=en'], envs=env_vars)
'-storepass:env', 'FDROID_KEY_STORE_PASS', '-J-Duser.language=en']
+ config['smartcardoptions'], envs=env_vars)
logging.info(p.output.strip() + '\n\n')
# get the public key
p = FDroidPopenBytes([config['keytool'], '-exportcert',

View File

@ -215,6 +215,9 @@ def main():
f.write('name = OpenSC\nlibrary = ')
f.write(opensc_so)
f.write('\n')
logging.info("Repo setup using a smartcard HSM. Please edit keystorepass and repo_keyalias in config.py.")
logging.info("If you want to generate a new repo signing key in the HSM you can do that with 'fdroid update "
"--create-key'.")
elif os.path.exists(keystore):
to_set = ['keystorepass', 'keypass', 'repo_keyalias', 'keydname']
if repo_keyalias:

View File

@ -77,12 +77,13 @@ def read_fingerprints_from_keystore():
are managed by F-Droid, grouped by appid.
"""
env_vars = {'LC_ALL': 'C.UTF-8',
'FDROID_KEY_STORE_PASS': config['keystorepass'],
'FDROID_KEY_PASS': config['keypass']}
p = FDroidPopen([config['keytool'], '-list',
'-v', '-keystore', config['keystore'],
'-storepass:env', 'FDROID_KEY_STORE_PASS'],
envs=env_vars, output=False)
'FDROID_KEY_STORE_PASS': config['keystorepass']}
cmd = [config['keytool'], '-list',
'-v', '-keystore', config['keystore'],
'-storepass:env', 'FDROID_KEY_STORE_PASS']
if config['keystore'] == 'NONE':
cmd += config['smartcardoptions']
p = FDroidPopen(cmd, envs=env_vars, output=False)
if p.returncode != 0:
raise FDroidException('could not read keystore {}'.format(config['keystore']))
@ -115,7 +116,7 @@ def sign_sig_key_fingerprint_list(jar_file):
else: # smardcards never use -keypass
cmd += '-keypass:env', 'FDROID_KEY_PASS'
env_vars = {'FDROID_KEY_STORE_PASS': config['keystorepass'],
'FDROID_KEY_PASS': config['keypass']}
'FDROID_KEY_PASS': config.get('keypass', "")}
p = common.FDroidPopen(cmd, envs=env_vars)
if p.returncode != 0:
raise FDroidException("Failed to sign '{}'!".format(jar_file))
@ -196,7 +197,7 @@ def main():
sys.exit(1)
binaries_dir = os.path.join(unsigned_dir, 'binaries')
if not os.path.exists(config['keystore']):
if not config['keystore'] == "NONE" and not os.path.exists(config['keystore']):
logging.error("Config error - missing '{0}'".format(config['keystore']))
sys.exit(1)
@ -319,7 +320,7 @@ def main():
# characters are significant, so we'll use the first 8 from
# the MD5 of the app's ID and hope there are no collisions.
# If a collision does occur later, we're going to have to
# come up with a new alogrithm, AND rename all existing keys
# come up with a new algorithm, AND rename all existing keys
# in the keystore!
if not skipsigning:
if appid in config['keyaliases']:
@ -340,20 +341,27 @@ def main():
# if not generate one...
env_vars = {'LC_ALL': 'C.UTF-8',
'FDROID_KEY_STORE_PASS': config['keystorepass'],
'FDROID_KEY_PASS': config['keypass']}
p = FDroidPopen([config['keytool'], '-list',
'-alias', keyalias, '-keystore', config['keystore'],
'-storepass:env', 'FDROID_KEY_STORE_PASS'], envs=env_vars)
'FDROID_KEY_PASS': config.get('keypass', "")}
cmd = [config['keytool'], '-list',
'-alias', keyalias, '-keystore', config['keystore'],
'-storepass:env', 'FDROID_KEY_STORE_PASS']
if config['keystore'] == 'NONE':
cmd += config['smartcardoptions']
p = FDroidPopen(cmd, envs=env_vars)
if p.returncode != 0:
logging.info("Key does not exist - generating...")
p = FDroidPopen([config['keytool'], '-genkey',
'-keystore', config['keystore'],
'-alias', keyalias,
'-keyalg', 'RSA', '-keysize', '2048',
'-validity', '10000',
'-storepass:env', 'FDROID_KEY_STORE_PASS',
'-keypass:env', 'FDROID_KEY_PASS',
'-dname', config['keydname']], envs=env_vars)
cmd = [config['keytool'], '-genkey',
'-keystore', config['keystore'],
'-alias', keyalias,
'-keyalg', 'RSA', '-keysize', '2048',
'-validity', '10000',
'-storepass:env', 'FDROID_KEY_STORE_PASS',
'-dname', config['keydname']]
if config['keystore'] == 'NONE':
cmd += config['smartcardoptions']
else:
cmd += '-keypass:env', 'FDROID_KEY_PASS'
p = FDroidPopen(cmd, envs=env_vars)
if p.returncode != 0:
raise BuildException("Failed to generate key", p.output)
if appid not in generated_keys:
@ -367,23 +375,12 @@ def main():
unsigned_dir,
output_dir))
# TODO replace below with common.sign_apk() once it has proven stable
# Sign the application...
p = FDroidPopen([config['jarsigner'], '-keystore', config['keystore'],
'-storepass:env', 'FDROID_KEY_STORE_PASS',
'-keypass:env', 'FDROID_KEY_PASS', '-sigalg',
'SHA1withRSA', '-digestalg', 'SHA1',
apkfile, keyalias], envs=env_vars)
if p.returncode != 0:
raise BuildException(_("Failed to sign application"), p.output)
# Sign and zipalign the application...
common.sign_apk(apkfile, signed_apk_path, keyalias)
if appid not in signed_apks:
signed_apks[appid] = []
signed_apks[appid].append(apkfile)
# Zipalign it...
common._zipalign(apkfile, os.path.join(output_dir, apkfilename))
os.remove(apkfile)
publish_source_tarball(apkfilename, unsigned_dir, output_dir)
logging.info('Published ' + apkfilename)

View File

@ -52,7 +52,7 @@ def sign_jar(jar):
args += ['-keypass:env', 'FDROID_KEY_PASS']
env_vars = {
'FDROID_KEY_STORE_PASS': config['keystorepass'],
'FDROID_KEY_PASS': config['keypass'],
'FDROID_KEY_PASS': config.get('keypass', ""),
}
p = common.FDroidPopen(args, envs=env_vars)
if p.returncode != 0:

View File

@ -2323,7 +2323,7 @@ def main():
if 'keystorepass' not in config:
config['keystorepass'] = password
common.write_to_config(config, 'keystorepass', config['keystorepass'])
if 'keypass' not in config:
if 'keypass' not in config and not config['keystore'] == "NONE":
config['keypass'] = password
common.write_to_config(config, 'keypass', config['keypass'])
common.genkeystore(config)