我们正在从使用 java 的第三方接收签名的 xml。我们的 .NET 实现正确验证签名,除非 xml 包含 字符参考。
看起来 .NET 在 c14n 过程中的某处删除了换行符。
我在 c# 中使用下一个 xml 运行了一些测试:
var xml = "<a>something \nsomething\r\n</a>";
使用 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);
}
}
将产生下一个 xml,它符合w3org规范(每行以 LF 字符结尾):
<a>something
something
</a>
但是,当使用下一个代码查看哪个规范表单具有使用 SignedXml .NET 类签名的 xml 时:
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);
}
将产生不同的 xml(每行以 LF char 结尾),我们可以看到换行符 ( ) 已被删除:
<a>something
something
</a>
有没有办法使用 SignedXml 类以便使用正确的规范形式?xml 解析(创建 XmlDocument 时)可能是导致此问题的原因吗?
我想知道这是否是 .NET 中的错误,以及是否有解决方法。