【问题标题】:XAdES SignedXml.CheckSignature() always returns falseXAdES SignedXml.CheckSignature() 始终返回 false
【发布时间】: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


【解决方案1】:

根据来自 cmets 的数据,您的问题是您尝试使用外部(分离的)签名,尽管您显示的代码使用的是 "" 的 Uri,它表示“整个文档”。

Remarks section for SignedXml on MSDN 中,我们获得了一些宝石:

还有第四种签名,称为外部分离签名,即数据和签名位于单独的 XML 文档中。 SignedXml 类不支持外部分离签名。

...

元素的 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 安全修复程序的特定部分。它还带有一个注释:

警告启用此注册表项可能会导致安全漏洞,包括拒绝服务、分布式反射拒绝服务、信息泄露、签名绕过和远程代码执行。

所以,如果你需要这样做……要小心。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-14
    • 2021-07-22
    相关资源
    最近更新 更多