SignedXml.CheckSignature在.NET 4中失败,但它在.NET 3.5,3或2中工作 [英] SignedXml.CheckSignature fails in .NET 4 but it works in .NET 3.5, 3 or 2

查看:525
本文介绍了SignedXml.CheckSignature在.NET 4中失败,但它在.NET 3.5,3或2中工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有来自第三方Web服务的回复。我加载一个XmlDocument的响应。

  string txt = readStream.ReadToEnd 
response = new XmlDocument()?
response.PreserveWhitespace = true;
response.LoadXml(txt);
return response;

现在我想验证respones是否使用证书签名。我有一个在 msdn 上找到的 VerifyXmlDoc(XmlDocument xmlDoc)方法。



我知道邮件是正确的。

  public bool VerifyXmlDoc (XmlDocument xmlDoc)
{

SignedXml signed = new SignedXml(xmlDoc);

XmlNodeList signatureNodeList = xmlDoc.GetElementsByTagName(Signature);


signed.LoadXml((XmlElement)signatureNodeList [0]);

X509Certificate1 serviceCertificate = null;
foreach(signed.KeyInfo中的KeyInfoClause子句)
{
if(子句是KeyInfoX509Data)
{
if(((KeyInfoX509Data)子句).Certificates.Count> ; 0)
{
serviceCertificate =(X509Certificate2)((KeyInfoX509Data)clause).Certificates [0];
}
}
}


bool result = signed.CheckSignature(serviceCertificate,true);
return result;

}



如果我将我的项目的目标框架设置为.NET 3.5或.NET 3或.NET 2,它的工作伟大。结果为true。但如果我将目标框架更改为.NET 4,结果为false。
(我必须使用.NET 4)



有关如何解决这个问题的任何想法吗?

解决方案

这是一个已知问题。 .NET 3.5和.NET 4.0之间的规范化实现已更改。



我不知道这是否适用于所有的XML签名,但下面的工作从我做过的测试。



向您的项目添加以下C14N Transform类:



  public class MyXmlDsigC14NTransform: XmlDsigC14NTransform {static XmlDocument _document; public static XmlDocument document {set {_document = value; }} public MyXmlDsigC14NTransform(){} public override Object GetOutput(){return base.GetOutput(); } public override void LoadInnerXml(XmlNodeList nodeList){base.LoadInnerXml(nodeList); } protected override XmlNodeList GetInnerXml(){XmlNodeList nodeList = base.GetInnerXml(); return nodeList; } public XmlElement GetXml(){return base.GetXml(); } public override void LoadInput(Object obj){int n; bool fDefaultNS = true; XmlElement element =((XmlDocument)obj).DocumentElement; if(element.Name.Contains(SignedInfo)){XmlNodeList DigestValue = element.GetElementsByTagName(DigestValue,element.NamespaceURI); string strHash = DigestValue [0] .InnerText; XmlNodeList nodeList = _document.GetElementsByTagName(element.Name); for(n = 0; n  

使用CryptoConfig.AddAlgorithm方法注册类。

/ p>

  CryptoConfig.AddAlgorithm(typeof(MyXmlDsigC14NTransform),http://www.w3.org/TR/2001/REC-xml-c14n- 20010315); var message = new XmlDocument(); message.PreserveWhitespace = true; message.Load(XmlSig.xml); MyXmlDsigC14NTransform.document = message; // Transform类需要xml文档// Validate signature as normal。  



应该这样做。


I have a response from a 3-rd party web service. I load an XmlDocument with that response.

  string txt = readStream.ReadToEnd();
  response = new XmlDocument();
  response.PreserveWhitespace = true;
  response.LoadXml(txt);   
  return response;

Now I would like to verify that the respones is signed using the certificate. I have a VerifyXmlDoc(XmlDocument xmlDoc) method which I have found on msdn.

I know that the message is correct.

    public bool VerifyXmlDoc(XmlDocument xmlDoc)
    {

        SignedXml signed = new SignedXml(xmlDoc);

        XmlNodeList signatureNodeList = xmlDoc.GetElementsByTagName("Signature");


        signed.LoadXml((XmlElement)signatureNodeList[0]);

        X509Certificate2 serviceCertificate = null;
        foreach (KeyInfoClause clause in signed.KeyInfo)
        {
            if (clause is KeyInfoX509Data)
            {
                if (((KeyInfoX509Data)clause).Certificates.Count > 0)
                {
                    serviceCertificate = (X509Certificate2)((KeyInfoX509Data)clause).Certificates[0];
                }
            }
        }


        bool result = signed.CheckSignature(serviceCertificate, true);
        return result;

    }

If I set target framework of my project to .NET 3.5 or .NET 3, or .NET 2 it works great. Result is true. But if I change target framework to .NET 4 result is false. (And I have to use .NET 4)

Any ideas on how to solve this problem?

解决方案

This is a known issue. The Canonicalization implementation between .NET 3.5 and .NET 4.0 has changed.

I don't know if this works on all XML signatures but the following works from the testing that I've done.

Add the following C14N Transform class to your project:

public class MyXmlDsigC14NTransform: XmlDsigC14NTransform {
  static XmlDocument _document;
  public static XmlDocument document {
    set {
      _document = value;
    }
  }

  public MyXmlDsigC14NTransform() {}

  public override Object GetOutput() {
    return base.GetOutput();
  }

  public override void LoadInnerXml(XmlNodeList nodeList) {
    base.LoadInnerXml(nodeList);
  }

  protected override XmlNodeList GetInnerXml() {
    XmlNodeList nodeList = base.GetInnerXml();
    return nodeList;
  }

  public XmlElement GetXml() {
    return base.GetXml();
  }

  public override void LoadInput(Object obj) {
    int n;
    bool fDefaultNS = true;

    XmlElement element = ((XmlDocument) obj).DocumentElement;

    if (element.Name.Contains("SignedInfo")) {
      XmlNodeList DigestValue = element.GetElementsByTagName("DigestValue", element.NamespaceURI);
      string strHash = DigestValue[0].InnerText;
      XmlNodeList nodeList = _document.GetElementsByTagName(element.Name);

      for (n = 0; n < nodeList.Count; n++) {
        XmlNodeList DigestValue2 = ((XmlElement) nodeList[n]).GetElementsByTagName("DigestValue", ((XmlElement) nodeList[n]).NamespaceURI);
        string strHash2 = DigestValue2[0].InnerText;
        if (strHash == strHash2) break;
      }

      XmlNode node = nodeList[n];

      while (node.ParentNode != null) {
        XmlAttributeCollection attrColl = node.ParentNode.Attributes;
        if (attrColl != null) {
          for (n = 0; n < attrColl.Count; n++) {
            XmlAttribute attr = attrColl[n];
            if (attr.Prefix == "xmlns") {
              element.SetAttribute(attr.Name, attr.Value);
            } else if (attr.Name == "xmlns") {
              if (fDefaultNS) {
                element.SetAttribute(attr.Name, attr.Value);
                fDefaultNS = false;
              }
            }
          }
        }

        node = node.ParentNode;
      }
    }

    base.LoadInput(obj);
  }
}

Register the class using the CryptoConfig.AddAlgorithm method.

CryptoConfig.AddAlgorithm(typeof(MyXmlDsigC14NTransform), "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"); 

var message = new XmlDocument();
message.PreserveWhitespace = true;
message.Load("XmlSig.xml");

MyXmlDsigC14NTransform.document = message; // The transform class needs the xml document

// Validate signature as normal.  

That should do it.

这篇关于SignedXml.CheckSignature在.NET 4中失败,但它在.NET 3.5,3或2中工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆