我们正在从使用 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字符结尾),我们可以看到换行符( )被删除:
<a>something
something
</a>
有没有办法使用 SignedXml 类以便使用正确的规范形式?可能是 xml 解析(创建 XmlDocument 时)导致此问题?
我想知道这是否是 .NET 中的一个错误,以及是否有解决方法。
我会称其为错误,因为https://www.w3.org/TR/xml-c14n11/ 描述了要做什么,第二个顶部位置是:
Line breaks normalized to #xA on input, before parsing
我认为 应该成为 ,但是 XmlDsigExcC14NTransform 是什么? 在这里我们得到
\n
在这里您还可以找到详细说明: https://www.di-mgt.com.au/xmldsig-c14n.html
我们改变 到 在我们使用 XmlDsigExcC14NTransform 之前,没有更多问题。至少有我们的内容。