bseddon / xml-signer

Provides signing and verification of XML documents including support for XAdES
BSD 3-Clause "New" or "Revised" License
19 stars 8 forks source link

What do I do if my xpath is returning false? #17

Open potatocode420 opened 5 months ago

potatocode420 commented 5 months ago

My transformation xpath (e.g. not(//ancestor-or-self::cac:Signature)) is returning a false value. Because of this, canonicalizeData method will also give me an empty string (but I still need this exact same transform value to be there).

I have checked the original xmlseclibs library and it doesn't do a loop. Would it be possible to start with a fresh copy of objData at the start of each foreach iteration, or would that ruin the whole purpose of the transforms since the xpath doesn't seem to be correct anyway?

bseddon commented 5 months ago

You will be able to see from the last changed dates in the repository it's not been update in some time so my response is going to be affected by that.

Things may have changed but three years ago xmlseclibs did not implement transformations well. Maybe that's why there's no loop? Based on the information provided it's not really possible to give much of an answer. Does the containing XPath element include a namespace for 'cac'?

potatocode420 commented 5 months ago

Yup, the XML looks something like this: https://[sdk.myinvois.hasil.gov.my/files/one-doc-signed.xml](https://sdk.myinvois.hasil.gov.my/files/one-doc-signed.xml)

potatocode420 commented 5 months ago

Update - I found that the xpath query actually is returning some namespaces. So now I will just try to figure out why the C14N method that is giving us an empty string.

update 2: No, xpath query was not returning anything.

bseddon commented 5 months ago

Good idea. On the way to work it occurred to me to me maybe the parameters passed to the C14N function are not right.

But you might check the element. Here is an example from the specification:

<Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
  <XPath xmlns:dsig="&dsig;">
    not(ancestor-or-self::dsig:Signature)
  </XPath>
</Transform>

You can see the element is being passed the namespace of the element to exclude. Your example does not include a definition for the 'cac' namespace.

<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
  <ds:XPath>not(//ancestor-or-self::ext:UBLExtensions)</ds:XPath>
</ds:Transform>

If the C14N function is not passed the namespace for 'cac' it will not be able to find the elements. Maybe this will have an effect?

I do not have any experience using a signature that is in a namespace that is not 'http://www.w3.org/2000/09/xmldsig#'. It maybe the code expects to use the DSig namespace not the cac namespace.

potatocode420 commented 5 months ago

The namespace is there because I tried to change the xpath to (ancestor-or-self::cac:Signature) and it worked. Something seems to be up with this "not" in XPath here - it can't select anything even in XPath testers. I believe this is the reason why the C14N method wasn't able to detect the path. As a result the document also probably has not been canonicalized at all.

If it turns out that the XPath is really screwed, I might consider a workaround where I manually canonicalize and append transform nodes.

Thanks for the help!