如何在 .NET 中使用 RSA 密钥对 XML 文件进行签名?
我正在尝试使用由 < 生成的私有 RSA 密钥在 C# .NET 3.5 中签署 XML 文件a href="http://en.wikipedia.org/wiki/OpenSSL" rel="noreferrer">OpenSSL。
我的操作步骤如下:我将 RSA 密钥从 PEM 格式转换为 XML 格式使用 chilkat 框架 (www.example-code.com/csharp/cert_usePrivateKeyFromPEM.asp)
通过我的 XML 密钥,我现在可以使用我更喜欢的本机 .NET 函数。所以我使用了 MSDN 上描述的方法。
所以,最后,我的源代码如下所示:
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
//Load the private key from xml file
XmlDocument xmlPrivateKey = new XmlDocument();
xmlPrivateKey.Load("PrivateKey.xml");
rsaProvider.FromXmlString(xmlPrivateKey.InnerXml);
// Create a SignedXml object.
SignedXml signedXml = new SignedXml(Doc);
// Add the key to the SignedXml document.
signedXml.SigningKey = Key;
// Create a reference to be signed.
Reference reference = new Reference();
reference.Uri = "";
// Add an enveloped transformation to the reference.
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
// Add the reference to the SignedXml object.
signedXml.AddReference(reference);
// Compute the signature.
signedXml.ComputeSignature();
// Get the XML representation of the signature and save
// it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Append the element to the XML document.
Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true));
使用此函数获得的签名 XML 看起来不错,我在文件末尾有 XML 元素,就像它应该的那样:
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<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="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>qoGPSbe4oR9e2XKN6MzP+7XlXYI=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>iPQ6IET400CXfchWJcP22p2gK6RpEc9mkSgfoA94fL5UM6+AB5+IO6BbjsNt31q6MB8hR6lAIcnjzHzc5SeXvFP8Py2bqHTYJvcSA6KcKCQl1LiDNt12UwWiKpSkus2p0LdAeeZJNy9aDxjC/blUaZEr4uPFt0kGCD7h1NQM2SY=</SignatureValue>
问题是,当我尝试在以下 URL 处使用 xmlsec 验证签名时: http:// www.aleksey.com/xmlsec/xmldsig-verifier.html。我收到一条消息,告诉我签名无效。
我几天来一直在寻找代码中的错误,但找不到。我开始认为从 PEM 到 XML 文件的转换可能是问题所在,但我不知道如何测试它。此外,我没有找到任何其他方法来转换为密钥或直接使用.NET中的PEM文件。
有人设法在 .NET 中获得有效签名吗?
I am trying to sign an XML file in C# .NET 3.5 with a private RSA Key generated by OpenSSL.
Here is how I proceeded: I converted the RSA key from PEM format to XML format using the chilkat framework (www.example-code.com/csharp/cert_usePrivateKeyFromPEM.asp)
With my XML key, I am now able to use native .NET Functions, which I prefer. So I used the methods described on MSDN.
So, in the end, my source code looks like this:
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
//Load the private key from xml file
XmlDocument xmlPrivateKey = new XmlDocument();
xmlPrivateKey.Load("PrivateKey.xml");
rsaProvider.FromXmlString(xmlPrivateKey.InnerXml);
// Create a SignedXml object.
SignedXml signedXml = new SignedXml(Doc);
// Add the key to the SignedXml document.
signedXml.SigningKey = Key;
// Create a reference to be signed.
Reference reference = new Reference();
reference.Uri = "";
// Add an enveloped transformation to the reference.
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
// Add the reference to the SignedXml object.
signedXml.AddReference(reference);
// Compute the signature.
signedXml.ComputeSignature();
// Get the XML representation of the signature and save
// it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Append the element to the XML document.
Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true));
The Signed XML I get with this function looks OK, I have the XML element at the end of the file, like it is supposed to be:
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<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="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>qoGPSbe4oR9e2XKN6MzP+7XlXYI=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>iPQ6IET400CXfchWJcP22p2gK6RpEc9mkSgfoA94fL5UM6+AB5+IO6BbjsNt31q6MB8hR6lAIcnjzHzc5SeXvFP8Py2bqHTYJvcSA6KcKCQl1LiDNt12UwWiKpSkus2p0LdAeeZJNy9aDxjC/blUaZEr4uPFt0kGCD7h1NQM2SY=</SignatureValue>
The problem is that when I try to verify the signature using xmlsec at this URL: http://www.aleksey.com/xmlsec/xmldsig-verifier.html. I get a message telling me the signature is invalid.
I have been looking for the error in my code for days and I can't find out. I am beginning to think that the conversion from PEM to XML file might be the problem but I don't know how to test this. Moreover, I did not find any other way to convert to key or to use directly the PEM file in .NET.
Did anyone manage to get a valid signature in .NET?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
是的,我已经做到了。
我认为问题出在你的参考上。 uri 应指向签名所针对的元素的 id。无论如何,请检查下面的代码,希望它能为您指明正确的方向。
/克劳斯
Yes, I have managed to do that.
I think the problem is with your reference. The uri should point to the id of the element that the signature is for. Anyway, check the below code, hope it points you in the right direction.
/Klaus
在我看来,您对 xml 中的所有内容进行了签名:
reference.Uri = "";
当您将其插入文档或以错误的方式插入时,您可能会破坏签名。
还要注意命名空间和空格,其中一些也已签名,这可能会在以后处理签名文档时导致问题。
It seems to me, that you sign the everrything in the xml:
reference.Uri = "";
Purhaps you break the signature when you insert it in the document or insert it in a wrong way.
Also be aware of namespaces and whitespace some of it is also signed which can cause problems later on when working on the signed document.
尝试
用这个替换:
Try to replace
with this:
我今天遇到了同样的问题,我的一位同事怀疑这可能是因为 .net xml C14 转换不遵循 xmlsec 中实现的 XML 标准。我会尝试自己进行转换,并让您知道这是否确实是问题所在。
I am having the same problem today, one of my co-worker suspects that it's maybe because .net xml C14 transform doesn't follow the XML standard which is implemented in xmlsec. I will try to do the transform on my own and let you know if that's really the issue.
在使用 XML-Signer 验证签名的 XML 时,我遇到了同样的问题。当我添加以下内容后,问题就解决了:
doc.PreserveWhitespace = False
在加载要签名的 XML 文档之前
可以在此处找到一个很好的示例:
http://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.signature(v=vs.110).aspx ?cs-save-lang=1&cs-lang=vb#code-snippet-2
I had the same problem when verifying the signed XML with XML-Signer. It got solved when I added:
doc.PreserveWhitespace = False
before loading the XML Document to be signed
A good example can be found here:
http://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.signature(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2