3

Markus Dreyer のような同じ問題に苦しんでいます: C# Calculate SHA256 value for SEPA (XML) paymentfile

DFÜ 協定によると、sha256 ハッシュ値を計算する必要があります。

  • ハッシュ値は、開始タグと終了タグを含む、含まれているドキュメント全体を使用して作成されます。
  • ドキュメントは、Canonical XML バージョン 1.0 に従って正規化されています。( http://www.w3.org/TR/2001/REC-xml-c14n-20010315 )。
  • 含まれるドキュメントの場合、メインドキュメントに従って正規化も実行する必要があります。
  • SHA-256 はハッシュ アルゴリズムとして使用されます。

これは、有効な xml ファイルのサンプルです (金融ツールからエクスポートされたもの)。

<?xml version="1.0" encoding="UTF-8"?>
<conxml xmlns="urn:conxml:xsd:container.nnn.002" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:conxml:xsd:container.nnn.002 container.nnn.002.xsd">
  <CreDtTm>2013-08-27T07:20:25Z</CreDtTm>
  <MsgPain001>
    <HashValue>33E579FE7A9AF6C32C100E8578EBD63E54A2DF47C6849F7A4BC8BEA9E2794197</HashValue>
    <HashAlgorithm>SHA256</HashAlgorithm>
    <Document xmlns="urn:swift:xsd:$pain.001.002.02">
      <pain.001.001.02>
        <GrpHdr>
          <MsgId>D005201308270920191</MsgId>
          <CreDtTm>2013-08-27T07:20:19Z</CreDtTm>
          <BtchBookg>true</BtchBookg>
          <NbOfTxs>1</NbOfTxs>
          <CtrlSum>0.50</CtrlSum>
          <Grpg>MIXD</Grpg>
          <InitgPty>
            <Nm>Test</Nm>
          </InitgPty>
        </GrpHdr>
        <PmtInf>
          <PmtInfId>D005201308270920191</PmtInfId>
          <PmtMtd>TRF</PmtMtd>
          <PmtTpInf>
            <SvcLvl>
              <Cd>SEPA</Cd>
            </SvcLvl>
          </PmtTpInf>
          <ReqdExctnDt>2013-08-27</ReqdExctnDt>
          <Dbtr>
            <Nm>Test</Nm>
          </Dbtr>
          <DbtrAcct>
            <Id>
              <IBAN>DE76200700000888888888</IBAN>
            </Id>
          </DbtrAcct>
          <DbtrAgt>
            <FinInstnId>
              <BIC>DEUTDEHHXXX</BIC>
            </FinInstnId>
          </DbtrAgt>
          <ChrgBr>SLEV</ChrgBr>
          <CdtTrfTxInf>
            <PmtId>
              <EndToEndId>NOTPROVIDED</EndToEndId>
            </PmtId>
            <Amt>
              <InstdAmt Ccy="EUR">0.50</InstdAmt>
            </Amt>
            <CdtrAgt>
              <FinInstnId>
                <BIC>DEUTDEHHXXX</BIC>
              </FinInstnId>
            </CdtrAgt>
            <Cdtr>
              <Nm>Erwin Mustermann</Nm>
            </Cdtr>
            <CdtrAcct>
              <Id>
                <IBAN>DE09200700000123456789</IBAN>
              </Id>
            </CdtrAcct>
            <RmtInf>
              <Ustrd>Sepa Test Gutschrift</Ustrd>
            </RmtInf>
          </CdtTrfTxInf>
        </PmtInf>
      </pain.001.001.02>
    </Document>
  </MsgPain001>
</conxml>

Markus Dreyer の Solution によると、私のコードは次のとおりです。

System.Text.UTF8Encoding enc = new UTF8Encoding(false);

XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load(@"path to file");
XmlNodeList list = doc.GetElementsByTagName("Document");
String s = list.Item(0).OuterXml;


MemoryStream msIn = new MemoryStream(enc.GetBytes(s));

XmlDsigC14NTransform t = new XmlDsigC14NTransform(true);
t.LoadInput(msIn);
MemoryStream ms = new MemoryStream();
ms = (MemoryStream)t.GetOutput(typeof(MemoryStream));


byte[] digest = t.GetDigestedOutput(new SHA256Managed());
String result = BitConverter.ToString(digest).Replace("-", String.Empty);

私の計算では、55B2597B0688AB1A19760B542AA70AEF4F980D7BC9D6EBCF2B741F6299C661D3 という値が得られましたが、ファイルからの値が期待されます: 33E579FE7A9AF6C32C100E8578EBD63E54A2DF47C6849F7A4BC79E8

私が見逃しているものはありますか?

4

1 に答える 1

3

ここhttp://www.mobilefish.com/download/sepa_xml/pain.001.001.02.xmlを見ると、Document ノードから名前空間が欠落していたようですxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"(おそらく XML パーサーによって削除されたため)。using構文を使用するようにコードを少し変更し、欠落している場合は名前空間を追加しました。これで、正しいハッシュが返されます。

XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.LoadXml(xml);

XmlNodeList list = doc.GetElementsByTagName("Document");

XmlElement node = (XmlElement)list[0];
node.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");

string s = node.OuterXml;

// The XmlDsigC14NTransform will strip the UTF8 BOM
using (MemoryStream msIn = new MemoryStream(Encoding.UTF8.GetBytes(s)))
{
    XmlDsigC14NTransform t = new XmlDsigC14NTransform(true);
    t.LoadInput(msIn);

    using (var hash = new SHA256Managed())
    {
        byte[] digest = t.GetDigestedOutput(hash);
        string result = BitConverter.ToString(digest).Replace("-", String.Empty);
    }
}
于 2013-08-27T08:22:54.250 に答える