Skip to content

Instantly share code, notes, and snippets.

@daisukenishino2
Last active May 1, 2019 08:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daisukenishino2/69074e571cf89c23cce6d1522abc67e5 to your computer and use it in GitHub Desktop.
Save daisukenishino2/69074e571cf89c23cce6d1522abc67e5 to your computer and use it in GitHub Desktop.
ネストしたXMLの署名・検証処理の問題の確認用コード。https://github.com/AndersAbel/DualXmlDsigBug
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.Xml;
namespace DualXmlDsigBug
{
public static class SigningTest
{
public static void SignAndVerify()
{
var xml = ""
+ "<xml>"
+ " <a ID=\"a\">"
+ " <b ID=\"b\">"
+ " <c/>"
+ " </b>"
+ " </a>"
+ "</xml>";
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
using (var csp = new RSACryptoServiceProvider())
{
#region 子ノード b のXML署名・検証
#region 子ノード b のXML署名
Console.WriteLine("Signing child b node...");
SignedXml signedXmlB = new SignedXml(xmlDoc) { SigningKey = csp };
#region Reference要素
// 子ノード b をポイント
Reference referenceB = new Reference("#b");
// Add Transform
referenceB.AddTransform(new XmlDsigEnvelopedSignatureTransform());
// Add Transform
referenceB.AddTransform(new XmlDsigExcC14NTransform());
// Add Reference
signedXmlB.AddReference(referenceB);
#endregion
// 子ノード b のXML署名の生成
signedXmlB.ComputeSignature();
// 子ノード b のXML署名を子ノード b 直下に追加
XmlNode signatureNodeB = xmlDoc.ImportNode(signedXmlB.GetXml(), true);
xmlDoc.SelectSingleNode("//b").AppendChild(signatureNodeB);
#endregion
#region 子ノード b のXML検証
signedXmlB.LoadXml(signatureNodeB as XmlElement);
XmlNode xmlnode = xmlDoc.SelectSingleNode("//b");
Console.WriteLine("Check signature B: " + CheckSignature(xmlnode, csp));
#endregion
#endregion
//---------------------------------------------
#region 親ノード a のXML署名・検証
#region 親ノード a のXML署名
Console.WriteLine("Signing parent a node...");
SignedXml signedXmlA = new SignedXml(xmlDoc) { SigningKey = csp };
#region Reference要素
// 親ノード a をポイント
Reference referenceA = new Reference("#a");
// Add Transform
referenceA.AddTransform(new XmlDsigEnvelopedSignatureTransform());
// Add Transform
referenceA.AddTransform(new XmlDsigExcC14NTransform());
// Add Reference
signedXmlA.AddReference(referenceA);
#endregion
// 親ノード a のXML署名の生成
signedXmlA.ComputeSignature();
// 親ノード a XML署名を親ノード a 直下に追加
XmlNode signatureNodeA = xmlDoc.ImportNode(signedXmlA.GetXml(), true);
xmlDoc.SelectSingleNode("//a").AppendChild(signatureNodeA);
#endregion
string temp = xmlDoc.OuterXml;
#region 親ノード a のXML検証
Console.WriteLine("Check signature A: " + CheckSignature(xmlDoc.SelectSingleNode("//a"), csp));
Console.WriteLine("Check signature B: " + CheckSignature(xmlDoc.SelectSingleNode("//b"), csp));
#endregion
#endregion
// ネストが問題になるようなら、
// 子ノード b だけ抽出して計算すればイイ
// ネストした、子ノード b のXML検証
var childDoc = new XmlDocument();
childDoc.LoadXml(xmlDoc.SelectSingleNode("//b").OuterXml);
Console.WriteLine("Check signature B, in own document: " + CheckSignature(childDoc.SelectSingleNode("//b"), csp));
}
}
private static bool CheckSignature(XmlNode xmlNode, RSACryptoServiceProvider csp)
{
// 署名ノードの直下のSignatureを取り出して、signedXml.LoadXmlする。
var signedXml = new SignedXml(xmlNode.OwnerDocument);
signedXml.LoadXml(xmlNode["Signature"] as XmlElement);
// XML検証
return signedXml.CheckSignature(csp);
}
}
}
@daisukenishino2
Copy link
Author

daisukenishino2 commented Apr 24, 2019

経緯

SignedXmlクラスの実装に問題があり、
ネストした複数のXML署名が Verify できないらしい。

https://techinfoofmicrosofttech.osscons.jp/index.php?SAML%E3%82%92%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B%E3%80%82#k3724cb3

結果

使用する範囲(SAML2 Assertionの署名・検証)で、問題なく動作するものと思われる。

出力

ConsoleのOutput。

Signing child b node...
Check signature B: True
Signing parent a node...
Check signature A: True
Check signature B: True
Check signature B, in own document: True

SignedXml

署名したXML(正しく検証できた。)

<?xml version="1.0"?>
<xml>
  <a ID="a">
    <b ID="b">
      <c/>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
          <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
          <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <Reference URI="#b">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <DigestValue>/EvGA/js0jXC8pDZ5yZlJHJkJY0=</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>qFnF7Llsxg8BIEXzTJeAimygL7GMIK9SRMZcsGeLXxvLQn7VE6DBMSByBkJ5iAjWp4ycDX6REtZEwk4z4XXjtKazZsS6DeVzmEzmRWeDxsBKrj4+OUK9BpoeBFwDbyXCc7H4xH5OeEwaxgVRxbJtGXuw74316A/IPAvEetsRca0=</SignatureValue>
      </Signature>
    </b>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
      <SignedInfo>
        <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
        <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
        <Reference URI="#a">
          <Transforms>
            <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
          </Transforms>
          <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
          <DigestValue>IV6qpTG2GvJPjQXOBFGAmhBhpPg=</DigestValue>
        </Reference>
      </SignedInfo>
      <SignatureValue>oJmT5RNVxR8ZtqzGVI1EM5nLB9XDiV/hUA+3d7BYz3PCYDN8BiWAER4oh8rh/kRdgbTpJezxidzR5eDPTvlDky31L+nOFAhfD4qeXgFM9mzAk9hl75jz0YnUGA76RwKKztWDf3+h8MjtenOwYFxj43ue1QI5Kl+kKq+qN6GRZXE=</SignatureValue>
    </Signature>
  </a>
</xml>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment