mirror of
https://github.com/f-droid/fdroidserver.git
synced 2025-11-05 06:50:29 +03:00
jarsigner: allow weak signatures
openjdk-11 11.0.17 in Debian unstable fails to verify weak signatures:
jarsigner -verbose -strict -verify tests/signindex/guardianproject.jar
131 Fri Dec 02 20:10:00 CET 2016 META-INF/MANIFEST.MF
252 Fri Dec 02 20:10:04 CET 2016 META-INF/1.SF
2299 Fri Dec 02 20:10:04 CET 2016 META-INF/1.RSA
0 Fri Dec 02 20:09:58 CET 2016 META-INF/
m ? 48743 Fri Dec 02 20:09:58 CET 2016 index.xml
s = signature was verified
m = entry is listed in manifest
k = at least one certificate was found in keystore
? = unsigned entry
- Signed by "EMAILADDRESS=root@guardianproject.info, CN=guardianproject.info, O=Guardian Project, OU=FDroid Repo, L=New York, ST=New York, C=US"
Digest algorithm: SHA1 (disabled)
Signature algorithm: SHA1withRSA (disabled), 4096-bit key
WARNING: The jar will be treated as unsigned, because it is signed with a weak algorithm that is now disabled by the security property:
jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, DSA keySize < 1024, SHA1 denyAfter 2019-01-01, include jdk.disabled.namedCurves
This commit is contained in:
parent
d4b6e95c4e
commit
1bb963d768
5 changed files with 64 additions and 84 deletions
|
|
@ -3416,13 +3416,27 @@ def verify_apks(signed_apk, unsigned_apk, tmp_dir, v1_only=None):
|
|||
return None
|
||||
|
||||
|
||||
def verify_jar_signature(jar):
|
||||
def verify_deprecated_jar_signature(jar):
|
||||
"""Verify the signature of a given JAR file.
|
||||
|
||||
jarsigner is very shitty: unsigned JARs pass as "verified"! So
|
||||
this has to turn on -strict then check for result 4, since this
|
||||
does not expect the signature to be from a CA-signed certificate.
|
||||
|
||||
Also used to verify the signature on an archived APK, supporting deprecated
|
||||
algorithms.
|
||||
|
||||
F-Droid aims to keep every single binary that it ever published. Therefore,
|
||||
it needs to be able to verify APK signatures that include deprecated/removed
|
||||
algorithms. For example, jarsigner treats an MD5 signature as unsigned.
|
||||
|
||||
jarsigner passes unsigned APKs as "verified"! So this has to turn
|
||||
on -strict then check for result 4.
|
||||
|
||||
Just to be safe, this never reuses the file, and locks down the
|
||||
file permissions while in use. That should prevent a bad actor
|
||||
from changing the settings during operation.
|
||||
|
||||
Raises
|
||||
------
|
||||
VerificationException
|
||||
|
|
@ -3430,15 +3444,30 @@ def verify_jar_signature(jar):
|
|||
|
||||
"""
|
||||
error = _('JAR signature failed to verify: {path}').format(path=jar)
|
||||
_java_security = os.path.join(os.getcwd(), '.java.security')
|
||||
if os.path.exists(_java_security):
|
||||
os.remove(_java_security)
|
||||
with open(_java_security, 'w') as fp:
|
||||
fp.write('jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024')
|
||||
os.chmod(_java_security, 0o400)
|
||||
|
||||
try:
|
||||
output = subprocess.check_output([config['jarsigner'], '-strict', '-verify', jar],
|
||||
stderr=subprocess.STDOUT)
|
||||
cmd = [
|
||||
config['jarsigner'],
|
||||
'-J-Djava.security.properties=' + _java_security,
|
||||
'-strict', '-verify', jar
|
||||
]
|
||||
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
||||
raise VerificationException(error + '\n' + output.decode('utf-8'))
|
||||
except subprocess.CalledProcessError as e:
|
||||
if e.returncode == 4:
|
||||
logging.debug(_('JAR signature verified: {path}').format(path=jar))
|
||||
else:
|
||||
raise VerificationException(error + '\n' + e.output.decode('utf-8')) from e
|
||||
finally:
|
||||
if os.path.exists(_java_security):
|
||||
os.chmod(_java_security, 0o600)
|
||||
os.remove(_java_security)
|
||||
|
||||
|
||||
def verify_apk_signature(apk, min_sdk_version=None):
|
||||
|
|
@ -3471,63 +3500,13 @@ def verify_apk_signature(apk, min_sdk_version=None):
|
|||
config['jarsigner_warning_displayed'] = True
|
||||
logging.warning(_("Using Java's jarsigner, not recommended for verifying APKs! Use apksigner"))
|
||||
try:
|
||||
verify_jar_signature(apk)
|
||||
verify_deprecated_jar_signature(apk)
|
||||
return True
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
return False
|
||||
|
||||
|
||||
def verify_old_apk_signature(apk):
|
||||
"""Verify the signature on an archived APK, supporting deprecated algorithms.
|
||||
|
||||
F-Droid aims to keep every single binary that it ever published. Therefore,
|
||||
it needs to be able to verify APK signatures that include deprecated/removed
|
||||
algorithms. For example, jarsigner treats an MD5 signature as unsigned.
|
||||
|
||||
jarsigner passes unsigned APKs as "verified"! So this has to turn
|
||||
on -strict then check for result 4.
|
||||
|
||||
Just to be safe, this never reuses the file, and locks down the
|
||||
file permissions while in use. That should prevent a bad actor
|
||||
from changing the settings during operation.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Boolean
|
||||
whether the APK was verified
|
||||
|
||||
"""
|
||||
_java_security = os.path.join(os.getcwd(), '.java.security')
|
||||
if os.path.exists(_java_security):
|
||||
os.remove(_java_security)
|
||||
with open(_java_security, 'w') as fp:
|
||||
fp.write('jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024')
|
||||
os.chmod(_java_security, 0o400)
|
||||
|
||||
try:
|
||||
cmd = [
|
||||
config['jarsigner'],
|
||||
'-J-Djava.security.properties=' + _java_security,
|
||||
'-strict', '-verify', apk
|
||||
]
|
||||
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
if e.returncode != 4:
|
||||
output = e.output
|
||||
else:
|
||||
logging.debug(_('JAR signature verified: {path}').format(path=apk))
|
||||
return True
|
||||
finally:
|
||||
if os.path.exists(_java_security):
|
||||
os.chmod(_java_security, 0o600)
|
||||
os.remove(_java_security)
|
||||
|
||||
logging.error(_('Old APK signature failed to verify: {path}').format(path=apk)
|
||||
+ '\n' + output.decode('utf-8'))
|
||||
return False
|
||||
|
||||
|
||||
apk_badchars = re.compile('''[/ :;'"]''')
|
||||
|
||||
|
||||
|
|
@ -3749,7 +3728,7 @@ def load_stats_fdroid_signing_key_fingerprints():
|
|||
if not os.path.isfile(jar_file):
|
||||
return {}
|
||||
try:
|
||||
verify_jar_signature(jar_file)
|
||||
verify_deprecated_jar_signature(jar_file)
|
||||
except VerificationException as e:
|
||||
raise FDroidException("Signature validation of '{}' failed! "
|
||||
"Please run publish again to rebuild this file.".format(jar_file)) from e
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue