diff --git a/src/xmlsec/crypto.py b/src/xmlsec/crypto.py index 0e47c10..9400430 100644 --- a/src/xmlsec/crypto.py +++ b/src/xmlsec/crypto.py @@ -15,6 +15,7 @@ from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.primitives.asymmetric import padding, ec from cryptography.x509 import load_pem_x509_certificate, load_der_x509_certificate, Certificate +from xmlsec.utils import load_pem_x509_cert_str_safe from xmlsec.utils import sigvalue2dsssig, noop import base64 @@ -249,7 +250,7 @@ def __init__(self, signature_element, keyspec): super(XMLSecCryptoFromXML, self).__init__(source=source, do_padding=False, private=False, do_digest=False) - self.key = load_pem_x509_certificate(data, backend=default_backend()) + self.key = load_pem_x509_cert_str_safe(data, backend=default_backend()) # XXX now we could implement encrypted-PEM-support self.cert_pem = self.key.public_bytes(encoding=serialization.Encoding.PEM) @@ -329,7 +330,7 @@ def __setitem__(self, key, value): if isinstance(value, Certificate): self.certs[key] = value else: - self.certs[key] = load_pem_x509_certificate(value, backend=default_backend()) + self.certs[key] = load_pem_x509_cert_str_safe(value, backend=default_backend()) def __delitem__(self, key): del self.certs[key] @@ -358,7 +359,7 @@ def _get_cert_by_fp(self, fp): def _cert_fingerprint(cert_pem): if "-----BEGIN CERTIFICATE" in cert_pem: - cert = load_pem_x509_certificate(cert_pem, backend=default_backend()) + cert = load_pem_x509_cert_str_safe(cert_pem, backend=default_backend()) else: cert = load_der_x509_certificate(base64.standard_b64decode(cert_pem), backend=default_backend()) diff --git a/src/xmlsec/utils.py b/src/xmlsec/utils.py index 8683fbc..46a0f35 100644 --- a/src/xmlsec/utils.py +++ b/src/xmlsec/utils.py @@ -16,6 +16,18 @@ import re from base64 import b64encode, standard_b64decode +def load_pem_x509_cert_str_safe(data, *args, **kwargs): + """ + Load a PEM-encoded X.509 certificate safely from a string or bytestring. + + :param data: str or bytes: The PEM X.509 certificate data as a string or bytestring + :returns: A X.509 certificate object + + *args and **kwargs are passed to load_pem_x509_certificate + """ + if isinstance(data, six.text_type): + data = data.encode() + return load_pem_x509_certificate(data, *args, **kwargs) def parse_xml(data, remove_whitespace=True, remove_comments=True, schema=None): """ @@ -80,7 +92,7 @@ def pem2cert(pem): be used by new code. @param pem The certificate as pem string """ - cert = load_pem_x509_certificate(pem, backend=default_backend()) + cert = load_pem_x509_cert_str_safe(pem, backend=default_backend()) return _cert2dict(cert)