chiark / gitweb /
Reduce code duplication
authorTorsten Grote <t@grobox.de>
Mon, 3 Apr 2017 12:23:06 +0000 (09:23 -0300)
committerTorsten Grote <t@grobox.de>
Mon, 3 Apr 2017 12:23:06 +0000 (09:23 -0300)
by re-using methods for extracting and verifying certificate

fdroidserver/common.py
fdroidserver/index.py
fdroidserver/update.py

index 85bd48e1466b7cc1bc4134bd1eba0a8006ef747b..42918ed7f3a00d21ee4c40a724e7d44c6a2f4a2d 100644 (file)
@@ -42,6 +42,10 @@ from distutils.version import LooseVersion
 from queue import Queue
 from zipfile import ZipFile
 
+from pyasn1.codec.der import decoder, encoder
+from pyasn1_modules import rfc2315
+from pyasn1.error import PyAsn1Error
+
 import fdroidserver.metadata
 from .asynchronousfilereader import AsynchronousFileReader
 
@@ -2221,6 +2225,26 @@ def get_cert_fingerprint(pubkey):
     return " ".join(ret)
 
 
+def get_certificate(certificate_file):
+    """
+    Extracts a certificate from the given file.
+    :param certificate_file: file bytes (as string) representing the certificate
+    :return: A binary representation of the certificate's public key, or None in case of error
+    """
+    content = decoder.decode(certificate_file, asn1Spec=rfc2315.ContentInfo())[0]
+    if content.getComponentByName('contentType') != rfc2315.signedData:
+        return None
+    content = decoder.decode(content.getComponentByName('content'),
+                             asn1Spec=rfc2315.SignedData())[0]
+    try:
+        certificates = content.getComponentByName('certificates')
+        cert = certificates[0].getComponentByName('certificate')
+    except PyAsn1Error:
+        logging.error("Certificates not found.")
+        return None
+    return encoder.encode(cert)
+
+
 def write_to_config(thisconfig, key, value=None, config_file=None):
     '''write a key/value to the local config.py
 
index 4cf9d4b783e8e176bd333b02c29c068fe2bff417..1421acb84eccf21d7c956cd1361aa7932409cdfc 100644 (file)
@@ -36,8 +36,6 @@ from datetime import datetime
 from xml.dom.minidom import Document
 
 import requests
-from pyasn1.codec.der import decoder, encoder
-from pyasn1_modules import rfc2315
 
 from fdroidserver import metadata, signindex, common
 from fdroidserver.common import FDroidPopen, FDroidPopenBytes
@@ -621,23 +619,7 @@ def get_public_key_from_jar(jar):
         raise VerificationException("Found multiple signing certificates for repository.")
 
     # extract public key from certificate
-    public_key = get_public_key_from_certificate(jar.read(certs[0]))
+    public_key = common.get_certificate(jar.read(certs[0]))
     public_key_fingerprint = common.get_cert_fingerprint(public_key).replace(' ', '')
 
     return public_key, public_key_fingerprint
-
-
-def get_public_key_from_certificate(certificate_file):
-    """
-    Extracts a public key from the given certificate.
-    :param certificate_file: file bytes (as string) representing the certificate
-    :return: A binary representation of the certificate's public key
-    """
-    content = decoder.decode(certificate_file, asn1Spec=rfc2315.ContentInfo())[0]
-    if content.getComponentByName('contentType') != rfc2315.signedData:
-        raise VerificationException("Unexpected certificate format.")
-    content = decoder.decode(content.getComponentByName('content'),
-                             asn1Spec=rfc2315.SignedData())[0]
-    certificates = content.getComponentByName('certificates')
-    cert = certificates[0].getComponentByName('certificate')
-    return encoder.encode(cert)
index 94f181ddaf5e056a12c1f108cb4582fe3e8f8c22..92075d8c2a48de82bea0093eb74a0d68b0672e08 100644 (file)
@@ -34,9 +34,6 @@ from datetime import datetime, timedelta
 from argparse import ArgumentParser
 
 import collections
-from pyasn1.error import PyAsn1Error
-from pyasn1.codec.der import decoder, encoder
-from pyasn1_modules import rfc2315
 from binascii import hexlify
 
 from PIL import Image
@@ -45,7 +42,7 @@ import logging
 from . import common
 from . import index
 from . import metadata
-from .common import FDroidPopen, SdkToolsPopen
+from .common import SdkToolsPopen
 
 METADATA_VERSION = 18
 
@@ -389,17 +386,11 @@ def getsig(apkpath):
               if an error occurred.
     """
 
-    cert = None
-
     # verify the jar signature is correct
-    args = [config['jarsigner'], '-verify', apkpath]
-    p = FDroidPopen(args)
-    if p.returncode != 0:
-        logging.critical(apkpath + " has a bad signature!")
+    if not common.verify_apk_signature(apkpath):
         return None
 
     with zipfile.ZipFile(apkpath, 'r') as apk:
-
         certs = [n for n in apk.namelist() if common.CERT_PATH_REGEX.match(n)]
 
         if len(certs) < 1:
@@ -411,20 +402,7 @@ def getsig(apkpath):
 
         cert = apk.read(certs[0])
 
-    content = decoder.decode(cert, asn1Spec=rfc2315.ContentInfo())[0]
-    if content.getComponentByName('contentType') != rfc2315.signedData:
-        logging.error("Unexpected format.")
-        return None
-
-    content = decoder.decode(content.getComponentByName('content'),
-                             asn1Spec=rfc2315.SignedData())[0]
-    try:
-        certificates = content.getComponentByName('certificates')
-    except PyAsn1Error:
-        logging.error("Certificates not found.")
-        return None
-
-    cert_encoded = encoder.encode(certificates)[4:]
+    cert_encoded = common.get_certificate(cert)
 
     return hashlib.md5(hexlify(cert_encoded)).hexdigest()