XML DSIG验证

时间:2009-07-10 07:51:49

标签: asp.net cryptography xml-signature

我正在对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将FullTrust安全策略分配给我的Web应用程序。

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

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

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

1 个答案:

答案 0 :(得分:4)

首先回答您的第二个问题:您希望使用用于签名的RSA密钥对的public部分来验证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构造函数来做),你应该能够在没有完全信任的情况下运行。