我使用MSDN中的以下方法来签名和验证XML文件。
问题是我无法验证签名的XML文件。 SignedXML.CheckSignature()方法总是返回false,甚至不会在出错的地方抛出任何异常。
用于签署XML文件的方法
public static void SignXMLFile(XmlDocument xmlDoc, string XmlSigFileName)
{
// Create a SignedXml object.
SignedXml signedXml = new SignedXml(xmlDoc);
string certPath = @"path to PFX file.pfx";
X509Certificate2 cert = new X509Certificate2(certPath, "password", X509KeyStorageFlags.Exportable);
var exportedKeyMaterial = cert.PrivateKey.ToXmlString(true);
var Key = new RSACryptoServiceProvider(new CspParameters(24));
Key.PersistKeyInCsp = false;
Key.FromXmlString(exportedKeyMaterial);
// Assign the key to the SignedXml object.
signedXml.SigningKey = Key;
//// Create a reference to be signed.
//Reference reference = new Reference(System.IO.File.Open(@"D:\test.docx",System.IO.FileMode.Open));
//// Add the passed URI to the reference object.
//reference.Uri = URIString;
//// Add the reference to the SignedXml object.
//signedXml.AddReference(reference);
// Create a reference to be signed.
Reference reference = new Reference();
// Add the passed URI to the reference object.
reference.Uri = "";
// Add the reference to the SignedXml object.
signedXml.AddReference(reference);
//Save the public key into the KeyValue node of the Signature
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new RSAKeyValue(Key));
signedXml.KeyInfo = keyInfo;
// Compute the signature.
signedXml.ComputeSignature();
// Get the XML representation of the signature and save
// it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Save the signed XML document to a file specified
//using the passed string.
XmlTextWriter xmltw = new XmlTextWriter(XmlSigFileName, new UTF8Encoding(false));
xmlDigitalSignature.WriteTo(xmltw);
xmltw.Close();
}
用于验证XML文件签名的方法
// Verify the signature of an XML file and return the result.
public static Boolean VerifyXmlFile(String Name)
{
// Check the arguments.
if (Name == null)
throw new ArgumentNullException("Name");
// Create a new XML document.
XmlDocument xmlDocument = new XmlDocument();
// Format using white spaces.
xmlDocument.PreserveWhitespace = true;
// Load the passed XML file into the document.
xmlDocument.Load(Name);
// Create a new SignedXml object and pass it
// the XML document class.
SignedXml signedXml = new SignedXml(xmlDocument);
// Find the "Signature" node and create a new
// XmlNodeList object.
XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");
// Load the signature node.
signedXml.LoadXml((XmlElement)nodeList[0]);
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigBase64TransformUrl;
X509Certificate2 cert = new X509Certificate2(@"path to PFX file.pfx", "password");
// Check the signature and return the result.
return signedXml.CheckSignature(cert, true);
}
我尝试使用stackoverflow中的所有suggesstions,但没有运气。这里的任何帮助非常感谢。感谢。
答案 0 :(得分:0)
根据评论中的数据,您的问题是您尝试使用外部(分离)签名,尽管您使用Uri ""
显示的代码代表了"这整个文档& #34;
在Remarks section for SignedXml on MSDN我们得到了几个宝石:
还有第四种称为外部分离签名的签名,即当数据和签名位于单独的XML文档中时。 SignedXml类不支持外部分离签名。
...
< Reference>的URI属性元件
...
- 将URI属性设置为空字符串表示文档的根元素正在签名,这是一种封装签名的形式。
...
- 其他任何内容都被视为外部资源分离签名,SignedXml类不支持。
然后整个部分称为"外部引用的问题"。该部分提供了After you apply security update 3141780, .NET Framework applications encounter exception errors or unexpected failures while processing files that contain SignedXml的链接。
该链接谈到了一个注册表项(我不打算在这里发布,随意关注它),其中说明了如何选择退出MS16-035安全修复程序的特定部分。它还带有一个注释:
警告启用此注册表项可能会导致安全漏洞,包括拒绝服务,分布式反射拒绝服务,信息泄露,签名绕过和远程执行代码。
所以,如果你需要这样做......小心。