[Python] How do I insert several digitally signed XML contents inside another XML without...

Discussão em 'Python' iniciado por Stack, Fevereiro 10, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to send a signed XML file (an event) to a webservice, but when I insert the signed event into a XML batch file, the signature is invalidated. I'm using Python with signxml module (method enveloped) to sign the event file XML, but after insertion, the event XML signed within the batch generates an “invalid asymmetric cipher” error in the validation.

    Does anyone know the best way to ensure that the event signature remains valid after insertion into the batch XML?

    I sign the event XML using signxml with the enveloped method and insert the signed event XML inside a batch XML containing other events:

    from lxml import etree
    from signxml import XMLSigner, methods
    from cryptography.hazmat.primitives.serialization import pkcs12

    # Extract PK and Cert
    private_key, cert, _ = pkcs12.load_key_and_certificates(pfx_data, cert_password)

    # Load XML
    xml_str = '''
    <Reinf xmlns="http://www.reinf.esocial.gov.br/schemas/evt4020PagtoBeneficiarioPJ/v2_01_02">
    <EvtPJ id="ID123">
    <cnpj>123456789</cnpj>
    </EvtPJ>
    </Reinf>
    '''
    root = etree.fromstring(xml_str)

    # Configure XMLSigner
    signer = XMLSigner(method=methods.enveloped, signature_algorithm="rsa-sha256", digest_algorithm="sha256")

    # Sign XML (referencing the ID from the tag EvtPJ)
    signed_root = signer.sign(root, key=private_key, cert=[cert], reference_uri="#ID123")

    # load batch XML
    main_xml_str = '''
    <Reinf xmlns="http://www.reinf.esocial.gov.br/schemas/envioLoteEventosAssincrono/v1_00_00">
    <lote>
    <eventos>
    <evento id="ID123">
    </evento>
    </eventos>
    </lote>
    </Reinf>
    '''
    main_root = etree.fromstring(main_xml_str)

    # Find tag <evento> that matches the ID
    evento_element = main_root.find(".//{http://www.reinf.esocial.gov.br/schemas/envioLoteEventosAssincrono/v1_00_00}evento[@id='ID123']")

    if evento_element is not None:
    # Insert signed XML into tag <evento>
    evento_element.append(signed_root)
    else:
    print("ID from <evento> Element not found")

    # Convert the signed xml to formatted string
    final_xml = etree.tostring(main_root, pretty_print=False, xml_declaration=False, encoding="utf-8")

    # Save the final XML into a file
    with open("xml_final.xml", "wb") as file:
    file.write(final_xml)


    Signed batch XML output:

    <Reinf xmlns="http://www.reinf.esocial.gov.br/schemas/envioLoteEventosAssincrono/v1_00_00">
    <lote>
    <eventos>
    <evento id="ID123">
    <Reinf xmlns="http://www.reinf.esocial.gov.br/schemas/evt4020PagtoBeneficiarioPJ/v2_01_02">
    <EvtPJ id="ID123">
    <cnpj>123456789</cnpj>
    </EvtPJ>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="[...]"/><ds:SignatureMethod Algorithm="[...]"/><ds:Reference URI="#ID123"><ds:Transforms><ds:Transform Algorithm="[...]"/><ds:Transform Algorithm="[...]"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>[...]</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>[...]</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>[...]
    </ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></Reinf></evento>
    </eventos>
    </lote>
    </Reinf>


    I want the same output, but with a valid signature.

    Continue reading...

Compartilhe esta Página