mirror of
https://gitlab.com/fdroid/fdroidserver.git
synced 2024-11-14 11:00:10 +01:00
Reduce code duplication
by re-using methods for extracting and verifying certificate
This commit is contained in:
parent
a23da47118
commit
7c34dd96f4
@ -42,6 +42,10 @@ from distutils.version import LooseVersion
|
|||||||
from queue import Queue
|
from queue import Queue
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
|
from pyasn1.codec.der import decoder, encoder
|
||||||
|
from pyasn1_modules import rfc2315
|
||||||
|
from pyasn1.error import PyAsn1Error
|
||||||
|
|
||||||
import fdroidserver.metadata
|
import fdroidserver.metadata
|
||||||
from .asynchronousfilereader import AsynchronousFileReader
|
from .asynchronousfilereader import AsynchronousFileReader
|
||||||
|
|
||||||
@ -2221,6 +2225,26 @@ def get_cert_fingerprint(pubkey):
|
|||||||
return " ".join(ret)
|
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):
|
def write_to_config(thisconfig, key, value=None, config_file=None):
|
||||||
'''write a key/value to the local config.py
|
'''write a key/value to the local config.py
|
||||||
|
|
||||||
|
@ -36,8 +36,6 @@ from datetime import datetime
|
|||||||
from xml.dom.minidom import Document
|
from xml.dom.minidom import Document
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from pyasn1.codec.der import decoder, encoder
|
|
||||||
from pyasn1_modules import rfc2315
|
|
||||||
|
|
||||||
from fdroidserver import metadata, signindex, common
|
from fdroidserver import metadata, signindex, common
|
||||||
from fdroidserver.common import FDroidPopen, FDroidPopenBytes
|
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.")
|
raise VerificationException("Found multiple signing certificates for repository.")
|
||||||
|
|
||||||
# extract public key from certificate
|
# 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(' ', '')
|
public_key_fingerprint = common.get_cert_fingerprint(public_key).replace(' ', '')
|
||||||
|
|
||||||
return public_key, public_key_fingerprint
|
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)
|
|
||||||
|
@ -34,9 +34,6 @@ from datetime import datetime, timedelta
|
|||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
from pyasn1.error import PyAsn1Error
|
|
||||||
from pyasn1.codec.der import decoder, encoder
|
|
||||||
from pyasn1_modules import rfc2315
|
|
||||||
from binascii import hexlify
|
from binascii import hexlify
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
@ -45,7 +42,7 @@ import logging
|
|||||||
from . import common
|
from . import common
|
||||||
from . import index
|
from . import index
|
||||||
from . import metadata
|
from . import metadata
|
||||||
from .common import FDroidPopen, SdkToolsPopen
|
from .common import SdkToolsPopen
|
||||||
|
|
||||||
METADATA_VERSION = 18
|
METADATA_VERSION = 18
|
||||||
|
|
||||||
@ -389,17 +386,11 @@ def getsig(apkpath):
|
|||||||
if an error occurred.
|
if an error occurred.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cert = None
|
|
||||||
|
|
||||||
# verify the jar signature is correct
|
# verify the jar signature is correct
|
||||||
args = [config['jarsigner'], '-verify', apkpath]
|
if not common.verify_apk_signature(apkpath):
|
||||||
p = FDroidPopen(args)
|
|
||||||
if p.returncode != 0:
|
|
||||||
logging.critical(apkpath + " has a bad signature!")
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
with zipfile.ZipFile(apkpath, 'r') as apk:
|
with zipfile.ZipFile(apkpath, 'r') as apk:
|
||||||
|
|
||||||
certs = [n for n in apk.namelist() if common.CERT_PATH_REGEX.match(n)]
|
certs = [n for n in apk.namelist() if common.CERT_PATH_REGEX.match(n)]
|
||||||
|
|
||||||
if len(certs) < 1:
|
if len(certs) < 1:
|
||||||
@ -411,20 +402,7 @@ def getsig(apkpath):
|
|||||||
|
|
||||||
cert = apk.read(certs[0])
|
cert = apk.read(certs[0])
|
||||||
|
|
||||||
content = decoder.decode(cert, asn1Spec=rfc2315.ContentInfo())[0]
|
cert_encoded = common.get_certificate(cert)
|
||||||
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 hashlib.md5(hexlify(cert_encoded)).hexdigest()
|
return hashlib.md5(hexlify(cert_encoded)).hexdigest()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user