我正在对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文档一起提供。
答案 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构造函数来做),你应该能够在没有完全信任的情况下运行。