facho/cli.py: nuevo atribute --use-cache-policy para firmar

FossilOrigin-Name: 7126044e6cfb596ad025ed1b18d6dc951a358d56d6d9778b3223f3b8a9ce2bc8
This commit is contained in:
bit4bit@riseup.net 2020-09-20 01:43:48 +00:00
parent a917258cee
commit e369ad2069
4 changed files with 32 additions and 9 deletions

View File

@ -213,13 +213,17 @@ def validate_invoice(invoice_path):
@click.option('--private-key', type=click.Path(exists=True)) @click.option('--private-key', type=click.Path(exists=True))
@click.option('--passphrase') @click.option('--passphrase')
@click.option('--ssl/--no-ssl', default=False) @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) @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: if not ssl:
disable_ssl() disable_ssl()
from facho import fe 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') document = open(xmlfile, 'r').read().encode('utf-8')
print(signer.sign_xml_string(document)) print(signer.sign_xml_string(document))
@ -229,8 +233,9 @@ def sign_xml(private_key, passphrase, xmlfile, ssl=True):
@click.option('--passphrase') @click.option('--passphrase')
@click.option('--ssl/--no-ssl', default=False) @click.option('--ssl/--no-ssl', default=False)
@click.option('--sign/--no-sign', 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) @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. imprime xml en pantalla.
SCRIPTNAME espera SCRIPTNAME espera
@ -265,7 +270,7 @@ def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=Tr
xml.add_extension(extension) xml.add_extension(extension)
if sign: if sign:
signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase) signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase, mockpolicy=use_cache_policy)
xml.add_extension(signer) xml.add_extension(signer)
print(xml.tostring(xml_declaration=True)) print(xml.tostring(xml_declaration=True))

Binary file not shown.

View File

@ -181,9 +181,10 @@ class DianXMLExtensionSigner(FachoXMLExtension):
POLICY_ID = 'https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf' 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.' 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._pkcs12_path = pkcs12_path
self._passphrase = None self._passphrase = None
self._mockpolicy = mockpolicy
if passphrase: if passphrase:
self._passphrase = passphrase.encode('utf-8') self._passphrase = passphrase.encode('utf-8')
@ -216,7 +217,7 @@ class DianXMLExtensionSigner(FachoXMLExtension):
) )
xmlsig.template.add_transform(ref, xmlsig.constants.TransformEnveloped) 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( xmlsig.template.add_reference(
signature, xmlsig.constants.TransformSha256, uri="#%s" % (id_keyinfo), signature, xmlsig.constants.TransformSha256, uri="#%s" % (id_keyinfo),
) )
@ -255,6 +256,22 @@ class DianXMLExtensionSigner(FachoXMLExtension):
ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(open(self._pkcs12_path, 'rb').read(), ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(open(self._pkcs12_path, 'rb').read(),
self._passphrase)) self._passphrase))
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.sign(signature)
ctx.verify(signature) ctx.verify(signature)
#xmlsig take parent root #xmlsig take parent root

View File

@ -18,6 +18,7 @@ requirements = ['Click>=6.0',
'pyOpenSSL>=19.1.0', 'pyOpenSSL>=19.1.0',
'xmlsig>=0.1.3', 'xmlsig>=0.1.3',
'xades>=0.2.1', 'xades>=0.2.1',
'mock==2.0.0',
'xmlsec>=1.3.8'] 'xmlsec>=1.3.8']
setup_requirements = ['pytest-runner', ] setup_requirements = ['pytest-runner', ]
@ -52,7 +53,7 @@ setup(
include_package_data=True, include_package_data=True,
package_data = { package_data = {
# If any package contains *.txt or *.rst files, include them: # If any package contains *.txt or *.rst files, include them:
'': ['*.gc', '*.xsd'] '': ['*.gc', '*.xsd', 'politicadefirmav2.pdf']
}, },
keywords='facho', keywords='facho',
name='facho', name='facho',