C# Расчет и проверка значения SHA256 для платежного файла SEPA (XML)

я борюсь с той же проблемой, что и Маркус Дрейер: C# Calculate SHA256 значение для платежного файла SEPA (XML)

В соответствии с соглашением 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>

Согласно решению от Маркуса Дрейера, вот мой код:

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, но ожидается значение из файла: 33E579FE7A9AF6C32C100E8578EBD63E54A2DF47C6749F7A2794BEA19A4BC84BEA

У кого-нибудь из вас есть идея, что мне не хватает?


person Özkan    schedule 27.08.2013    source источник
comment
Я думаю, вы хотите канонизировать, если только ваш XML-документ не возводится в святые.   -  person Damien_The_Unbeliever    schedule 27.08.2013
comment
исправлено: канонизированный -> канонизированный. Я скопировал эту часть из спецификации, так как мой английский не настолько хорош, что я ее пропустил.   -  person Özkan    schedule 27.08.2013


Ответы (1)


Посмотрев здесь http://www.mobilefish.com/download/sepa_xml/pain.001.001.02.xml, похоже, вы пропустили пространство имен xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" в узле Document (вероятно, потому, что оно было удалено синтаксическим анализатором 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);
    }
}
person xanatos    schedule 27.08.2013