We are receiving signed xmls from third parties which are using java. Our .NET implementation validates correctly the signatures, except when the xml contain the character reference.
It looks like .NET removes that line break character somewhere in the process of c14n.
I have run some tests in c# with the next xml:
var xml = "<a>something \nsomething\r\n</a>";
Using the next code for c14n:
public static void c14n(string xml)
{
using (MemoryStream msIn = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
var t = new XmlDsigExcC14NTransform(false);
t.LoadInput(msIn);
var o = t.GetOutput() as MemoryStream;
var c14n = Encoding.UTF8.GetString((o as MemoryStream).ToArray());
Console.WriteLine(c14n);
}
}
will result in the next xml, which is accordingly to w3org specifications (each line ends with LF char):
<a>something
something
</a>
However, when using the next code to see what canonical form has the xml which is signed with SignedXml .NET class:
public static void SignXml(string xml)
{
var doc = new XmlDocument { PreserveWhitespace = true };
doc.LoadXml(xml);
var cspParams = new CspParameters { KeyContainerName = "XML_DSIG_RSA_KEY" };
var rsaKey = new RSACryptoServiceProvider(cspParams);
var signedXml = new SignedXml(doc);
signedXml.SigningKey = rsaKey;
var reference = new Reference { Uri = "" };
var env = new XmlDsigEnvelopedSignatureTransform();
var excC14NTransform = new XmlDsigExcC14NTransform(false);
reference.AddTransform(env);
reference.AddTransform(excC14NTransform);
reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
signedXml.AddReference(reference);
signedXml.ComputeSignature();
var c14n = Encoding.UTF8.GetString((excC14NTransform.GetOutput() as MemoryStream).ToArray());
Console.WriteLine(c14n);
}
will result in a different xml (each line ends with LF char), and we can see that the line break ( ) was removed:
<a>something
something
</a>
Is there a way of using SignedXml class so that the correct canonical form to be used? Could be the xml parsing (when creating XmlDocument) the cause of this issue?
I wonder if that's a bug in .NET, and whether there is a workaround for it.