Reputation: 11
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.
Upvotes: 1
Views: 47