diff --git a/facho/cli.py b/facho/cli.py index b32c085..ca52d4d 100644 --- a/facho/cli.py +++ b/facho/cli.py @@ -213,13 +213,17 @@ def validate_invoice(invoice_path): @click.option('--private-key', type=click.Path(exists=True)) @click.option('--passphrase') @click.option('--ssl/--no-ssl', default=False) +@click.option('--use-cache-policy/--no-use-cache-policy', default=False) @click.argument('xmlfile', type=click.Path(exists=True), required=True) -def sign_xml(private_key, passphrase, xmlfile, ssl=True): +def sign_xml(private_key, passphrase, xmlfile, ssl=True, use_cache_policy=False): if not ssl: disable_ssl() from facho import fe - signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase) + if use_cache_policy: + warnings.warn("xades using cache policy") + print(use_cache_policy) + signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase, mockpolicy=use_cache_policy) document = open(xmlfile, 'r').read().encode('utf-8') print(signer.sign_xml_string(document)) @@ -229,8 +233,9 @@ def sign_xml(private_key, passphrase, xmlfile, ssl=True): @click.option('--passphrase') @click.option('--ssl/--no-ssl', default=False) @click.option('--sign/--no-sign', default=False) +@click.option('--use-cache-policy/--no-use-cache-policy', default=False) @click.argument('scriptname', type=click.Path(exists=True), required=True) -def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=True, sign=False): +def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=True, sign=False, use_cache_policy=False): """ imprime xml en pantalla. SCRIPTNAME espera @@ -265,7 +270,7 @@ def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=Tr xml.add_extension(extension) if sign: - signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase) + signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase, mockpolicy=use_cache_policy) xml.add_extension(signer) print(xml.tostring(xml_declaration=True)) diff --git a/facho/fe/data/dian/politicadefirmav2.pdf b/facho/fe/data/dian/politicadefirmav2.pdf new file mode 100644 index 0000000..b9bf696 Binary files /dev/null and b/facho/fe/data/dian/politicadefirmav2.pdf differ diff --git a/facho/fe/fe.py b/facho/fe/fe.py index fa5166a..39c6625 100644 --- a/facho/fe/fe.py +++ b/facho/fe/fe.py @@ -181,9 +181,10 @@ class DianXMLExtensionSigner(FachoXMLExtension): POLICY_ID = 'https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf' POLICY_NAME = u'Política de firma para facturas electrónicas de la República de Colombia.' - def __init__(self, pkcs12_path, passphrase=None): + def __init__(self, pkcs12_path, passphrase=None, mockpolicy=False): self._pkcs12_path = pkcs12_path self._passphrase = None + self._mockpolicy = mockpolicy if passphrase: self._passphrase = passphrase.encode('utf-8') @@ -216,7 +217,7 @@ class DianXMLExtensionSigner(FachoXMLExtension): ) xmlsig.template.add_transform(ref, xmlsig.constants.TransformEnveloped) - id_keyinfo = "%s-KeyInfo" % (id_uuid) + id_keyinfo = "xmldsig-%s-KeyInfo" % (id_uuid) xmlsig.template.add_reference( signature, xmlsig.constants.TransformSha256, uri="#%s" % (id_keyinfo), ) @@ -255,8 +256,24 @@ class DianXMLExtensionSigner(FachoXMLExtension): ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(open(self._pkcs12_path, 'rb').read(), self._passphrase)) - ctx.sign(signature) - ctx.verify(signature) + if self._mockpolicy: + from mock import patch + import os.path + with patch('xades.policy.urllib.urlopen') as mock: + class UrllibPolicyMock: + def read(self): + cur_dir = os.path.dirname(os.path.abspath(__file__)) + data_dir = os.path.join(cur_dir, 'data', 'dian') + policy_file = os.path.join(data_dir, 'politicadefirmav2.pdf') + with open(policy_file, 'rb') as f: + return f.read() + + mock.return_value = UrllibPolicyMock() + ctx.sign(signature) + ctx.verify(signature) + else: + ctx.sign(signature) + ctx.verify(signature) #xmlsig take parent root xml.remove(signature) return signature diff --git a/setup.py b/setup.py index a5b6098..317b478 100644 --- a/setup.py +++ b/setup.py @@ -18,6 +18,7 @@ requirements = ['Click>=6.0', 'pyOpenSSL>=19.1.0', 'xmlsig>=0.1.3', 'xades>=0.2.1', + 'mock==2.0.0', 'xmlsec>=1.3.8'] setup_requirements = ['pytest-runner', ] @@ -52,7 +53,7 @@ setup( include_package_data=True, package_data = { # If any package contains *.txt or *.rst files, include them: - '': ['*.gc', '*.xsd'] + '': ['*.gc', '*.xsd', 'politicadefirmav2.pdf'] }, keywords='facho', name='facho',