Search code examples
xmlxml-signaturezeepxmlsec

Signed payload is not valid when using signxml but xmlsec one is valid


Could you help me to find out why the two libraries (signxml and xmlsec) do not sign the same. The signature accepted by the server is xmlsec.

Code sign signxml:

signer = XMLSigner(
    method=methods.enveloped,
    signature_algorithm="rsa-sha1",
    digest_algorithm='sha1',
    c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
ns = {}
ns[None] = signer.namespaces['ds']
signer.namespaces = ns

signed_root = signer.sign(xml_element, key=self.chave, cert=self.certificado, reference_uri=None)

But the signed payload is not correct, ending up with either signature verification failed error/getting error message to check for the signature. When I used the xmlsec, it is generating in a proper way. But I have to use signxml as it does not have platform dependencies. Attached both the xml output files here.

https://github.com/XML-Security/signxml/files/6207744/signs.zip

And the payload here payload.txt

I see the Issuer details tag is missing in signxml generated output document and there are two Reference URI and digest method and value in xmlsec generated output but seeing only one on the signxml. How can I make the signxml to generate and verify the signature and able to successfully make SOA API invocation?

XMLSec code: Ref https://github.com/orcasgit/py-wsse/blob/ff4fea90687606af31d4b31cbdb3e753154299a4/wsse/signing.py#L19

wsse = signing.sign(envelope=envelope, keyfile=key_path, certfile=cert_path)
signing.verify(envelope=wsse.decode(), certfile=cert_path)

I would appreciate any help on this from anyone.


Solution

  • Finally, I'm able to generate the XML signature that is being verified by signxml.XMLVerifier() using this. Earlier could not verify the signature generated but this did the trick lxml.etree.tostring(signed_root) Thanks for the awesome post: https://technotes.shemyak.com/posts/xml-signatures-with-python-elementtree/. Payload with signature able to get the response from the remote server as well.

    import lxml
    import signxml
    from xml.etree import ElementTree
    
    key = open("key.pem").read()
    cert = open("cert.pem").read()
    
    root = ElementTree.fromstring(payload, parser=lxml.etree.XMLParser())
    
    signed_root = signxml.XMLSigner(method=signxml.methods.enveloped).sign(root, key=key, cert=cert)
    data_serialized = lxml.etree.tostring(signed_root)
    
    # Now able to verify this
    signxml.XMLVerifier().verify(data_serialized, x509_cert=cert)
    
    #To get the signed XML
    print(data_serialized.decode())