5

我正在尝试使用OpenSSL生成的私有RSA密钥在 C# .NET 3.5 中签署 XML 文件。

以下是我的操作:我使用 chilkat 框架 (www.example-code.com/csharp/cert_usePrivateKeyFromPEM.asp) 将 RSA 密钥从PEM格式转换为 XML 格式

通过我的 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 中获得有效签名?

4

5 回答 5

3

是的,我已经做到了。我认为问题在于您的参考。uri 应该指向签名所针对的元素的 id。无论如何,请检查以下代码,希望它为您指明正确的方向。

/克劳斯

/// <summary>
    /// Signs an XmlDocument with an xml signature using the signing certificate given as argument to the method.
    /// </summary>
    /// <param name="doc">The XmlDocument to be signed</param>
    /// <param name="id">The is of the topmost element in the xmldocument</param>
    /// <param name="cert">The certificate used to sign the document</param>
    public static void SignDocument(XmlDocument doc, string id, X509Certificate2 cert)
    {
        SignedXml signedXml = new SignedXml(doc);
        signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
        signedXml.SigningKey = cert.PrivateKey;

        // Retrieve the value of the "ID" attribute on the root assertion element.
        Reference reference = new Reference("#" + id);

        reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
        reference.AddTransform(new XmlDsigExcC14NTransform());

        signedXml.AddReference(reference);

        // Include the public key of the certificate in the assertion.
        signedXml.KeyInfo = new KeyInfo();
        signedXml.KeyInfo.AddClause(new KeyInfoX509Data(cert, X509IncludeOption.WholeChain));

        signedXml.ComputeSignature();
        // Append the computed signature. The signature must be placed as the sibling of the Issuer element.
        XmlNodeList nodes = doc.DocumentElement.GetElementsByTagName("Issuer", Saml20Constants.ASSERTION);
        // doc.DocumentElement.InsertAfter(doc.ImportNode(signedXml.GetXml(), true), nodes[0]);            
        nodes[0].ParentNode.InsertAfter(doc.ImportNode(signedXml.GetXml(), true), nodes[0]);
    }
于 2009-12-01T10:05:08.127 回答
1

我今天遇到了同样的问题,我的一位同事怀疑这可能是因为 .net xml C14 转换不遵循在 xmlsec 中实现的 XML 标准。我将尝试自己进行转换,并让您知道这是否真的是问题所在。

于 2013-08-09T06:45:14.097 回答
1

尝试更换

dataObject.Data = Doc.ChildNodes;

有了这个:

dataObject.Data = Doc.GetElementsByTagName("YourRootNodeNameHere");
于 2009-12-08T15:46:32.197 回答
1

在我看来,您签署了 xml 中的所有内容:reference.Uri = "";

可能是您在将签名插入文档或以错误方式插入时破坏了签名。

还要注意命名空间和空格,其中一些也已签名,这可能会在以后处理已签名的文档时导致问题。

于 2009-12-01T10:05:28.310 回答
1

在使用 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

于 2015-01-20T07:46:21.827 回答