import hashlib
import socket
import base64
+import zipfile
import xml.etree.ElementTree as XMLElementTree
from binascii import hexlify
apk_sigfile = re.compile(r'META-INF/[0-9A-Za-z]+\.(SF|RSA|DSA|EC)')
+def signer_fingerprint(sig):
+ """Obtain sha256 signing-key fingerprint for pkcs7 signature.
+
+ Extracts hexadecimal sha256 signing-key fingerprint string
+ for a given pkcs7 signature.
+
+ :param: Contents of an APK signature.
+ :returns: shortened signature fingerprint.
+ """
+ cert_encoded = get_certificate(sig)
+ return hashlib.sha256(cert_encoded).hexdigest()
+
+
+def apk_signer_fingerprint(apk_path):
+ """Obtain sha256 signing-key fingerprint for APK.
+
+ Extracts hexadecimal sha256 signing-key fingerprint string
+ for a given APK.
+
+ :param apkpath: path to APK
+ :returns: signature fingerprint
+ """
+
+ with zipfile.ZipFile(apk_path, 'r') as apk:
+ certs = [n for n in apk.namelist() if CERT_PATH_REGEX.match(n)]
+
+ if len(certs) < 1:
+ logging.error("Found no signing certificates on %s" % apk_path)
+ return None
+ if len(certs) > 1:
+ logging.error("Found multiple signing certificates on %s" % apk_path)
+ return None
+
+ cert = apk.read(certs[0])
+ return signer_fingerprint(cert)
+
+
def metadata_get_sigdir(appid, vercode=None):
"""Get signature directory for app"""
if vercode:
for name in bad:
self.assertIsNone(fdroidserver.common.STANDARD_FILE_NAME_REGEX.match(name))
+ def test_apk_signer_fingerprint(self):
+
+ # fingerprints fetched with: keytool -printcert -file ____.RSA
+ testapks = (('repo/obb.main.oldversion_1444412523.apk',
+ '818e469465f96b704e27be2fee4c63ab9f83ddf30e7a34c7371a4728d83b0bc1'),
+ ('repo/obb.main.twoversions_1101613.apk',
+ '32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6'),
+ ('repo/obb.main.twoversions_1101617.apk',
+ '32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6'))
+
+ for apkfile, keytoolcertfingerprint in testapks:
+ self.assertEqual(keytoolcertfingerprint,
+ fdroidserver.common.apk_signer_fingerprint(apkfile))
+
if __name__ == "__main__":
parser = optparse.OptionParser()