Terry Pham
Terry Pham

Reputation: 31

signxml throws "InvalidCertificate: [20, 0, 'unable to get local issuer certificate']"

So the context is, I'm trying to write a function that verifies digital signature of a signed XML doc, mainly for tampering detection. I'm using signxml for the task and when I call "verify" it throws"InvalidCertificate: [20, 0, 'unable to get local issuer certificate']"

from signxml import XMLVerifier, XMLSigner
from xml.etree import ElementTree

xml_path = r'FS.xml'
xml = open(xml_path,'r', encoding='utf-8').read()
xml_obj = ElementTree.fromstring(xml)

XMLVerifier().verify(xml_obj)

And the exception is

---------------------------------------------------------------------------
X509StoreContextError                     Traceback (most recent call last)
c:\users\terry\miniconda3\lib\site-packages\signxml\util\__init__.py in _add_cert_to_store(store, cert)
    215     try:
--> 216         X509StoreContext(store, cert).verify_certificate()
    217     except X509StoreContextError as e:

c:\users\terry\miniconda3\lib\site-packages\OpenSSL\crypto.py in verify_certificate(self)
   1808         if ret <= 0:
-> 1809             raise self._exception_from_context()
   1810 

X509StoreContextError: [20, 0, 'unable to get local issuer certificate']

During handling of the above exception, another exception occurred:

InvalidCertificate                        Traceback (most recent call last)
<ipython-input-47-09643ddb2e40> in <module>
      1 # cert = open(r"G:\My Drive\Projects\Credit Modeling\Vietnam\XML Certs\test.cert", "r").read()
      2 
----> 3 XMLVerifier().verify(xml_obj)

c:\users\terry\miniconda3\lib\site-packages\signxml\__init__.py in verify(self, data, require_x509, x509_cert, cert_subject_name, ca_pem_file, ca_path, hmac_key, validate_schema, parser, uri_resolver, id_attribute, expect_references, ignore_ambiguous_key_info)
    778                     raise InvalidInput(msg)
    779                 cert_chain = [load_certificate(FILETYPE_PEM, add_pem_header(cert)) for cert in certs]
--> 780                 signing_cert = verify_x509_cert_chain(cert_chain, ca_pem_file=ca_pem_file, ca_path=ca_path)
    781             elif isinstance(self.x509_cert, X509):
    782                 signing_cert = self.x509_cert

c:\users\terry\miniconda3\lib\site-packages\signxml\util\__init__.py in verify_x509_cert_chain(cert_chain, ca_pem_file, ca_path)
    259                 last_error = e
    260         else:
--> 261             raise last_error
    262     return end_of_chain

c:\users\terry\miniconda3\lib\site-packages\signxml\util\__init__.py in verify_x509_cert_chain(cert_chain, ca_pem_file, ca_path)
    248         for cert in certs:
    249             try:
--> 250                 end_of_chain = _add_cert_to_store(store, cert)
    251                 certs.remove(cert)
    252                 break

c:\users\terry\miniconda3\lib\site-packages\signxml\util\__init__.py in _add_cert_to_store(store, cert)
    216         X509StoreContext(store, cert).verify_certificate()
    217     except X509StoreContextError as e:
--> 218         raise InvalidCertificate(e)
    219     try:
    220         store.add_cert(cert)

InvalidCertificate: [20, 0, 'unable to get local issuer certificate']

Does anyone have any idea how to overcome this?

Much appreciated!

Upvotes: 3

Views: 1312

Answers (1)

hoefling
hoefling

Reputation: 66161

By default, certs from system CA bundle are used and the document was probably signed with a cert that is not in CA bundle. Find the certificate and either add it to trusted system-wide (see e.g. Adding a self-signed certificate to the "trusted list" or How do you add a certificate authority (CA) to Ubuntu? etc) or pass its path via ca_pem_file argument:

XMLVerifier().verify(signed_root, ca_pem_file='path/to/cert.pem')

Upvotes: 1

Related Questions