# Buggy code
def cert_info(app_dir, app_file):
    """Return certificate information."""
    try:
        logger.info("Reading Code Signing Certificate")
        issued = ""
        manidat = ""
        certlist = []
        cert_path = os.path.join(app_dir, "META-INF/")

        apk_file = os.path.join(app_dir, app_file)
        hashfunctions = {
            "md5": hashlib.md5,
            "sha1": hashlib.sha1,
            "sha256": hashlib.sha256,
            "sha512": hashlib.sha512,
        }
        files = [
            f
            for f in os.listdir(cert_path)
            if os.path.isfile(os.path.join(cert_path, f))
        ]
        a = APK(apk_file)
        if a.is_signed():
            certlist.append("APK is signed")
        else:
            certlist.append("Missing certificate")

        certlist.append("v1 signature: {}".format(a.is_signed_v1()))
        certlist.append("v2 signature: {}".format(a.is_signed_v2()))
        certlist.append("v3 signature: {}".format(a.is_signed_v3()))

        certs = set(
            a.get_certificates_der_v3()
            + a.get_certificates_der_v2()
            + [a.get_certificate_der(x) for x in a.get_signature_names()]
        )
        pkeys = set(a.get_public_keys_der_v3() + a.get_public_keys_der_v2())

        if len(certs) > 0:
            certlist.append("Found {} unique certificates".format(len(certs)))

        for cert in certs:
            x509_cert = x509.Certificate.load(cert)
            certlist.append(
                "Subject: {}".format(
                    get_certificate_name_string(x509_cert.subject, short=True)
                )
            )
            certlist.append("Signature Algorithm: {}".format(x509_cert.signature_algo))
            certlist.append(
                "Valid From: {}".format(
                    x509_cert["tbs_certificate"]["validity"]["not_before"].native
                )
            )
            certlist.append(
                "Valid To: {}".format(
                    x509_cert["tbs_certificate"]["validity"]["not_after"].native
                )
            )
            certlist.append(
                "Issuer: {}".format(
                    get_certificate_name_string(x509_cert.issuer, short=True)
                )
            )
            certlist.append("Serial Number: {}".format(hex(x509_cert.serial_number)))
            certlist.append("Hash Algorithm: {}".format(x509_cert.hash_algo))
            for k, v in hashfunctions.items():
                certlist.append("{}: {}".format(k, v(cert).hexdigest()))

        for public_key in pkeys:
            x509_public_key = keys.PublicKeyInfo.load(public_key)
            certlist.append("PublicKey Algorithm: {}".format(x509_public_key.algorithm))
            certlist.append("Bit Size: {}".format(x509_public_key.bit_size))
            certlist.append(
                "Fingerprint: {}".format(
                    binascii.hexlify(x509_public_key.fingerprint).decode("utf-8")
                )
            )
            try:
                certlist.append("Hash Algorithm: {}".format(x509_public_key.hash_algo))
            except ValueError:
                pass
        certlist = "\n".join(certlist)
        if a.is_signed():
            issued = "good"
        else:
            issued = "missing"
        if re.findall(r"CN=Android Debug", certlist):
            issued = "bad"
        if re.findall(r"Hash Algorithm: sha1", certlist):
            issued = "bad hash"
        if "MANIFEST.MF" in files:
            manifestfile = os.path.join(cert_path, "MANIFEST.MF")
        if manifestfile:
            with open(manifestfile, "r", encoding="utf-8") as manifile:
                manidat = manifile.read()
        sha256_digest = bool(re.findall(r"SHA-256-Digest", manidat))
        cert_dic = {
            "cert_info": certlist,
            "issued": issued,
            "sha256Digest": sha256_digest,
        }
        return cert_dic
    except Exception:
        logger.exception("Reading Code Signing Certificate")


# Traceback (TypeError)
[INFO] 03/Oct/2019 02:35:15 - Generating Hashes
[INFO] 03/Oct/2019 02:35:15 - Unzipping
[INFO] 03/Oct/2019 02:35:15 - Getting Hardcoded Certificates/Keystores
[INFO] 03/Oct/2019 02:35:15 - APK Extracted
[INFO] 03/Oct/2019 02:35:15 - Converting AXML to XML
[INFO] 03/Oct/2019 02:35:18 - Reading Android Manifest
[INFO] 03/Oct/2019 02:35:18 - Parsing AndroidManifest.xml
[INFO] 03/Oct/2019 02:35:19 - Fetching icon path
[INFO] 03/Oct/2019 02:35:19 - Extracting Manifest Data
[INFO] 03/Oct/2019 02:35:19 - Fetching Details from Play Store: com.everbridge.mobile.iv.recipient
[WARNING] 03/Oct/2019 02:35:19 - Unable to get app details.
[INFO] 03/Oct/2019 02:35:19 - Manifest Analysis Started
[INFO] 03/Oct/2019 02:35:19 - Static Android Binary Analysis Started
[INFO] 03/Oct/2019 02:35:19 - Static Android Resource Analysis Started
[INFO] 03/Oct/2019 02:35:19 - Reading Code Signing Certificate
[ERROR] 03/Oct/2019 02:35:20 - Reading Code Signing Certificate
Traceback (most recent call last):
File "/home/gclair/Mobile-Security-Framework-MobSF/StaticAnalyzer/views/android/cert_analysis.py", line 111, in cert_info
binascii.hexlify(x509_public_key.fingerprint).decode('utf-8')))
File "/home/gclair/Mobile-Security-Framework-MobSF/venv/lib/python3.6/site-packages/asn1crypto/keys.py", line 1212, in fingerprint
'asn1crypto.keys.PublicKeyInfo().fingerprint has been removed, '
asn1crypto._errors.APIException: asn1crypto.keys.PublicKeyInfo().fingerprint has been removed, please use oscrypto.asymmetric.PublicKey().fingerprint instead
[INFO] 03/Oct/2019 02:35:21 - Trackers Database is outdated!
[INFO] 03/Oct/2019 02:35:21 - Updating Trackers Database....
[INFO] 03/Oct/2019 02:35:21 - Detecting Trackers
[INFO] 03/Oct/2019 02:35:22 - APK -> JAVA
[INFO] 03/Oct/2019 02:35:22 - Decompiling to Java with jadx
[INFO] 03/Oct/2019 02:35:31 - DEX -> SMALI
[INFO] 03/Oct/2019 02:35:31 - Converting classes2.dex to Smali Code
[INFO] 03/Oct/2019 02:35:31 - Converting classes.dex to Smali Code
[INFO] 03/Oct/2019 02:35:31 - Static Android Code Analysis Started
[INFO] 03/Oct/2019 02:35:31 - Code Analysis Started on - java_source
[INFO] 03/Oct/2019 02:35:38 - Finished Code Analysis, Email and URL Extraction
[INFO] 03/Oct/2019 02:35:38 - Extracting Strings from APK
[INFO] 03/Oct/2019 02:35:40 - Detecting Firebase URL(s)
[INFO] 03/Oct/2019 02:35:40 - Performing Malware Check on extracted Domains
[INFO] 03/Oct/2019 02:35:41 - Malware Database is up-to-date
[INFO] 03/Oct/2019 02:35:41 - Generating Java and Smali Downloads
[INFO] 03/Oct/2019 02:35:41 - Generating Downloads
[INFO] 03/Oct/2019 02:35:41 - Zipping
[INFO] 03/Oct/2019 02:35:41 - Zipping
[INFO] 03/Oct/2019 02:35:42 - Connecting to Database
[INFO] 03/Oct/2019 02:35:42 - Saving to Database
[ERROR] 03/Oct/2019 02:35:42 - Saving to DB
Traceback (most recent call last):
File "/home/gclair/Mobile-Security-Framework-MobSF/StaticAnalyzer/views/android/db_interaction.py", line 255, in create_db_entry
CERT_INFO=cert_dic['cert_info'],
TypeError: 'NoneType' object is not subscriptable
[ERROR] 03/Oct/2019 02:35:42 - Rendering to Template
Traceback (most recent call last):
File "/home/gclair/Mobile-Security-Framework-MobSF/StaticAnalyzer/views/android/db_interaction.py", line 120, in get_context_from_analysis
'certinfo': cert_dic['cert_info'],
TypeError: 'NoneType' object is not subscriptable
[ERROR] 03/Oct/2019 02:35:42 - Error Performing Static Analysis
Traceback (most recent call last):
File "/home/gclair/Mobile-Security-Framework-MobSF/StaticAnalyzer/views/android/static_analyzer.py", line 271, in static_analyzer
'security_score'] = score(context['findings'])
TypeError: 'NoneType' object is not subscriptable
[ERROR] 03/Oct/2019 02:35:42 - 'NoneType' object is not subscriptable
[ERROR] 03/Oct/2019 02:35:42 - Internal Server Error: /StaticAnalyzer/

# Fixed code
def cert_info(app_dir, app_file):
    """Return certificate information."""
    try:
        logger.info("Reading Code Signing Certificate")
        issued = ""
        manidat = ""
        certlist = []
        cert_path = os.path.join(app_dir, "META-INF/")

        apk_file = os.path.join(app_dir, app_file)
        hashfunctions = {
            "md5": hashlib.md5,
            "sha1": hashlib.sha1,
            "sha256": hashlib.sha256,
            "sha512": hashlib.sha512,
        }
        files = [
            f
            for f in os.listdir(cert_path)
            if os.path.isfile(os.path.join(cert_path, f))
        ]
        a = APK(apk_file)
        if a.is_signed():
            certlist.append("APK is signed")
        else:
            certlist.append("Missing certificate")
        certlist.append("v1 signature: {}".format(a.is_signed_v1()))
        certlist.append("v2 signature: {}".format(a.is_signed_v2()))
        certlist.append("v3 signature: {}".format(a.is_signed_v3()))

        certs = set(
            a.get_certificates_der_v3()
            + a.get_certificates_der_v2()
            + [a.get_certificate_der(x) for x in a.get_signature_names()]
        )
        pkeys = set(a.get_public_keys_der_v3() + a.get_public_keys_der_v2())

        if len(certs) > 0:
            certlist.append("Found {} unique certificates".format(len(certs)))

        for cert in certs:
            x509_cert = x509.Certificate.load(cert)
            certlist.append(
                "Subject: {}".format(
                    get_certificate_name_string(x509_cert.subject, short=True)
                )
            )
            certlist.append("Signature Algorithm: {}".format(x509_cert.signature_algo))
            certlist.append(
                "Valid From: {}".format(
                    x509_cert["tbs_certificate"]["validity"]["not_before"].native
                )
            )
            certlist.append(
                "Valid To: {}".format(
                    x509_cert["tbs_certificate"]["validity"]["not_after"].native
                )
            )
            certlist.append(
                "Issuer: {}".format(
                    get_certificate_name_string(x509_cert.issuer, short=True)
                )
            )
            certlist.append("Serial Number: {}".format(hex(x509_cert.serial_number)))
            certlist.append("Hash Algorithm: {}".format(x509_cert.hash_algo))
            for k, v in hashfunctions.items():
                certlist.append("{}: {}".format(k, v(cert).hexdigest()))

        for public_key in pkeys:
            x509_public_key = asymmetric.load_public_key(public_key)
            certlist.append("PublicKey Algorithm: {}".format(x509_public_key.algorithm))
            certlist.append("Bit Size: {}".format(x509_public_key.bit_size))
            certlist.append(
                "Fingerprint: {}".format(
                    binascii.hexlify(x509_public_key.fingerprint).decode("utf-8")
                )
            )
        certlist = "\n".join(certlist)
        if a.is_signed():
            issued = "good"
        else:
            issued = "missing"
        if re.findall(r"CN=Android Debug", certlist):
            issued = "bad"
        if re.findall(r"Hash Algorithm: sha1", certlist):
            issued = "bad hash"
        if "MANIFEST.MF" in files:
            manifestfile = os.path.join(cert_path, "MANIFEST.MF")
        if manifestfile:
            with open(manifestfile, "r", encoding="utf-8") as manifile:
                manidat = manifile.read()
        sha256_digest = bool(re.findall(r"SHA-256-Digest", manidat))
        cert_dic = {
            "cert_info": certlist,
            "issued": issued,
            "sha256Digest": sha256_digest,
        }
        return cert_dic
    except Exception:
        logger.exception("Reading Code Signing Certificate")