EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Sign XML node correctly

Also by EldoS: Rethync
The cross-platform framework that simplifies synchronizing data between mobile and desktop applications and servers and cloud storages
#13326
Posted: 05/14/2010 16:46:09
by Robertas  (Basic support level)
Joined: 05/14/2010
Posts: 2

I tried to sign an xml node with SecureBlackbox, but the hashes generated in
Code
<DigestValue>base64code</DigestValue>
are different (I compared them with third party signer).
This is an example of xml I want to sign:
Code
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<metadata ID="Metadata_0" xmlns="bla">
<document ID="Document_1">
<title>bla</title>
</document>
<authors ID="Authors_0">
<author ID="Author_0">
<name>bla</name>
<no>12345678901</no>
<address>bla</address>
<individual>true</individual>
</author>
</authors>
</metadata>

I want to sign a node: 'Document_1'. To select this node I am using this XPath query:
Code
ancestor-or-self::*[@ID='Document_1']

This is my code for adding reference to the reference list:
Code
TElXMLReferenceList references = new TElXMLReferenceList();

TElXMLXPathTransform transformXPath = new TElXMLXPathTransform();
transformXPath.XPath = xpathTransform; // ancestor-or-self::*[@ID='Document_1']

TElXMLC14NTransform transformCanonicalization = new TElXMLC14NTransform();
transformCanonicalization.CanonicalizationMethod = SBXMLDefs.Unit.xcmCanon;

TElXMLReference ref1 = new TElXMLReference();
ref1.URI = uri; // uri of the xml file above without #somenode e.g folder/filename.xml
ref1.TransformChain.Add(transformXPath);
ref1.TransformChain.Add(transformCanonicalization);
ref1.URIData = content; // content is aforementioned xml file in bytes
// Everything is the same when I assign xml document node to ref1.URINode.
ref1.DigestMethod = SBXMLSec.Unit.xdmSHA1;
ref1.UpdateDigestValue();
references.Add(ref1);

I assign the reference list to TElXMLSigner's property References after all references are added.
I want it to look like this in my signature xml file after signature is generated:
Code
<Reference URI="metadata/SignableMetadata0.xml">
<Transforms>
<Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
<XPath>ancestor-or-self::*[@ID='Document_1']</XPath>
</Transform>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>ogrDLsxLvNQ4OoPUeYIMn3VixA8=</DigestValue>
</Reference>


Results:
I get the following when I assign the array of bytes of the XML file. And the same when I assign the XML file to ref1.URINode.
Code
<Reference URI="metadata/SignableMetadata0.xml">
  <Transforms>
    <Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
    <XPath>ancestor-or-self::*[@ID='Document_1']</XPath>
    </Transform>
    <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
  </Transforms>
  <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
  <DigestValue>/sOP2jQglFqJPc9pk+wOIpFro/8=</DigestValue>
</Reference>

And this is what I get when I use third party signer with the same XML file
Code
<Reference URI="metadata/SignableMetadata0.xml">
  <Transforms>
    <Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
    <XPath>ancestor-or-self::*[@ID='Document_1']</XPath>
    </Transform>
    <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
  </Transforms>
  <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
  <DigestValue>ogrDLsxLvNQ4OoPUeYIMn3VixA8=</DigestValue>
</Reference>

I even tried to assign ref1.DigestValue manually, but in the resulting XML it was stil wrong.

When I try to verify signature, it says that data was altered.

Everything works fine for any file except when I want to sign an XML node.
What I am doing wrong? Could you post me the right way to sign an XML node? I prefer C# syntax.
#13327
Posted: 05/15/2010 06:30:48
by Dmytro Bogatskyy (EldoS Corp.)

The XPath query and XPath transform are a different things. The XPath in the XPath transform is used as a node test.
It is evaluated in the following way:
Quote

1. Initialize an XPath evaluation context by setting the initial node equal to the input XML document's root node, and set the context position and size to 1.
2. Evaluate the XPath expression (//. | //@* | //namespace::*)

So, the final XPath expression will look like: "(//. | //@* | //namespace::*)[XXX]"
Where XXX is your query "ancestor-or-self::*[@ID='Document_1']".
So it will select all elements in this xml document, and on verification it would select a newly created Signature element, so that's why verification would fail.

Try to set XPath to something like this:
count(ancestor-or-self::*[local-name() = 'document']) > 0

Quote
I even tried to assign ref1.DigestValue manually, but in the resulting XML it was stil wrong.

If you set DigestValue manually, then you shouldn't call UpdateDigestValue method.
#13335
Posted: 05/16/2010 17:56:53
by Robertas  (Basic support level)
Joined: 05/14/2010
Posts: 2

Thank you for your quick response. I have revised my code and found one flaw. With manually setting DigestValue it works fine now. Albeit I did not call method UpdateDigestValue in my AddReference() method, but I called UpdateReferencesDigest() in my Sign() method. This was my mistake.
But still I would like to know how to assign XPath transform correctly. Could you give me more detailed explanation how to create an XPath transformation?

Does my way of assigning XPath transform is wrong? I did not understand how it should look. Now I am doing this as follows:
Code
string xpathQuery = "ancestor-or-self::*[@ID='Document_1']";
TElXMLXPathTransform transformXPath = new TElXMLXPathTransform();
transformXPath.XPath = xpathQuery;

Do I need to set anything else here? I set such (ancestor-or-self::*[@ID='Document_1']) XPath expression because I want to be exactly like this in the signature.xml file under the <Transform ...><XPath> tag. This is an example how the resulting xml's part should look like:
Code
<Reference URI="metadata/SignableMetadata0.xml">
<Transforms>
<Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
<XPath>ancestor-or-self::*[@ID='Document_1']</XPath>
</Transform>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>ogrDLsxLvNQ4OoPUeYIMn3VixA8=</DigestValue>
</Reference>

If I set TElXMLXPathTransform's XPath property to: "(//.)[ancestor-or-self::*[@ID='Document_1']]" in the signature.xml I get this:
Code
<Reference URI="metadata/SignableMetadata0.xml">
  <Transforms>
    <Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
      <XPath>(//.)[ancestor-or-self::*[@ID='Document_1']]</XPath>
    </Transform>
    <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
  </Transforms>
  <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
  <DigestValue>cQtb6sm24ZB5i1/g/VO1KnpWJP0=</DigestValue>
</Reference>

And also the DigestValue is not right. The correct result should be:
Code
<Reference URI="metadata/SignableMetadata0.xml">
  <Transforms>
    <Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
      <XPath>ancestor-or-self::*[@ID='Document_1']</XPath>
    </Transform>
    <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
  </Transforms>
  <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
  <DigestValue>ogrDLsxLvNQ4OoPUeYIMn3VixA8=</DigestValue>
</Reference>


Respectfully,
Robertas
#13341
Posted: 05/17/2010 11:39:18
by Dmytro Bogatskyy (EldoS Corp.)

I revised this. Your XPath expression should be correct, but there is a bug in XPath engine in attribute comparison, it invalidly select some nodes.
This is fixed for the next build.
Thank you for pointing this.

Reply

Statistics

Topic viewed 2021 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!