【发布时间】:2017-07-21 23:16:54
【问题描述】:
我使用了 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 的所有建议,但没有运气。非常感谢这里的任何帮助。谢谢。
【问题讨论】:
-
您可以尝试启用 SignedXml 日志 (social.msdn.microsoft.com/Forums/en-US/…)。或者,如果您可以提供一个您已签署但报告为无效的示例文档,这将很有帮助。
-
谢谢@bartonjs,我会试一试,让你知道。另外,想知道 SignedXml 类是否支持外部分离签名。我发现一篇文章 [msdn.microsoft.com/en-us/library/… 提到 SignedXml 类不支持外部分离签名。无论如何我可以在 C# 中使用外部分离签名吗?
-
我启用了 SignedXml 日志,并且在日志中捕获了事件。但是,日志中没有抛出任何错误。在验证签名时,我遇到了“无法解析 URI”错误。我可以从日志文件中得到的最后一行是 "System.Security.Cryptography.Xml.SignedXml Verbose: 13 : [SignedXml#01f93f3e, VerifyReference] Processing reference Reference#00eb2115, Uri "test.xml", Id "", 输入 ""。" 一周以来我一直在寻找解决方案。非常感谢您的帮助。
-
SignedXml 不支持分离签名,除非您编辑注册表。没有文档、稳定的重现或日志,任何人都无能为力。
-
@bartonjs 按照你的建议,我编辑了注册表,没有抛出“无法解析 Uri”错误,签名验证成功。非常感谢您的回复。非常感谢。
标签: c# xml x509certificate signing