mirror of
https://gitlab.com/fdroid/fdroidserver.git
synced 2024-11-14 02:50:12 +01:00
Replace getsig.java with a pure python implementation
Special thanks to deki for helping out with the certificate encodings: https://gitlab.com/snippets/1842 fixes #5 https://gitlab.com/fdroid/fdroidserver/issues/5
This commit is contained in:
parent
c88eff9af7
commit
6e2d0a9e1e
@ -24,9 +24,6 @@ include examples/config.py
|
|||||||
include examples/fdroid-icon.png
|
include examples/fdroid-icon.png
|
||||||
include examples/makebs.config.py
|
include examples/makebs.config.py
|
||||||
include examples/opensc-fdroid.cfg
|
include examples/opensc-fdroid.cfg
|
||||||
include fdroidserver/getsig/run.sh
|
|
||||||
include fdroidserver/getsig/make.sh
|
|
||||||
include fdroidserver/getsig/getsig.java
|
|
||||||
include tests/run-tests
|
include tests/run-tests
|
||||||
include tests/urzip.apk
|
include tests/urzip.apk
|
||||||
include wp-fdroid/AndroidManifest.xml
|
include wp-fdroid/AndroidManifest.xml
|
||||||
|
@ -29,6 +29,11 @@ import pickle
|
|||||||
from xml.dom.minidom import Document
|
from xml.dom.minidom import Document
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
import time
|
import time
|
||||||
|
from pyasn1.error import PyAsn1Error
|
||||||
|
from pyasn1.codec.der import decoder, encoder
|
||||||
|
from pyasn1_modules import rfc2315
|
||||||
|
from hashlib import md5
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -322,6 +327,52 @@ def resize_all_icons(repodirs):
|
|||||||
resize_icon(iconpath, density)
|
resize_icon(iconpath, density)
|
||||||
|
|
||||||
|
|
||||||
|
cert_path_regex = re.compile(r'^META-INF/.*\.RSA$')
|
||||||
|
|
||||||
|
|
||||||
|
def getsig(apkpath):
|
||||||
|
""" Get the signing certificate of an apk. To get the same md5 has that
|
||||||
|
Android gets, we encode the .RSA certificate in a specific format and pass
|
||||||
|
it hex-encoded to the md5 digest algorithm.
|
||||||
|
|
||||||
|
:param apkpath: path to the apk
|
||||||
|
:returns: A string containing the md5 of the signature of the apk or None
|
||||||
|
if an error occurred.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cert = None
|
||||||
|
|
||||||
|
with zipfile.ZipFile(apkpath, '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" % apkpath)
|
||||||
|
return None
|
||||||
|
if len(certs) > 1:
|
||||||
|
logging.error("Found multiple signing certificates on %s" % apkpath)
|
||||||
|
return None
|
||||||
|
|
||||||
|
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:]
|
||||||
|
|
||||||
|
return md5(cert_encoded.encode('hex')).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def scan_apks(apps, apkcache, repodir, knownapks):
|
def scan_apks(apps, apkcache, repodir, knownapks):
|
||||||
"""Scan the apks in the given repo directory.
|
"""Scan the apks in the given repo directory.
|
||||||
|
|
||||||
@ -476,18 +527,8 @@ def scan_apks(apps, apkcache, repodir, knownapks):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Get the signature (or md5 of, to be precise)...
|
# Get the signature (or md5 of, to be precise)...
|
||||||
getsig_dir = os.path.join(os.path.dirname(__file__), 'getsig')
|
thisinfo['sig'] = getsig(os.path.join(os.getcwd(), apkfile))
|
||||||
if not os.path.exists(getsig_dir + "/getsig.class"):
|
if not thisinfo['sig']:
|
||||||
logging.critical("getsig.class not found. To fix: cd '%s' && ./make.sh" % getsig_dir)
|
|
||||||
sys.exit(1)
|
|
||||||
p = FDroidPopen(['java', '-cp', os.path.join(os.path.dirname(__file__), 'getsig'),
|
|
||||||
'getsig', os.path.join(os.getcwd(), apkfile)])
|
|
||||||
thisinfo['sig'] = None
|
|
||||||
for line in p.output.splitlines():
|
|
||||||
if line.startswith('Result:'):
|
|
||||||
thisinfo['sig'] = line[7:].strip()
|
|
||||||
break
|
|
||||||
if p.returncode != 0 or not thisinfo['sig']:
|
|
||||||
logging.critical("Failed to get apk signature")
|
logging.critical("Failed to get apk signature")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
@ -38,11 +38,6 @@ fi
|
|||||||
|
|
||||||
export PATH=/usr/lib/jvm/java-7-openjdk-amd64/bin:$PATH
|
export PATH=/usr/lib/jvm/java-7-openjdk-amd64/bin:$PATH
|
||||||
|
|
||||||
#------------------------------------------------------------------------------#
|
|
||||||
# run local build
|
|
||||||
cd $WORKSPACE/fdroidserver/getsig
|
|
||||||
./make.sh
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------#
|
#------------------------------------------------------------------------------#
|
||||||
# run local tests
|
# run local tests
|
||||||
|
10
setup.py
10
setup.py
@ -1,14 +1,8 @@
|
|||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python2
|
||||||
|
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if not os.path.exists('fdroidserver/getsig/getsig.class'):
|
|
||||||
subprocess.check_output('cd fdroidserver/getsig && javac getsig.java',
|
|
||||||
shell=True)
|
|
||||||
|
|
||||||
setup(name='fdroidserver',
|
setup(name='fdroidserver',
|
||||||
version='0.2.1',
|
version='0.2.1',
|
||||||
description='F-Droid Server Tools',
|
description='F-Droid Server Tools',
|
||||||
@ -25,8 +19,6 @@ setup(name='fdroidserver',
|
|||||||
'examples/makebs.config.py',
|
'examples/makebs.config.py',
|
||||||
'examples/opensc-fdroid.cfg',
|
'examples/opensc-fdroid.cfg',
|
||||||
'examples/fdroid-icon.png']),
|
'examples/fdroid-icon.png']),
|
||||||
('fdroidserver/getsig',
|
|
||||||
['fdroidserver/getsig/getsig.class']),
|
|
||||||
],
|
],
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'mwclient',
|
'mwclient',
|
||||||
@ -34,6 +26,8 @@ setup(name='fdroidserver',
|
|||||||
'Pillow',
|
'Pillow',
|
||||||
'python-magic',
|
'python-magic',
|
||||||
'apache-libcloud >= 0.14.1',
|
'apache-libcloud >= 0.14.1',
|
||||||
|
'pyasn1',
|
||||||
|
'pyasn1-modules',
|
||||||
],
|
],
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 3 - Alpha',
|
'Development Status :: 3 - Alpha',
|
||||||
|
@ -101,8 +101,6 @@ $python setup.py sdist
|
|||||||
REPOROOT=`create_test_dir`
|
REPOROOT=`create_test_dir`
|
||||||
cd $REPOROOT
|
cd $REPOROOT
|
||||||
tar xzf `ls -1 $WORKSPACE/dist/fdroidserver-*.tar.gz | sort -n | tail -1`
|
tar xzf `ls -1 $WORKSPACE/dist/fdroidserver-*.tar.gz | sort -n | tail -1`
|
||||||
cd $REPOROOT/fdroidserver-*/fdroidserver/getsig
|
|
||||||
./make.sh
|
|
||||||
cd $REPOROOT
|
cd $REPOROOT
|
||||||
./fdroidserver-*/fdroid init
|
./fdroidserver-*/fdroid init
|
||||||
copy_apks_into_repo $REPOROOT
|
copy_apks_into_repo $REPOROOT
|
||||||
|
Loading…
Reference in New Issue
Block a user