se cambian parametros a DianXMLExtensionSigner
facho/cli.py: generate permite firmar directamente FossilOrigin-Name: 23efe2dc5ae9df524963c927c5b461882f864008efbf25fd8677772ac8431cb1
This commit is contained in:
		@@ -228,8 +228,9 @@ def sign_xml(private_key, passphrase, xmlfile, ssl=True):
 | 
				
			|||||||
@click.option('--generate/--validate', default=False)
 | 
					@click.option('--generate/--validate', default=False)
 | 
				
			||||||
@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.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):
 | 
					def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=True, sign=False):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    imprime xml en pantalla.
 | 
					    imprime xml en pantalla.
 | 
				
			||||||
    SCRIPTNAME espera 
 | 
					    SCRIPTNAME espera 
 | 
				
			||||||
@@ -263,6 +264,10 @@ def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=Tr
 | 
				
			|||||||
        for extension in extensions:
 | 
					        for extension in extensions:
 | 
				
			||||||
            xml.add_extension(extension)
 | 
					            xml.add_extension(extension)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if sign:
 | 
				
			||||||
 | 
					            signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase)
 | 
				
			||||||
 | 
					            xml.add_extension(signer)
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
        print(xml.tostring(xml_declaration=True))
 | 
					        print(xml.tostring(xml_declaration=True))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
# this repository contains the full copyright notices and license terms.
 | 
					# this repository contains the full copyright notices and license terms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ..facho import FachoXML, FachoXMLExtension, LXMLBuilder
 | 
					from ..facho import FachoXML, FachoXMLExtension, LXMLBuilder
 | 
				
			||||||
 | 
					import uuid
 | 
				
			||||||
import xmlsig
 | 
					import xmlsig
 | 
				
			||||||
import xades
 | 
					import xades
 | 
				
			||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
@@ -178,7 +179,7 @@ class DianXMLExtensionSoftwareSecurityCode(FachoXMLExtension):
 | 
				
			|||||||
class DianXMLExtensionSigner(FachoXMLExtension):
 | 
					class DianXMLExtensionSigner(FachoXMLExtension):
 | 
				
			||||||
    # RESOLUCION 0001: pagina 516
 | 
					    # RESOLUCION 0001: pagina 516
 | 
				
			||||||
    POLICY_ID = 'https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf'
 | 
					    POLICY_ID = 'https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf'
 | 
				
			||||||
    POLICY_NAME = 'Dian'
 | 
					    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):
 | 
				
			||||||
        self._pkcs12_path = pkcs12_path
 | 
					        self._pkcs12_path = pkcs12_path
 | 
				
			||||||
@@ -192,20 +193,34 @@ class DianXMLExtensionSigner(FachoXMLExtension):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def sign_xml_string(self, document):
 | 
					    def sign_xml_string(self, document):
 | 
				
			||||||
        xml = LXMLBuilder.from_string(document)
 | 
					        xml = LXMLBuilder.from_string(document)
 | 
				
			||||||
 | 
					        signature = self.sign_xml_element(xml)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fachoxml = FachoXML(xml,nsmap=NAMESPACES)
 | 
				
			||||||
 | 
					        #DIAN 1.7.-2020: FAB01
 | 
				
			||||||
 | 
					        ublextension = fachoxml.fragment('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension', append=True)
 | 
				
			||||||
 | 
					        extcontent = ublextension.find_or_create_element('/ext:UBLExtension/ext:ExtensionContent')
 | 
				
			||||||
 | 
					        fachoxml.append_element(extcontent, signature)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return fachoxml.tostring()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def sign_xml_element(self, xml):
 | 
				
			||||||
        signature = xmlsig.template.create(
 | 
					        signature = xmlsig.template.create(
 | 
				
			||||||
            xmlsig.constants.TransformInclC14N,
 | 
					            xmlsig.constants.TransformInclC14N,
 | 
				
			||||||
            xmlsig.constants.TransformRsaSha256,
 | 
					            xmlsig.constants.TransformRsaSha256,
 | 
				
			||||||
            "Signature",
 | 
					            "Signature",
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					        id_uuid = str(uuid.uuid4())
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        ref = xmlsig.template.add_reference(
 | 
					        ref = xmlsig.template.add_reference(
 | 
				
			||||||
            signature, xmlsig.constants.TransformSha256, uri="", name="R1"
 | 
					            signature, xmlsig.constants.TransformSha256, uri="", name="xmldsig-%s-ref0" % (id_uuid)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        xmlsig.template.add_transform(ref, xmlsig.constants.TransformEnveloped)
 | 
					        xmlsig.template.add_transform(ref, xmlsig.constants.TransformEnveloped)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        id_keyinfo = "%s-KeyInfo" % (id_uuid)
 | 
				
			||||||
        xmlsig.template.add_reference(
 | 
					        xmlsig.template.add_reference(
 | 
				
			||||||
            signature, xmlsig.constants.TransformSha256, uri="#KI", name="RKI"
 | 
					            signature, xmlsig.constants.TransformSha256, uri="#%s" % (id_keyinfo),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        ki = xmlsig.template.ensure_key_info(signature, name="KI")
 | 
					        ki = xmlsig.template.ensure_key_info(signature, name=id_keyinfo)
 | 
				
			||||||
        data = xmlsig.template.add_x509_data(ki)
 | 
					        data = xmlsig.template.add_x509_data(ki)
 | 
				
			||||||
        xmlsig.template.x509_data_add_certificate(data)
 | 
					        xmlsig.template.x509_data_add_certificate(data)
 | 
				
			||||||
        serial = xmlsig.template.x509_data_add_issuer_serial(data)
 | 
					        serial = xmlsig.template.x509_data_add_issuer_serial(data)
 | 
				
			||||||
@@ -216,12 +231,20 @@ class DianXMLExtensionSigner(FachoXMLExtension):
 | 
				
			|||||||
        xmlsig.template.add_key_value(ki)
 | 
					        xmlsig.template.add_key_value(ki)
 | 
				
			||||||
        qualifying = xades.template.create_qualifying_properties(signature)
 | 
					        qualifying = xades.template.create_qualifying_properties(signature)
 | 
				
			||||||
        xades.utils.ensure_id(qualifying)
 | 
					        xades.utils.ensure_id(qualifying)
 | 
				
			||||||
        xades.utils.ensure_id(qualifying)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # TODO assert with http://www.sic.gov.co/hora-legal-colombiana
 | 
					        # TODO assert with http://www.sic.gov.co/hora-legal-colombiana
 | 
				
			||||||
 | 
					        id_props = "xmldsig-%s-signedprops" % (id_uuid)
 | 
				
			||||||
        props = xades.template.create_signed_properties(qualifying, datetime=datetime.now())
 | 
					        props = xades.template.create_signed_properties(qualifying, datetime=datetime.now())
 | 
				
			||||||
 | 
					        props.set('Id', id_props)
 | 
				
			||||||
        xades.template.add_claimed_role(props, "supplier")
 | 
					        xades.template.add_claimed_role(props, "supplier")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        props_ref = xmlsig.template.add_reference(
 | 
				
			||||||
 | 
					            props, xmlsig.constants.TransformSha256, uri="#%s" % (id_props),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        props_ref.set('Type', "http://uri.etsi.org/01903#SignedProperties")        
 | 
				
			||||||
 | 
					        xmlsig.template.add_transform(props_ref, xmlsig.constants.TransformEnveloped)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        xml.append(signature)
 | 
					        xml.append(signature)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        policy = xades.policy.GenericPolicyId(
 | 
					        policy = xades.policy.GenericPolicyId(
 | 
				
			||||||
@@ -236,20 +259,15 @@ class DianXMLExtensionSigner(FachoXMLExtension):
 | 
				
			|||||||
        ctx.verify(signature)
 | 
					        ctx.verify(signature)
 | 
				
			||||||
        #xmlsig take parent root
 | 
					        #xmlsig take parent root
 | 
				
			||||||
        xml.remove(signature)
 | 
					        xml.remove(signature)
 | 
				
			||||||
 | 
					        return signature
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fachoxml = FachoXML(xml,nsmap=NAMESPACES)
 | 
					    # return (xpath, xml.Element)
 | 
				
			||||||
 | 
					    def build(self, fachoxml):
 | 
				
			||||||
 | 
					        signature = self.sign_xml_element(fachoxml.root)
 | 
				
			||||||
        #DIAN 1.7.-2020: FAB01
 | 
					        #DIAN 1.7.-2020: FAB01
 | 
				
			||||||
        ublextension = fachoxml.fragment('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension', append=True)
 | 
					        ublextension = fachoxml.fragment('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension', append=True)
 | 
				
			||||||
        extcontent = ublextension.find_or_create_element('/ext:UBLExtension/ext:ExtensionContent')
 | 
					        extcontent = ublextension.find_or_create_element('/ext:UBLExtension/ext:ExtensionContent')
 | 
				
			||||||
        fachoxml.append_element(extcontent, signature)
 | 
					        fachoxml.append_element(extcontent, signature)
 | 
				
			||||||
        return fachoxml.tostring()
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
    # return (xpath, xml.Element)
 | 
					 | 
				
			||||||
    def build(self, fachoxml):
 | 
					 | 
				
			||||||
        xmlsigned = self.sign_xml_string(fachoxml.tostring())
 | 
					 | 
				
			||||||
        xml = LXMLBuilder.from_string(xmlsigned)
 | 
					 | 
				
			||||||
        fachoxml.root = xml
 | 
					 | 
				
			||||||
        return fachoxml
 | 
					 | 
				
			||||||
     
 | 
					     
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DianXMLExtensionAuthorizationProvider(FachoXMLExtension):
 | 
					class DianXMLExtensionAuthorizationProvider(FachoXMLExtension):
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user