def testPartialSignature(self): from androguard.core.bytecodes.apk import APK a = APK("examples/tests/partialsignature.apk", skip_analysis=True) self.assertIn("META-INF/CERT.RSA", a.get_files()) self.assertIn("META-INF/6AD89F48.RSA", a.get_files()) self.assertNotIn("META-INF/CERT.RSA", a.get_signature_names()) self.assertIn("META-INF/6AD89F48.RSA", a.get_signature_names())
def testAPKCertFingerprint(self): """ Test if certificates are correctly unpacked from the SignatureBlock files Check if fingerprints matches :return: """ from androguard.core.bytecodes.apk import APK import binascii from hashlib import md5, sha1, sha256 a = APK("examples/android/TestsAndroguard/bin/TestActivity.apk", skip_analysis=True) # this one is not signed v2, it is v1 only self.assertTrue(a.is_signed_v1()) self.assertFalse(a.is_signed_v2()) self.assertTrue(a.is_signed()) self.assertEqual(a.get_certificates_der_v2(), []) self.assertEqual(a.get_certificates_v2(), []) self.assertEqual(a.get_signature_name(), "META-INF/CERT.RSA") self.assertEqual(a.get_signature_names(), ["META-INF/CERT.RSA"]) cert = a.get_certificate(a.get_signature_name()) cert_der = a.get_certificate_der(a.get_signature_name()) # Keytool are the hashes collected by keytool -printcert -file CERT.RSA for h2, keytool in [(md5, "99:FF:FC:37:D3:64:87:DD:BA:AB:F1:7F:94:59:89:B5"), (sha1, "1E:0B:E4:01:F9:34:60:E0:8D:89:A3:EF:6E:27:25:55:6B:E1:D1:6B"), (sha256, "6F:5C:31:60:8F:1F:9E:28:5E:B6:34:3C:7C:8A:F0:7D:E8:1C:1F:B2:14:8B:53:49:BE:C9:06:44:41:44:57:6D")]: x = h2() x.update(cert_der) hash_hashlib = x.hexdigest() self.assertEqual(hash_hashlib.lower(), keytool.replace(":", "").lower())
def androsign_main(args_apk, args_hash, args_all, show): from androguard.core.bytecodes.apk import APK from androguard.util import get_certificate_name_string import hashlib import traceback from colorama import Fore, Style from asn1crypto import x509 # Keep the list of hash functions in sync with cli/entry_points.py:sign hashfunctions = dict(md5=hashlib.md5, sha1=hashlib.sha1, sha256=hashlib.sha256, sha512=hashlib.sha512, ) if args_hash.lower() not in hashfunctions: print("Hash function {} not supported!" .format(args_hash.lower()), file=sys.stderr) print("Use one of {}" .format(", ".join(hashfunctions.keys())), file=sys.stderr) sys.exit(1) for path in args_apk: try: a = APK(path) print("{}, package: '{}'".format(os.path.basename(path), a.get_package())) print("Is signed v1: {}".format(a.is_signed_v1())) print("Is signed v2: {}".format(a.is_signed_v2())) certs = set(a.get_certificates_der_v2() + [a.get_certificate_der(x) for x in a.get_signature_names()]) if len(certs) > 0: print("Found {} unique certificates".format(len(certs))) for cert in certs: if show: x509_cert = x509.Certificate.load(cert) print("Issuer:", get_certificate_name_string(x509_cert.issuer, short=True)) print("Subject:", get_certificate_name_string(x509_cert.subject, short=True)) print("Serial Number:", hex(x509_cert.serial_number)) print("Hash Algorithm:", x509_cert.hash_algo) print("Signature Algorithm:", x509_cert.signature_algo) print("Valid not before:", x509_cert['tbs_certificate']['validity']['not_before'].native) print("Valid not after:", x509_cert['tbs_certificate']['validity']['not_after'].native) if not args_all: print("{} {}".format(args_hash.lower(), hashfunctions[args_hash.lower()](cert).hexdigest())) else: for k, v in hashfunctions.items(): print("{} {}".format(k, v(cert).hexdigest())) print() except: print(Fore.RED + "Error in {}".format(os.path.basename(path)) + Style.RESET_ALL, file=sys.stderr) traceback.print_exc(file=sys.stderr) if len(args_apk) > 1: print()
def androsign_main(args_apk, args_hash, args_all, show): from androguard.core.apk import APK from androguard.util import get_certificate_name_string import hashlib import binascii import traceback from colorama import Fore, Style from asn1crypto import x509, keys # Keep the list of hash functions in sync with cli/entry_points.py:sign hashfunctions = dict(md5=hashlib.md5, sha1=hashlib.sha1, sha256=hashlib.sha256, sha512=hashlib.sha512, ) if args_hash.lower() not in hashfunctions: print("Hash function {} not supported!" .format(args_hash.lower()), file=sys.stderr) print("Use one of {}" .format(", ".join(hashfunctions.keys())), file=sys.stderr) sys.exit(1) for path in args_apk: try: a = APK(path) print("{}, package: '{}'".format(os.path.basename(path), a.get_package())) print("Is signed v1: {}".format(a.is_signed_v1())) print("Is signed v2: {}".format(a.is_signed_v2())) print("Is signed v3: {}".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: print("Found {} unique certificates".format(len(certs))) for cert in certs: if show: x509_cert = x509.Certificate.load(cert) print("Issuer:", get_certificate_name_string(x509_cert.issuer, short=True)) print("Subject:", get_certificate_name_string(x509_cert.subject, short=True)) print("Serial Number:", hex(x509_cert.serial_number)) print("Hash Algorithm:", x509_cert.hash_algo) print("Signature Algorithm:", x509_cert.signature_algo) print("Valid not before:", x509_cert['tbs_certificate']['validity']['not_before'].native) print("Valid not after:", x509_cert['tbs_certificate']['validity']['not_after'].native) if not args_all: print("{} {}".format(args_hash.lower(), hashfunctions[args_hash.lower()](cert).hexdigest())) else: for k, v in hashfunctions.items(): print("{} {}".format(k, v(cert).hexdigest())) print() if len(certs) > 0: print("Found {} unique public keys associated with the certs".format(len(pkeys))) for public_key in pkeys: if show: x509_public_key = keys.PublicKeyInfo.load(public_key) print("PublicKey Algorithm:", x509_public_key.algorithm) print("Bit Size:", x509_public_key.bit_size) print("Fingerprint:", binascii.hexlify(x509_public_key.fingerprint)) try: print("Hash Algorithm:", x509_public_key.hash_algo) except ValueError as ve: # RSA pkey does not have an hash algorithm pass print() except: print(Fore.RED + "Error in {}".format(os.path.basename(path)) + Style.RESET_ALL, file=sys.stderr) traceback.print_exc(file=sys.stderr) if len(args_apk) > 1: print()
def testApksignAPKs(self): # These APKs are from the apksign testcases and cover # all different signature algorithms as well as some error cases from androguard.core.bytecodes.apk import APK import zipfile from asn1crypto import x509, pem import binascii root = "examples/signing/apksig" # Correct values generated with openssl: # In the apksig repo:src/test/resources/com/android/apksig # for f in *.pem; do openssl x509 -in $f -noout -sha256 -fingerprint; done certfp = { 'dsa-1024.x509.pem': 'fee7c19ff9bfb4197b3727b9fd92d95406b1bd96db99ea642f5faac019a389d7', 'dsa-2048.x509.pem': '97cce0bab292c2d5afb9de90e1810b41a5d25c006a10d10982896aa12ab35a9e', 'dsa-3072.x509.pem': '966a4537058d24098ea213f12d4b24e37ff5a1d8f68deb8a753374881f23e474', 'ec-p256.x509.pem': '6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599', 'ec-p384.x509.pem': '5e7777ada7ee7ce8f9c4d1b07094876e5604617b7988b4c5d5b764a23431afbe', 'ec-p521.x509.pem': '69b50381d98bebcd27df6d7df8af8c8b38d0e51e9168a95ab992d1a9da6082da', 'rsa-1024_2.x509.pem': 'eba3685e799f59804684abebf0363e14ccb1c213e2b954a22669714ed97f61e9', 'rsa-1024.x509.pem': 'bc5e64eab1c4b5137c0fbc5ed05850b3a148d1c41775cffa4d96eea90bdd0eb8', 'rsa-16384.x509.pem': 'f3c6b37909f6df310652fbd7c55ec27d3079dcf695dc6e75e22ba7c4e1c95601', 'rsa-2048_2.x509.pem': '681b0e56a796350c08647352a4db800cc44b2adc8f4c72fa350bd05d4d50264d', 'rsa-2048_3.x509.pem': 'bb77a72efc60e66501ab75953af735874f82cfe52a70d035186a01b3482180f3', 'rsa-2048.x509.pem': 'fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8', 'rsa-3072.x509.pem': '483934461229a780010bc07cd6eeb0b67025fc4fe255757abbf5c3f2ed249e89', 'rsa-4096.x509.pem': '6a46158f87753395a807edcc7640ac99c9125f6b6e025bdbf461ff281e64e685', 'rsa-8192.x509.pem': '060d0a24fea9b60d857225873f78838e081795f7ef2d1ea401262bbd75a58234', } will_not_validate_correctly = [ "targetSandboxVersion-2.apk", "targetSandboxVersion-2.apk", "v1-only-with-cr-in-entry-name.apk", "v1-only-with-lf-in-entry-name.apk", "v1-only-with-nul-in-entry-name.apk", "v1-only-with-rsa-1024-cert-not-der2.apk", "v2-only-cert-and-public-key-mismatch.apk", "v2-only-with-dsa-sha256-1024-sig-does-not-verify.apk", "debuggable-boolean.apk", "debuggable-resource.apk", ] # Collect possible hashes for certificates # Unfortunately, not all certificates are supplied... for apath in os.listdir(root): if apath in certfp: with open(os.path.join(root, apath), "rb") as fp: cert = x509.Certificate.load(pem.unarmor(fp.read())[2]) h = cert.sha256_fingerprint.replace(" ", "").lower() self.assertEqual(h, certfp[apath]) self.assertIn(h, certfp.values()) for apath in os.listdir(root): if apath.endswith(".apk"): if apath == "v2-only-garbage-between-cd-and-eocd.apk" or \ apath == "v2-only-truncated-cd.apk" or \ apath == "v1v2v3-with-rsa-2048-lineage-3-signers-invalid-zip.apk": # Can not load as APK with self.assertRaises(zipfile.BadZipFile): APK(os.path.join(root, apath)) continue elif apath in will_not_validate_correctly: # These APKs are faulty (by design) and will return a not correct fingerprint. # TODO: we need to check if we can prevent such errors... continue a = APK(os.path.join(root, apath)) self.assertIsInstance(a, APK) # Test if the correct method returns True, while others return # False m_tests = { '1': a.is_signed_v1, '2': a.is_signed_v2, '3': a.is_signed_v3 } # These APKs will raise an error excluded = [ "v1v2v3-with-rsa-2048-lineage-3-signers-no-sig-block.apk", "v2-only-apk-sig-block-size-mismatch.apk", "v2-only-empty.apk", "v2-only-wrong-apk-sig-block-magic.apk", "v2-stripped.apk", "v2-stripped-with-ignorable-signing-schemes.apk", "v2v3-signed-v3-block-stripped.apk", "v3-only-empty.apk", "v3-only-with-ecdsa-sha512-p384-wrong-apk-sig-block-magic.apk", "v3-only-with-rsa-pkcs1-sha512-4096-apk-sig-block-size-mismatch.apk", "v3-stripped.apk", ] if apath[0] == "v" and apath not in excluded: methods = apath.split("-", 1)[0].split("v")[1:] for m, f in m_tests.items(): if m in methods: self.assertTrue(f()) else: self.assertFalse(f()) # Special error cases if apath == "v2-only-apk-sig-block-size-mismatch.apk": with self.assertRaises(apk.BrokenAPKError): a.is_signed_v2() continue elif apath == "v2-only-empty.apk": with self.assertRaises(apk.BrokenAPKError): a.is_signed_v2() continue elif apath == "v3-only-with-rsa-pkcs1-sha512-4096-apk-sig-block-size-mismatch.apk": with self.assertRaises(apk.BrokenAPKError): a.is_signed_v3() continue if a.is_signed_v1(): if apath == "weird-compression-method.apk": with self.assertRaises(NotImplementedError): for c in a.get_signature_names(): a.get_certificate(c) elif apath == "v1-only-with-rsa-1024-cert-not-der.apk": for sig in a.get_signature_names(): c = a.get_certificate(sig) h = c.sha256_fingerprint.replace(" ", "").lower() self.assertNotIn(h, certfp.values()) # print([apath, h]) # I do not know, why put this file? der = a.get_certificate_der(sig) apk.show_Certificate(c, True) apk.show_Certificate(c, False) self.assertEqual( hashlib.sha256(der).hexdigest(), h) pass else: for sig in a.get_signature_names(): c = a.get_certificate(sig) h = c.sha256_fingerprint.replace(" ", "").lower() self.assertIn(h, certfp.values()) # Check that we get the same signature if we take the DER der = a.get_certificate_der(sig) self.assertEqual( hashlib.sha256(der).hexdigest(), h) if a.is_signed_v2(): if apath == "weird-compression-method.apk": with self.assertRaises(NotImplementedError): a.get_certificates_der_v2() elif apath == "v2-only-with-rsa-pkcs1-sha256-1024-cert-not-der.apk": # FIXME # Not sure what this one should do... but the certificate fingerprint is weird # as the hash over the DER is not the same when using the certificate continue else: for c in a.get_certificates_der_v2(): cert = x509.Certificate.load(c) h = cert.sha256_fingerprint.replace(" ", "").lower() self.assertIn(h, certfp.values()) # Check that we get the same signature if we take the DER self.assertEqual(hashlib.sha256(c).hexdigest(), h) if a.is_signed_v3(): print(apath) if apath == "weird-compression-method.apk": with self.assertRaises(NotImplementedError): a.get_certificates_der_v3() elif apath == "v3-only-with-rsa-pkcs1-sha256-3072-sig-does-not-verify.apk" or \ apath == "v3-only-cert-and-public-key-mismatch.apk": cert = x509.Certificate.load( a.get_certificates_der_v3()[0]) h = cert.sha256_fingerprint.replace(" ", "").lower() self.assertNotIn(h, certfp.values()) else: for c in a.get_certificates_der_v3(): cert = x509.Certificate.load(c) h = cert.sha256_fingerprint.replace(" ", "").lower() self.assertIn(h, certfp.values()) # Check that we get the same signature if we take the DER self.assertEqual(hashlib.sha256(c).hexdigest(), h)
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')
def main(): parser = get_parser() args = parser.parse_args() hashfunctions = dict(md5=hashlib.md5, sha1=hashlib.sha1, sha256=hashlib.sha256, sha512=hashlib.sha512, ) if args.hash.lower() not in hashfunctions: print("Hash function {} not supported!".format(args.hash.lower()), file=sys.stderr) print("Use one of {}".format(", ".join(hashfunctions.keys())), file=sys.stderr) sys.exit(1) for path in args.apk: try: a = APK(path) print("{}, package: '{}'".format(os.path.basename(path), a.get_package())) print("Is signed v1: {}".format(a.is_signed_v1())) print("Is signed v2: {}".format(a.is_signed_v2())) certs = set(a.get_certificates_der_v2() + [a.get_certificate_der(x) for x in a.get_signature_names()]) if len(certs) > 0: print("Found {} unique certificates".format(len(certs))) for cert in certs: if not args.all: print("{} {}".format(args.hash.lower(), hashfunctions[args.hash.lower()](cert).hexdigest())) else: for k, v in hashfunctions.items(): print("{} {}".format(k, v(cert).hexdigest())) except: print(Fore.RED + "Error in {}".format(os.path.basename(path)) + Style.RESET_ALL, file=sys.stderr) traceback.print_exc(file=sys.stderr) if len(args.apk) > 1: print()
def cert_info(app_dir, app_file): """Return certificate information.""" try: logger.info('Reading Code Signing Certificate') manifestfile = None status = '' manidat = '' cert_info = '' 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'))) cert_info = '\n'.join(certlist) 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)) if a.is_signed(): status = 'good' desc = 'Certificate looks good.' else: status = 'missing' desc = 'Certificate is not found' if re.findall(r'CN=Android Debug', cert_info): status = 'bad' desc = ('This is a debug certificate. Production application' ' must not be shipped with a debug certificate.') if re.findall(r'Hash Algorithm: sha1', cert_info): status = 'bad' desc = ('The app is signed with SHA1withRSA. SHA1 hash algorithm' ' is known to have collision issues.') if sha256_digest: status = 'warning' desc += ('The manifest indicates SHA256withRSA is in use. ' 'Please verify this manually.') cert_dic = { 'certificate_info': cert_info, 'certificate_status': status, 'description': desc, } return cert_dic except Exception: logger.exception('Reading Code Signing Certificate')
def main(): parser = get_parser() args = parser.parse_args() hashfunctions = dict( md5=hashlib.md5, sha1=hashlib.sha1, sha256=hashlib.sha256, sha512=hashlib.sha512, ) if args.hash.lower() not in hashfunctions: print("Hash function {} not supported!".format(args.hash.lower()), file=sys.stderr) print("Use one of {}".format(", ".join(hashfunctions.keys())), file=sys.stderr) sys.exit(1) for path in args.apk: try: a = APK(path) print("{}, package: '{}'".format(os.path.basename(path), a.get_package())) print("Is signed v1: {}".format(a.is_signed_v1())) print("Is signed v2: {}".format(a.is_signed_v2())) certs = set( a.get_certificates_der_v2() + [a.get_certificate_der(x) for x in a.get_signature_names()]) if len(certs) > 0: print("Found {} unique certificates".format(len(certs))) for cert in certs: if args.show: x509_cert = x509.Certificate.load(cert) print("Issuer:", x509_cert.issuer.human_friendly) print("Subject:", x509_cert.subject.human_friendly) print("Serial Number:", hex(x509_cert.serial_number)) print("Hash Algorithm:", x509_cert.hash_algo) print("Signature Algorithm:", x509_cert.signature_algo) print( "Valid not before:", x509_cert['tbs_certificate'] ['validity']['not_before'].native) print( "Valid not after:", x509_cert['tbs_certificate'] ['validity']['not_after'].native) if not args.all: print("{} {}".format( args.hash.lower(), hashfunctions[args.hash.lower()](cert).hexdigest())) else: for k, v in hashfunctions.items(): print("{} {}".format(k, v(cert).hexdigest())) print() except: print(Fore.RED + "Error in {}".format(os.path.basename(path)) + Style.RESET_ALL, file=sys.stderr) traceback.print_exc(file=sys.stderr) if len(args.apk) > 1: print()
def analyze(path): try: start = process_time() hashfunctions = dict(md5=hashlib.md5, sha1=hashlib.sha1, sha256=hashlib.sha256, sha512=hashlib.sha512) a = APK(path) certs = set( a.get_certificates_der_v3() + a.get_certificates_der_v2() + [a.get_certificate_der(x) for x in a.get_signature_names()]) for cert in certs: x509_cert = x509.Certificate.load(cert) issuer = { 'commonName': None, 'organizationName': None, 'organizationalUnitName': None, 'countryName': None, 'stateOrProvinceName': None, 'localityName': None } subject = { 'commonName': None, 'organizationName': None, 'organizationalUnitName': None, 'countryName': None, 'stateOrProvinceName': None, 'localityName': None } strIssuer = get_certificate_name_string(x509_cert.issuer, short=False) strSubject = get_certificate_name_string(x509_cert.subject, short=False) arrIssuer = strIssuer.split(',') for i in arrIssuer: if i.lstrip().split('=')[0] == 'commonName': issuer['commonName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'organizationName': issuer['organizationName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'organizationalUnitName': issuer['organizationalUnitName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'countryName': issuer['countryName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'stateOrProvinceName': issuer['stateOrProvinceName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'localityName': issuer['localityName'] = i.lstrip().split('=')[1] arrSubject = strSubject.split(',') for i in arrSubject: if i.lstrip().split('=')[0] == 'commonName': subject['commonName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'organizationName': subject['organizationName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'organizationalUnitName': subject['organizationalUnitName'] = i.lstrip().split( '=')[1] elif i.lstrip().split('=')[0] == 'countryName': subject['countryName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'stateOrProvinceName': subject['stateOrProvinceName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'localityName': subject['localityName'] = i.lstrip().split('=')[1] for k, v in hashfunctions.items(): if k == 'md5': md5 = v(cert).hexdigest() elif k == 'sha1': sha1 = v(cert).hexdigest() elif k == 'sha256': sha256 = v(cert).hexdigest() elif k == 'sha512': sha512 = v(cert).hexdigest() md5 = md5 appName = a.get_app_name() fileSize = os.stat(a.get_filename()).st_size sha1 = sha1 sha256 = sha256 sha512 = sha512 timestamp = time.time() dateTime = datetime.fromtimestamp(timestamp) timeOfSubmit = dateTime.strftime("%Y-%m-%d %H:%M:%S") package = a.get_package() androidversionCode = a.get_androidversion_code() androidversionName = a.get_androidversion_name() minSDKVersion = a.get_min_sdk_version() maxSDKVersion = a.get_max_sdk_version() targetSDKVersion = a.get_target_sdk_version() mainActivity = a.get_main_activity() attributes = { 'validFrom': x509_cert['tbs_certificate']['validity'] ['not_before'].native.strftime("%Y-%m-%d %H:%M:%S"), 'validTo': x509_cert['tbs_certificate']['validity'] ['not_after'].native.strftime("%Y-%m-%d %H:%M:%S"), 'serialNumber': hex(x509_cert.serial_number), 'hashAlgorithm': x509_cert.hash_algo, 'signatureAlgorithm': x509_cert.signature_algo } certificateAttributes = json.dumps(attributes) certificateIssuer = json.dumps(issuer) certificateSubject = json.dumps(subject) declaredPermissions = json.dumps(a.get_declared_permissions()) requestedPermissions = json.dumps(a.get_permissions()) activities = json.dumps(a.get_activities()) services = json.dumps(a.get_services()) receivers = json.dumps(a.get_receivers()) providers = json.dumps(a.get_providers()) stop = process_time() analysisTime = stop - start connect = mysql.connect() cursor = connect.cursor() sql = "INSERT INTO tbl_apkinfo (md5, appName, fileSize, analysisTime, sha1, sha256, sha512, firstSubmission, lastSubmission, package, androidversionCode, androidversionName, minSDKVersion, maxSDKVersion, targetSDKVersion, mainActivity, certificateAttributes, certificateIssuer, certificateSubject, declaredPermissions, requestedPermissions, activities, services, providers, receivers) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" param = (md5, appName, fileSize, analysisTime, sha1, sha256, sha512, timeOfSubmit, timeOfSubmit, package, androidversionCode, androidversionName, minSDKVersion, maxSDKVersion, targetSDKVersion, mainActivity, certificateAttributes, certificateIssuer, certificateSubject, declaredPermissions, requestedPermissions, activities, services, providers, receivers) cursor.execute(sql, param) connect.commit() connect.close() androaxml_main(path, os.path.join(app.config['OUTPUT_PATH'], md5 + '.xml')) return True except: return False
def testApksignAPKs(self): # These APKs are from the apksign testcases and cover # all different signature algorithms as well as some error cases from androguard.core.bytecodes.apk import APK import zipfile from asn1crypto import x509, pem import binascii root = "examples/signing/apksig" # Correct values generated with openssl: certfp = { "dsa-1024.x509.pem": "fee7c19ff9bfb4197b3727b9fd92d95406b1bd96db99ea642f5faac019a389d7", "dsa-2048.x509.pem": "97cce0bab292c2d5afb9de90e1810b41a5d25c006a10d10982896aa12ab35a9e", "dsa-3072.x509.pem": "966a4537058d24098ea213f12d4b24e37ff5a1d8f68deb8a753374881f23e474", "ec-p256.x509.pem": "6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599", "ec-p384.x509.pem": "5e7777ada7ee7ce8f9c4d1b07094876e5604617b7988b4c5d5b764a23431afbe", "ec-p521.x509.pem": "69b50381d98bebcd27df6d7df8af8c8b38d0e51e9168a95ab992d1a9da6082da", "rsa-1024.x509.pem": "bc5e64eab1c4b5137c0fbc5ed05850b3a148d1c41775cffa4d96eea90bdd0eb8", "rsa-16384.x509.pem": "f3c6b37909f6df310652fbd7c55ec27d3079dcf695dc6e75e22ba7c4e1c95601", "rsa-2048.x509.pem": "fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8", "rsa-3072.x509.pem": "483934461229a780010bc07cd6eeb0b67025fc4fe255757abbf5c3f2ed249e89", "rsa-4096.x509.pem": "6a46158f87753395a807edcc7640ac99c9125f6b6e025bdbf461ff281e64e685", "rsa-8192.x509.pem": "060d0a24fea9b60d857225873f78838e081795f7ef2d1ea401262bbd75a58234", } will_not_validate_correctly = [ "targetSandboxVersion-2.apk", "targetSandboxVersion-2.apk", "v1-only-with-cr-in-entry-name.apk", "v1-only-with-lf-in-entry-name.apk", "v1-only-with-nul-in-entry-name.apk", "v1-only-with-rsa-1024-cert-not-der2.apk", "v2-only-cert-and-public-key-mismatch.apk", "v2-only-with-dsa-sha256-1024-sig-does-not-verify.apk", ] # Collect possible hashes for certificates # Unfortunately, not all certificates are supplied... for apath in os.listdir(root): if apath in certfp: with open(os.path.join(root, apath), "rb") as fp: cert = x509.Certificate.load(pem.unarmor(fp.read())[2]) h = cert.sha256_fingerprint.replace(" ", "").lower() self.assertEqual(h, certfp[apath]) self.assertIn(h, certfp.values()) for apath in os.listdir(root): if apath.endswith(".apk"): if apath == "v2-only-garbage-between-cd-and-eocd.apk" or \ apath == "v2-only-truncated-cd.apk": # Can not load as APK if sys.version_info.major == 2: # Different name in python2... with self.assertRaises(zipfile.BadZipfile): APK(os.path.join(root, apath)) else: with self.assertRaises(zipfile.BadZipFile): APK(os.path.join(root, apath)) continue elif apath in will_not_validate_correctly: # These APKs are faulty (by design) and will return a not correct fingerprint. # TODO: we need to check if we can prevent such errors... continue a = APK(os.path.join(root, apath)) self.assertIsInstance(a, APK) # Special error cases if apath == "v2-only-apk-sig-block-size-mismatch.apk": with self.assertRaises(AssertionError): a.is_signed_v2() continue elif apath == "v2-only-empty.apk": with self.assertRaises(AssertionError): a.is_signed_v2() continue if a.is_signed_v1(): if apath == "weird-compression-method.apk": with self.assertRaises(NotImplementedError): for c in a.get_signature_names(): a.get_certificate(c) elif apath == "v1-only-with-rsa-1024-cert-not-der.apk": for sig in a.get_signature_names(): c = a.get_certificate(sig) h = c.sha256_fingerprint.replace(" ", "").lower() self.assertNotIn(h, certfp.values()) # print([apath, h]) # I do not know, why put this file? der = a.get_certificate_der(sig) apk.show_Certificate(c, True) apk.show_Certificate(c, False) self.assertEqual( hashlib.sha256(der).hexdigest(), h) pass else: for sig in a.get_signature_names(): c = a.get_certificate(sig) h = c.sha256_fingerprint.replace(" ", "").lower() self.assertIn(h, certfp.values()) # Check that we get the same signature if we take the DER der = a.get_certificate_der(sig) self.assertEqual( hashlib.sha256(der).hexdigest(), h) if a.is_signed_v2(): if apath == "weird-compression-method.apk": with self.assertRaises(NotImplementedError): a.get_certificates_der_v2() elif apath == "v2-only-with-rsa-pkcs1-sha256-1024-cert-not-der.apk": # FIXME # Not sure what this one should do... but the certificate fingerprint is weird # as the hash over the DER is not the same when using the certificate continue else: for c in a.get_certificates_der_v2(): cert = x509.Certificate.load(c) h = cert.sha256_fingerprint.replace(" ", "").lower() self.assertIn(h, certfp.values()) # Check that we get the same signature if we take the DER self.assertEqual(hashlib.sha256(c).hexdigest(), h)
def main(): parser = get_parser() args = parser.parse_args() hashfunctions = dict(md5=hashlib.md5, sha1=hashlib.sha1, sha256=hashlib.sha256, sha512=hashlib.sha512, ) if args.hash.lower() not in hashfunctions: print("Hash function {} not supported!".format(args.hash.lower()), file=sys.stderr) print("Use one of {}".format(", ".join(hashfunctions.keys())), file=sys.stderr) sys.exit(1) for path in args.apk: try: a = APK(path) print("{}, package: '{}'".format(os.path.basename(path), a.get_package())) print("Is signed v1: {}".format(a.is_signed_v1())) print("Is signed v2: {}".format(a.is_signed_v2())) certs = set(a.get_certificates_der_v2() + [a.get_certificate_der(x) for x in a.get_signature_names()]) if len(certs) > 0: print("Found {} unique certificates".format(len(certs))) for cert in certs: if args.show: x509_cert = x509.Certificate.load(cert) print("Issuer:", get_certificate_name_string(x509_cert.issuer, short=True)) print("Subject:", get_certificate_name_string(x509_cert.subject, short=True)) print("Serial Number:", hex(x509_cert.serial_number)) print("Hash Algorithm:", x509_cert.hash_algo) print("Signature Algorithm:", x509_cert.signature_algo) print("Valid not before:", x509_cert['tbs_certificate']['validity']['not_before'].native) print("Valid not after:", x509_cert['tbs_certificate']['validity']['not_after'].native) if not args.all: print("{} {}".format(args.hash.lower(), hashfunctions[args.hash.lower()](cert).hexdigest())) else: for k, v in hashfunctions.items(): print("{} {}".format(k, v(cert).hexdigest())) print() except: print(Fore.RED + "Error in {}".format(os.path.basename(path)) + Style.RESET_ALL, file=sys.stderr) traceback.print_exc(file=sys.stderr) if len(args.apk) > 1: print()
def testApksignAPKs(self): # These APKs are from the apksign testcases and cover # all different signature algorithms as well as some error cases from androguard.core.bytecodes.apk import APK import zipfile from asn1crypto import x509, pem import binascii root = "examples/signing/apksig" # Correct values generated with openssl: certfp = { "dsa-1024.x509.pem": "fee7c19ff9bfb4197b3727b9fd92d95406b1bd96db99ea642f5faac019a389d7", "dsa-2048.x509.pem": "97cce0bab292c2d5afb9de90e1810b41a5d25c006a10d10982896aa12ab35a9e", "dsa-3072.x509.pem": "966a4537058d24098ea213f12d4b24e37ff5a1d8f68deb8a753374881f23e474", "ec-p256.x509.pem": "6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599", "ec-p384.x509.pem": "5e7777ada7ee7ce8f9c4d1b07094876e5604617b7988b4c5d5b764a23431afbe", "ec-p521.x509.pem": "69b50381d98bebcd27df6d7df8af8c8b38d0e51e9168a95ab992d1a9da6082da", "rsa-1024.x509.pem": "bc5e64eab1c4b5137c0fbc5ed05850b3a148d1c41775cffa4d96eea90bdd0eb8", "rsa-16384.x509.pem": "f3c6b37909f6df310652fbd7c55ec27d3079dcf695dc6e75e22ba7c4e1c95601", "rsa-2048.x509.pem": "fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8", "rsa-3072.x509.pem": "483934461229a780010bc07cd6eeb0b67025fc4fe255757abbf5c3f2ed249e89", "rsa-4096.x509.pem": "6a46158f87753395a807edcc7640ac99c9125f6b6e025bdbf461ff281e64e685", "rsa-8192.x509.pem": "060d0a24fea9b60d857225873f78838e081795f7ef2d1ea401262bbd75a58234", } will_not_validate_correctly = [ "targetSandboxVersion-2.apk", "targetSandboxVersion-2.apk", "v1-only-with-cr-in-entry-name.apk", "v1-only-with-lf-in-entry-name.apk", "v1-only-with-nul-in-entry-name.apk", "v1-only-with-rsa-1024-cert-not-der2.apk", "v2-only-cert-and-public-key-mismatch.apk", "v2-only-with-dsa-sha256-1024-sig-does-not-verify.apk", ] # Collect possible hashes for certificates # Unfortunately, not all certificates are supplied... for apath in os.listdir(root): if apath in certfp: with open(os.path.join(root, apath), "rb") as fp: cert = x509.Certificate.load(pem.unarmor(fp.read())[2]) h = cert.sha256_fingerprint.replace(" ","").lower() self.assertEqual(h, certfp[apath]) self.assertIn(h, certfp.values()) for apath in os.listdir(root): if apath.endswith(".apk"): if apath == "v2-only-garbage-between-cd-and-eocd.apk" or \ apath == "v2-only-truncated-cd.apk": # Can not load as APK if sys.version_info.major == 2: # Different name in python2... with self.assertRaises(zipfile.BadZipfile): APK(os.path.join(root, apath)) else: with self.assertRaises(zipfile.BadZipFile): APK(os.path.join(root, apath)) continue elif apath in will_not_validate_correctly: # These APKs are faulty (by design) and will return a not correct fingerprint. # TODO: we need to check if we can prevent such errors... continue a = APK(os.path.join(root, apath)) self.assertIsInstance(a, APK) # Special error cases if apath == "v2-only-apk-sig-block-size-mismatch.apk": with self.assertRaises(AssertionError): a.is_signed_v2() continue elif apath == "v2-only-empty.apk": with self.assertRaises(AssertionError): a.is_signed_v2() continue if a.is_signed_v1(): if apath == "weird-compression-method.apk": with self.assertRaises(NotImplementedError): for c in a.get_signature_names(): a.get_certificate(c) elif apath == "v1-only-with-rsa-1024-cert-not-der.apk": for sig in a.get_signature_names(): c = a.get_certificate(sig) h = c.sha256_fingerprint.replace(" ","").lower() self.assertNotIn(h, certfp.values()) # print([apath, h]) # I do not know, why put this file? der = a.get_certificate_der(sig) apk.show_Certificate(c, True) apk.show_Certificate(c, False) self.assertEqual(hashlib.sha256(der).hexdigest(), h) pass else: for sig in a.get_signature_names(): c = a.get_certificate(sig) h = c.sha256_fingerprint.replace(" ","").lower() self.assertIn(h, certfp.values()) # Check that we get the same signature if we take the DER der = a.get_certificate_der(sig) self.assertEqual(hashlib.sha256(der).hexdigest(), h) if a.is_signed_v2(): if apath == "weird-compression-method.apk": with self.assertRaises(NotImplementedError): a.get_certificates_der_v2() elif apath == "v2-only-with-rsa-pkcs1-sha256-1024-cert-not-der.apk": # FIXME # Not sure what this one should do... but the certificate fingerprint is weird # as the hash over the DER is not the same when using the certificate continue else: for c in a.get_certificates_der_v2(): cert = x509.Certificate.load(c) h = cert.sha256_fingerprint.replace(" ","").lower() self.assertIn(h, certfp.values()) # Check that we get the same signature if we take the DER self.assertEqual(hashlib.sha256(c).hexdigest(), h)
def testApksignAPKs(self): # These APKs are from the apksign testcases and cover # all different signature algorithms as well as some error cases from androguard.core.bytecodes.apk import APK import zipfile from asn1crypto import x509, pem import binascii root = "examples/signing/apksig" # Correct values generated with openssl: # In the apksig repo:src/test/resources/com/android/apksig # for f in *.pem; do openssl x509 -in $f -noout -sha256 -fingerprint; done certfp = { 'dsa-1024.x509.pem': 'fee7c19ff9bfb4197b3727b9fd92d95406b1bd96db99ea642f5faac019a389d7', 'dsa-2048.x509.pem': '97cce0bab292c2d5afb9de90e1810b41a5d25c006a10d10982896aa12ab35a9e', 'dsa-3072.x509.pem': '966a4537058d24098ea213f12d4b24e37ff5a1d8f68deb8a753374881f23e474', 'ec-p256.x509.pem': '6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599', 'ec-p384.x509.pem': '5e7777ada7ee7ce8f9c4d1b07094876e5604617b7988b4c5d5b764a23431afbe', 'ec-p521.x509.pem': '69b50381d98bebcd27df6d7df8af8c8b38d0e51e9168a95ab992d1a9da6082da', 'rsa-1024_2.x509.pem': 'eba3685e799f59804684abebf0363e14ccb1c213e2b954a22669714ed97f61e9', 'rsa-1024.x509.pem': 'bc5e64eab1c4b5137c0fbc5ed05850b3a148d1c41775cffa4d96eea90bdd0eb8', 'rsa-16384.x509.pem': 'f3c6b37909f6df310652fbd7c55ec27d3079dcf695dc6e75e22ba7c4e1c95601', 'rsa-2048_2.x509.pem': '681b0e56a796350c08647352a4db800cc44b2adc8f4c72fa350bd05d4d50264d', 'rsa-2048_3.x509.pem': 'bb77a72efc60e66501ab75953af735874f82cfe52a70d035186a01b3482180f3', 'rsa-2048.x509.pem': 'fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8', 'rsa-3072.x509.pem': '483934461229a780010bc07cd6eeb0b67025fc4fe255757abbf5c3f2ed249e89', 'rsa-4096.x509.pem': '6a46158f87753395a807edcc7640ac99c9125f6b6e025bdbf461ff281e64e685', 'rsa-8192.x509.pem': '060d0a24fea9b60d857225873f78838e081795f7ef2d1ea401262bbd75a58234', } will_not_validate_correctly = [ "targetSandboxVersion-2.apk", "targetSandboxVersion-2.apk", "v1-only-with-cr-in-entry-name.apk", "v1-only-with-lf-in-entry-name.apk", "v1-only-with-nul-in-entry-name.apk", "v1-only-with-rsa-1024-cert-not-der2.apk", "v2-only-cert-and-public-key-mismatch.apk", "v2-only-with-dsa-sha256-1024-sig-does-not-verify.apk", "debuggable-boolean.apk", "debuggable-resource.apk", ] # Collect possible hashes for certificates # Unfortunately, not all certificates are supplied... for apath in os.listdir(root): if apath in certfp: with open(os.path.join(root, apath), "rb") as fp: cert = x509.Certificate.load(pem.unarmor(fp.read())[2]) h = cert.sha256_fingerprint.replace(" ","").lower() self.assertEqual(h, certfp[apath]) self.assertIn(h, certfp.values()) for apath in os.listdir(root): if apath.endswith(".apk"): if apath == "v2-only-garbage-between-cd-and-eocd.apk" or \ apath == "v2-only-truncated-cd.apk" or \ apath == "v1v2v3-with-rsa-2048-lineage-3-signers-invalid-zip.apk": # Can not load as APK with self.assertRaises(zipfile.BadZipFile): APK(os.path.join(root, apath)) continue elif apath in will_not_validate_correctly: # These APKs are faulty (by design) and will return a not correct fingerprint. # TODO: we need to check if we can prevent such errors... continue a = APK(os.path.join(root, apath)) self.assertIsInstance(a, APK) # Test if the correct method returns True, while others return # False m_tests = {'1': a.is_signed_v1, '2': a.is_signed_v2, '3': a.is_signed_v3} # These APKs will raise an error excluded = [ "v1v2v3-with-rsa-2048-lineage-3-signers-no-sig-block.apk", "v2-only-apk-sig-block-size-mismatch.apk", "v2-only-empty.apk", "v2-only-wrong-apk-sig-block-magic.apk", "v2-stripped.apk", "v2-stripped-with-ignorable-signing-schemes.apk", "v2v3-signed-v3-block-stripped.apk", "v3-only-empty.apk", "v3-only-with-ecdsa-sha512-p384-wrong-apk-sig-block-magic.apk", "v3-only-with-rsa-pkcs1-sha512-4096-apk-sig-block-size-mismatch.apk", "v3-stripped.apk", ] if apath[0] == "v" and apath not in excluded: methods = apath.split("-", 1)[0].split("v")[1:] for m, f in m_tests.items(): if m in methods: self.assertTrue(f()) else: self.assertFalse(f()) # Special error cases if apath == "v2-only-apk-sig-block-size-mismatch.apk": with self.assertRaises(apk.BrokenAPKError): a.is_signed_v2() continue elif apath == "v2-only-empty.apk": with self.assertRaises(apk.BrokenAPKError): a.is_signed_v2() continue elif apath == "v3-only-with-rsa-pkcs1-sha512-4096-apk-sig-block-size-mismatch.apk": with self.assertRaises(apk.BrokenAPKError): a.is_signed_v3() continue if a.is_signed_v1(): if apath == "weird-compression-method.apk": with self.assertRaises(NotImplementedError): for c in a.get_signature_names(): a.get_certificate(c) elif apath == "v1-only-with-rsa-1024-cert-not-der.apk": for sig in a.get_signature_names(): c = a.get_certificate(sig) h = c.sha256_fingerprint.replace(" ","").lower() self.assertNotIn(h, certfp.values()) # print([apath, h]) # I do not know, why put this file? der = a.get_certificate_der(sig) apk.show_Certificate(c, True) apk.show_Certificate(c, False) self.assertEqual(hashlib.sha256(der).hexdigest(), h) pass else: for sig in a.get_signature_names(): c = a.get_certificate(sig) h = c.sha256_fingerprint.replace(" ","").lower() self.assertIn(h, certfp.values()) # Check that we get the same signature if we take the DER der = a.get_certificate_der(sig) self.assertEqual(hashlib.sha256(der).hexdigest(), h) if a.is_signed_v2(): if apath == "weird-compression-method.apk": with self.assertRaises(NotImplementedError): a.get_certificates_der_v2() elif apath == "v2-only-with-rsa-pkcs1-sha256-1024-cert-not-der.apk": # FIXME # Not sure what this one should do... but the certificate fingerprint is weird # as the hash over the DER is not the same when using the certificate continue else: for c in a.get_certificates_der_v2(): cert = x509.Certificate.load(c) h = cert.sha256_fingerprint.replace(" ","").lower() self.assertIn(h, certfp.values()) # Check that we get the same signature if we take the DER self.assertEqual(hashlib.sha256(c).hexdigest(), h) if a.is_signed_v3(): print(apath) if apath == "weird-compression-method.apk": with self.assertRaises(NotImplementedError): a.get_certificates_der_v3() elif apath == "v3-only-with-rsa-pkcs1-sha256-3072-sig-does-not-verify.apk" or \ apath == "v3-only-cert-and-public-key-mismatch.apk": cert = x509.Certificate.load(a.get_certificates_der_v3()[0]) h = cert.sha256_fingerprint.replace(" ","").lower() self.assertNotIn(h, certfp.values()) else: for c in a.get_certificates_der_v3(): cert = x509.Certificate.load(c) h = cert.sha256_fingerprint.replace(" ","").lower() self.assertIn(h, certfp.values()) # Check that we get the same signature if we take the DER self.assertEqual(hashlib.sha256(c).hexdigest(), h)