1

我正在对 XML 文档进行数字签名并在 2 台不同的机器上验证它(在一台机器上签名并在另一台机器上验证)。

我正在执行以下操作来验证 CSharp.Net 中的 XML DSIG。

        public static Boolean VerifyXml(XmlDocument document)
        {
            document.PreserveWhitespace = true;
            // Create a new CspParameters object to specify
            // a key container.
            CspParameters cspParams = new CspParameters();
            cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";

            // Create a new RSA signing key and save it in the container. 
            //**Earlier was getting exception here in rsaKey object**
            RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

            // Create a new SignedXml object and pass it
            // the XML document class.
            SignedXml signedXml = new SignedXml(document);

            // Find the "Signature" node and create a new
            // XmlNodeList object.
            // It's guaranteed that there's always exists a signature 
            XmlNodeList nodeList = document.GetElementsByTagName("Signature");

            // Load the <signature> node.  
            signedXml.LoadXml((XmlElement)nodeList[0]);

            // Check the signature and return the result.
            bool isDone = signedXml.CheckSignature(rsaKey); //**This is returning false.**
            return isDone;
        }

最初,当我的 Web 应用程序尝试访问密钥容器时,我得到了 PermissionDenied 异常。但是,我暂时将应用程序用户和 IIS 用户添加到管理员角色,并使用 CasPol 为我的 Web 应用程序分配了 FullTrust 安全策略。

Q1:[我的第一个问题是克服这个问题的最佳方法是什么??我知道分配 web 应用程序完全信任并将用户添加到管理员角色不是一个好主意,即使它有效

我的第二个问题是关于signedXml.CheckSignature(rsaKey);返回的错误。现在根据我的理解,由于 XML 文档是在另一台机器上进行数字签名的,因此用于签名的 MAC 存储在该机器上 KEY Container Name "XML_DSIG_RSA_KEY",但是当我尝试验证主机上的签名时,不同的 MAC 是生成并存储在主机上的容器名称“XML_DSIG_RSA_KEY”中,因此数字签名没有得到验证。

Q2:这个假设正确吗?以及解决此问题的最佳方法是什么...在这种情况下,我是否应该使用证书对 XML 文档进行数字签名,然后对其进行验证。我是否需要将证书与 DSIG XML 文档一起提供????

4

1 回答 1

4

首先回答您的第二个问题:您想使用用于签名的 RSA 密钥对的公共部分来验证 XML。因此,您需要在验证机上已经拥有(并信任)公钥,或者发送包含带有 XML 公钥的证书(它可以存储在 XML 签名结构中),然后验证证书是否已经由受信任的证书颁发机构颁发。

要实现第一种情况,您可以ToXmlString(false)在发送端调用密钥,将结果存储在一个文件中,并将此文件保存在接收端。然后在接收端,读取文件并调用:

RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider();
rsaKey.ImportFromXml(publicKeyFromFile);

第二种情况可以通过获取证书来完成,并将其添加到签名端的签名中,如下所示:

KeyInfo keyInfo = new KeyInfo();
X509Certificate cert = // load certificate
keyInfo.AddClause(new KeyInfoX509Data(cert));
signedXml.KeyInfo = keyInfo;

如果证书是可信的,那么您可以通过调用来验证接收方的签名:

bool isDone = signedXml.CheckSignature();

要回答您的第一个问题:一旦您不再尝试访问私钥存储(您通过调用 RSACryptoServiceProvider-constructor 像您所做的那样),您应该能够在没有完全信任的情况下运行。

于 2009-07-10T09:07:06.297 回答