34

サードパーティのWebサービスから応答があります。その応答でXmlDocumentをロードします。

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

次に、証明書を使用して応答が署名されていることを確認します。私はmsdnVerifyXmlDoc(XmlDocument xmlDoc)で見つけたメソッドを持っています。

私はメッセージが正しいことを知っています。

    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;

    }

プロジェクトのターゲットフレームワークを.NET3.5または.NET3、あるいは.NET 2に設定すると、うまく機能します。結果は真です。しかし、ターゲットフレームワークを.NET 4に変更すると、結果はfalseになります。(そして私は.NET 4を使用する必要があります)

この問題を解決する方法について何かアイデアはありますか?

4

8 に答える 8

7

これは既知の問題です。.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 < 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);
  }
}

CryptoConfig.AddAlgorithm メソッドを使用してクラスを登録します。

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.  

それはそれを行う必要があります。

于 2014-12-02T19:08:33.267 に答える
1

SignedXml クラスの SignedInfo プロパティの Canonicalization メソッドを明示的に設定してみてください。ここでは、.Net 2.0 と .Net 4.0 の間でデフォルトの動作が変更されているようです。

signed.SignedInfo.CanonicalizationMethod = Signed.XmlDsigExcC14NTransformUrl;

参照:

この答え

于 2014-01-29T05:13:42.090 に答える
0

SignatureタグからSignedInfoに同じ名前空間を追加して、この問題を解決しました。このような:

前: ここに画像の説明を入力

後: ここに画像の説明を入力

于 2014-12-11T16:41:25.667 に答える
0
// Assume the data to sign is in the data.xml file, load it, and

// set up the signature object.
XmlDocument doc = new XmlDocument();

doc.Load(@"D:\Example.xml");
SignedXml sig = new SignedXml(doc);

// Make a random RSA key, and set it on the signature for signing.
RSA key = new RSACryptoServiceProvider();

sig.SigningKey = key;

// Create a Reference to the containing document, add the enveloped
// transform, and then add the Reference to the signature
Reference refr = new Reference("");refr.AddTransform(new XmlDsigEnvelopedSignatureTransform());

sig.AddReference(refr);

// Compute the signature, add it to the XML document, and save
sig.ComputeSignature();

doc.DocumentElement.AppendChild(sig.GetXml());
doc.Save("data-signed.xml");

// Load the signed data

//XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;

doc.Load("data-signed.xml");

// Find the Signature element in the document
XmlNamespaceManager nsm = new XmlNamespaceManager(new NameTable());

nsm.AddNamespace("dsig", SignedXml.XmlDsigNamespaceUrl);
XmlElement sigElt = (XmlElement)doc.SelectSingleNode("//dsig:Signature", nsm);

// Load the signature for verification

//SignedXml sig = new SignedXml(doc);

sig.LoadXml(sigElt);

// Verify the signature, assume the public key part of the

// signing key is in the key variable
if (sig.CheckSignature(key))
    Console.WriteLine("Signature verified");
else
    Console.WriteLine("Signature not valid");
于 2014-04-26T07:28:00.850 に答える
0

.NET Framework 4/4.5 以降、x509 証明書およびその他のセキュリティ機能を操作するクラスは、System.IdentityModel.dll にあります。上記の名前空間でそれぞれのクラスを検索します。

于 2014-11-21T17:28:43.313 に答える
0

NET 4.0+ で署名を確認するには、CanonicalizationMethod のコンテキストを変更する必要があるため、signedXml オブジェクトを次の方法で初期化する必要があります。

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

SignedXml signedXml = new SignedXml((XmlElement)signatureNodeList[0]);

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

//Then you proceed your check as usual
于 2016-07-12T02:11:55.710 に答える