EldoS | Feel safer!

Software components for data protection, secure storage and transfer

About signing an XML

Also by EldoS: RawDisk
Access locked and protected files in Windows, read and write disks and partitions and more.
#12566
Posted: 02/23/2010 11:00:20
by Roland . (Basic support level)
Joined: 02/07/2010
Posts: 7

Hi,

I'm working on an application that signs an XML using ElXMLSigner, in Delphi.
I've configured the XML signer and it signs my XML. First there where some problems but now I seem to have the structure right, and it (the webservice) will accept my XML with the signature. But it then tells me (in the reply) that my signature is incorrect. Since the structure and everything is OK, there is no more error information as you would expect from XML signing and validating.

Looking around what options I might have missed etc, I came accross the ElXMLKeyInfoData type, which you can find in ElXMLSigner.KeyData. I fill it with a KeyInfoX509Data object, in which I put my X509 certificate (from a .pfx).
But the base class ElXMLKeyInfoData has a Reference field/property. However I cannot seem to find in Delphi, it is not defined in the sources. But here it is in the documentation:
[URL=http://www.eldos.com/documentation/sbb/documentation/ref_cl_xmlkeyinfodata.html]http://www.eldos.com/documentation/sbb/documentation/ref_cl_xmlkeyinfodata.html[/URL]

Why can't I find it and is it necessary to make the XML signing better? I am using a reference already, as it needs to sign one particulair node.
I am just looking for options why my signature won't be accepted.

Thanks in advance.
#12567
Posted: 02/23/2010 11:11:58
by Eugene Mayevski (EldoS Corp.)

Please assign the license ticket to your user account before we provide further support to you.


Sincerely yours
Eugene Mayevski
#12568
Posted: 02/23/2010 11:18:32
by Michael van Heusden (Standard support level)
Joined: 02/23/2010
Posts: 10

Ah yes, you pointed that out earlier, my apolegies. This is the correct account, with the license already assigned to it.
The confusion was caused because I am working for the one who purchased the components for me to work with and complete the webservice tasks, so I did not purchase them myself. And created my own account, without the right information for your support system.
#12569
Posted: 02/23/2010 12:38:53
by Dmytro Bogatskyy (EldoS Corp.)

Quote
I've configured the XML signer and it signs my XML. First there where some problems but now I seem to have the structure right, and it (the webservice) will accept my XML with the signature. But it then tells me (in the reply) that my signature is incorrect. Since the structure and everything is OK, there is no more error information as you would expect from XML signing and validating.

If your resulting xml document validates ok by XMLBlackbox\Signer sample?
Could you please attach (here or to helpdesk) this document and any xml sample that validates ok with this webservice.
Quote
Looking around what options I might have missed etc, I came accross the ElXMLKeyInfoData type, which you can find in ElXMLSigner.KeyData. I fill it with a KeyInfoX509Data object, in which I put my X509 certificate (from a .pfx).
But the base class ElXMLKeyInfoData has a Reference field/property. However I cannot seem to find in Delphi, it is not defined in the sources. But here it is in the documentation:
http://www.eldos.com/documentation/sb...odata.html

Sorry for misleading. This option was added (simple support), but lately was removed (commented), as nobody use or require it.
Will fix documentation, thank you for pointing this.
#12570
Posted: 02/23/2010 13:15:22
by Michael van Heusden (Standard support level)
Joined: 02/23/2010
Posts: 10

Ok, I was afraid of that, that it was depricated.

I was going to work on validating anyway, and then it's easy to validate my own generated xml. I will get back on that.

Here is a good, working example:

Code
<Signature>
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#Leerdossier">
<Transforms>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>0t6qwwn03SzbFQe32AxcIfZNgwQ=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
kotnNRKcS6WHezz7DPB12d2HsLfFrQzRvi9dNUO1BJF95Ro5ZtKW5jPdW+0s3mStYWCjrK1dKlyDmdVq3R2ijsle+xNb7eyIe5iWBafhdSqn63HvXmJNKyRQe+bVGU5wYhv2XRp8FCuNnXPoKynEZtKklU1LJVMFvccfUl5wKIY=
</SignatureValue>
<KeyInfo>
<KeyValue>
<RSAKeyValue>
<Modulus>
x964m+5go0Cr6k5aoe9Fx4nkkTVrkZg57eBq0D4PMhToUA9lPdf2ST8YnxIhwaQgmis+Exk094sYCvXKIa3ZzIbRzEb7Chp7bvKm00vq6DaiV+zqMXc/48LM2sG42fQZnnxTq3BkSkyt/4Q83Y7r0CuiAuriONWTpkWlFnW8AIc=
</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
</Signature>


This is a generated example, by me:

Code
<Signature>
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#Leerdossier">
<Transforms>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>AjEVFHxb33zObf9zjAHi5QR6PRs=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
ajpn...IFgX/KqUtCzHX6HYnj0BEbng2DhMv9xRQpvLI4X/7nJoyShg++0a22Wr8E+ycG4Ai0OPVYZjk+E5otRdgYGNqSNws=
</SignatureValue>
<KeyInfo>
<KeyValue>
<RSAKeyValue>
<Modulus>
t2h7zxhkj3HiCU6DmVloqJ6eczL7yLbdro1A33VZL2MKgxbZQcU9/HQHv...Iq1k+vqLX4IBLEn0l5vaXF9E=
</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
<X509Data/>
</KeyInfo>
</Signature>


Note: I removed the <X509Data /> element. It makes no difference if it's there or if it's missing, however when I set IncludeDataParams to empty, the resulting <X509Data /> is not accepted. So if it's there it has to have a certain structure. But as I said, it works either way and will therefore likely not cause any problems. It reports structure errors as they are, not via an incorrect signature of course.

The above sample, A, is made by someone else with different XML content and a different personal certificate and key. So ofcourse the calculated content is different. But as you see, the structure seems to be identical.

I'm now thinking it has something to do with the fact that I put in the signature. I load everything in a Eldos XML document, then I construct a reference with all the right details, pointing it to right XML node from the document.
However, I don't let the signature be put in the document automatically. I tell it to save to another particulair node (an envelope header) so it's in the place that is needed.
Afterwards, I let the XML document save it's content to a TStringStream. I then return the StringStream.DataString property as a result of the sign function. Then I post the string as a 'body' parameter in a HTTP(S) POST operation. (which I do with the Eldos HTTPSClient from the SSL box)

Perhaps there is a problem in how strings are treated? So the content is slightly different, because of spaces etc?
I noticed that the output of the XML document (saving it to the TStringStream) contains a few weird characters on the start. It always starts with "", which I have to remove myself if I want the webservice to accept my XML. Where does it come from? Al I do is:
Code
  lOutputStringStream := TStringStream.Create('');
  lXMLDoc.SaveToStream(lOutputStringStream);
  lTempResult := lOutputStringStream.DataString;


Maybe it is an indication something is wrong?

If you need more information, please let me know.
#12571
Posted: 02/23/2010 15:12:29
by Dmytro Bogatskyy (EldoS Corp.)

Quote
Note: I removed the <X509Data /> element. It makes no difference if it's there or if it's missing, however when I set IncludeDataParams to empty, the resulting <X509Data /> is not accepted. So if it's there it has to have a certain structure. But as I said, it works either way and will therefore likely not cause any problems. It reports structure errors as they are, not via an incorrect signature of course.

If you don't need X509Data, but include a RSAKeyValue, then you can use:
RSAKeyData: TElXMLKeyInfoRSAData; (not TElXMLKeyInfoX509Data)
and fill it:
Code
if Certificate.KeyMaterial is TElRSAKeyMaterial then
begin
RSAKeyData := TElXMLKeyInfoRSAData.Create(False);
RSAKeyData.RSAKeyMaterial.Assign(Certificate.KeyMaterial);
ElXMLSigner.KeyData := RSAKeyData;
end;

Quote
It always starts with "", which I have to remove myself if I want the webservice to accept my XML. Where does it come from? Al I do is: Code

lOutputStringStream := TStringStream.Create('');
lXMLDoc.SaveToStream(lOutputStringStream);
lTempResult := lOutputStringStream.DataString;

It is UTF8 BOM (Byte order mark), you can remove it using a following code:
Code
  var Codec : TElXMLCodec;
      Codec := TElXMLUTF8Codec.Create;
      try
        Codec.WriteBOM := False;
        XMLDocument.SaveToStream(Stream, xcmNone, Codec);
      finally
        FreeAndNil(Codec);
      end;

However, you can obtain xml data as a string (unicode string) using OuterXML property of TElXMLDOMNode class, for example:
s := XMLDocument.OuterXML;

I think you have a problem with whitespace characters (especially with CRLF), because you are using TStringStream (it may reconvert a file using system default encoding).
Please, also ensure that you load a document (before signing) with XMLDocument.LoadFromStream(Stream, '', True), the third parameter enables normalization of newline characters (removes CR character), because most of webservices ignore CR character on canonicalization or canonicalize it incorrectly.
Then obtain a string value using OuterXML property.
#12572
Posted: 02/23/2010 15:12:33
by Michael van Heusden (Standard support level)
Joined: 02/23/2010
Posts: 10

Edit: The following is posted at the same time as above comment. I will try your suggestions now.

Some more information. I am now validating the XML signature which should be wrong according to the webservice. Using the ElXMLVerifier I load the document and call the validate function, as described in your short tutorial. It returns True which is nice. But it returns True anyway, even if I change the content of the node which is signed, or I don't give the certificate (and when there is no X509Data element to get the certificate from). But it does seem to work, as it errors when I remove the signature information or put nonsense in there (so the structure is incorrect). And it does return "Invalid signature" when I change a letter in the signature.

Perhaps this is an indication. I can change the content of the node which is to be signed (and is named in the reference) but it won't effect if the signature is valid or not. So maybe it's not picking up my reference and it's signing something else?
#12573
Posted: 02/23/2010 15:17:54
by Dmytro Bogatskyy (EldoS Corp.)

Quote
Some more information. I am now validating the XML signature which should be wrong according to the webservice. Using the ElXMLVerifier I load the document and call the validate function, as described in your short tutorial. It returns True which is nice. But it returns True anyway, even if I change the content of the node which is signed, or I don't give the certificate (and when there is no X509Data element to get the certificate from).

What methods return true ValidateSignature or ValidateReference?
If it is ValidateSignature then it is ok, it checks the integrity of SignedInfo element. Then you should call ValidateReference to check the references that are stored in SignedInfo element.
The RSAKeyValue element contains enough information to verify a signature.
#12574
Posted: 02/23/2010 15:18:47
by Michael van Heusden (Standard support level)
Joined: 02/23/2010
Posts: 10

Ah thank you, I will try all your suggestions now.
#12575
Posted: 02/23/2010 15:39:17
by Michael van Heusden (Standard support level)
Joined: 02/23/2010
Posts: 10

The ValidateSignature was giving me True. I didn't read far enough, I forgot about the ValidateReference function. Now I implemented it, taking the only reference there is and settings it's URINode. It also return true. So the XMLVerifier validates the signature succesfully.

Still, your earlier posted suggestions concerning spaces and crlf's can still be useful. I will apply them now.

It might also be usefull to look at how I do the HTTPS Post, here only the relevant code:

Code
  lPostParams := TStringList.Create;
  lPostParams.Add('body=' + AXMLMessage );
  HTTPSClient.Post( cELDWebserviceURL, lPostParams );


(the XML is supposed to be given through the Post parameter named 'body')

But this shouldn't give me problems right?
Also by EldoS: BizCrypto
Components for BizTalk® and SQL Server® Integration Services that let you securely store and transfer information in your business automation solutions.

Reply

Statistics

Topic viewed 4786 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!