I want to add a digital signature to a XML file, with the particularity that before signing the file I want to add xml comments inside the file and then sign in.
The signing part seems to be working fine. I.e. for different contents in my comments or file, I get different signatures. Furthermore, the canonalization attribute is showing properly and displaying explicitly that the signature includes the comments.
However, when veryfing the signature on the XML files, the content of the comments is ignored. I.e., if I change the content of the comments, the signature is asserted as valid in every case.
The point I do not understand, is how this is possible if the signature produces different values for different content in the comments.
What might be wrong?
My example files:
Original XML file:
<?xml version="1.0" encoding="utf-8"?>
<test>
<ThisIsATest></ThisIsATest>
</test>
Signed file with an example comment:
<?xml version="1.0" encoding="utf-8"?>
<test><!--Comment 1-->
<ThisIsATest></ThisIsATest>
<!--Comment 1-->
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>0XZNOavY/0SEZPoU1cBJZs+rAlo=</DigestValue></Reference></SignedInfo><SignatureValue>T9xYVBwbWX3qg4IfsB3XJkviTaOh0pmEJ4Acimf9PA5Y5eDQ+ML8cWXkRPj4pYaGPa13TuwXkc0OK2izen4Cajrg4IZJRW8bLAIEt19wf1F8bduEN02WW2GZVN65OwUqSDqkC4vqMQ07IsVKap0KQaiyOrguZEEtygmSDES1OdM=</SignatureValue><KeyInfo><KeyValue><RSAKeyValue><Modulus>yi0TzN4OQ+mhHSDTZLcZPMnzbSrF51T9yLnWpnkkA+zUyhN6vEHBPgTjDst7RWQNg3G74NR4a88EiBCGzUdEH0a61cyUgHLW1/0IpBIr37jyhwFkLNmogpCltwO5KXNFOuqfq+yXYupHMkgW0BMn7AZfqr3XpuQsjGu2SQUxvr0=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue></KeyInfo></Signature></test>
Signed file with a different example comment:
<?xml version="1.0" encoding="utf-8"?>
<test><!--Comment 2-->
<ThisIsATest></ThisIsATest>
<!--Comment 2-->
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>0XZNOavY/0SEZPoU1cBJZs+rAlo=</DigestValue></Reference></SignedInfo><SignatureValue>gnAIkBy2Bi6CaxT6mCPCMw97BboX6EZ2l5tTuSj9zbPIdznScjMMhuUIFYGnl2Q73Nmify3HX2PHCyONfk9aaBcoP2v0G754NiH5T86gkGqo1IaMJVE9zXhjv5mMI7qV+o0lqvBLnvrr1hooIdUt6OL4j3OXgVG0OzhChaOz8K8=</SignatureValue><KeyInfo><KeyValue><RSAKeyValue><Modulus>nvH+jxiGv3BCqW3yWgsEr+VGiDIOdCn11FwHsU6CDVVIkzufMpyLnOPZQ5nSV1lWRS2KDUCLdp2FlJKNnJPnD0O3WBcpTN7+q9XrSYvu7UihEL4T1dT0QoBhBoKOLj08y45ZJ02tKqOmsN0LlDCr/dGiidZywPbr4s5uPQCJxLM=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue></KeyInfo></Signature></test>
The part of my code where the comments are added and the file signed:
public XmlDocument SignXMLString2(string xmlStringToSign) {
var originalDocument = new XmlDocument { PreserveWhitespace = true };
originalDocument.LoadXml(xmlStringToSign);
string commentString = "Comment 1";
var documentElement = originalDocument.DocumentElement;
var commentElement1 = originalDocument.CreateComment(commentString);
var commentElement2 = originalDocument.CreateComment(commentString);
documentElement.PrependChild(commentElement1);
documentElement.AppendChild(commentElement2);
documentElement.AppendChild(originalDocument.CreateTextNode("\n"));
var transformEnveloped = new XmlDsigEnvelopedSignatureTransform();
var reference = new Reference { Uri = "" };
reference.AddTransform(transformEnveloped);
var xmldsig = new SignedXml(originalDocument);
xmldsig.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigCanonicalizationWithCommentsUrl;// tried different one's here
// xmldsig.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NWithCommentsTransformUrl;
// xmldsig.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigC14NWithCommentsTransformUrl;
xmldsig.AddReference(reference);
xmldsig.SigningKey = new RSACryptoServiceProvider();
xmldsig.KeyInfo = new KeyInfo();
xmldsig.KeyInfo.AddClause(new RSAKeyValue((RSA)xmldsig.SigningKey));
xmldsig.ComputeSignature();
XmlElement signature = xmldsig.GetXml();
XmlNode signatureNode = originalDocument.ImportNode(signature, true);
originalDocument.DocumentElement.AppendChild(signatureNode);
return originalDocument;
}
The part of my code where the signature is verified:
public bool Validate2(string pathSigned) {
string xmlString = File.ReadAllText(path: pathSigned, encoding: Encoding.UTF8);
var signedDocument = new XmlDocument { PreserveWhitespace = true };
signedDocument.LoadXml(xmlString);
var xmldsig = new SignedXml(signedDocument);
var signature = (XmlElement)signedDocument.GetElementsByTagName("Signature")[0];
xmldsig.LoadXml(signature);
Console.WriteLine("xmldsig.SignedInfo.CanonicalizationMethod=" + xmldsig.SignedInfo.CanonicalizationMethod);//This shows the proper canonicalization
bool result = xmldsig.CheckSignature();
return result;
}
You are using the URI: "". This is a same-document URI (See http://www.w3.org/TR/xmldsig-core/#sec-Same-Document). In this case, Comment nodes are removed (even before any canonicalization) and are not included in the signed part.
Hope this helps.