C#为SEPA(XML)付款文件计算SHA256值

问题描述:

以计算SHA256对于SEPA容器支付文件的哈希值。

in the specification of the "DFÜ agreement" is described to calculate the hashvalue for a SEPA container payment file by SHA256.


使用整个包含的文档创建哈希值,包括打开
和关闭document标签。

The hash value is created using the entire contained document, including the opening and closing "document" tag.

文档根据Canonical XML 1.0版进行了规范化。
http://www.w3.org/TR/ 2001 / REC-xml-c14n-20010315 )。

The document is canonised according to Canonical XML, version 1.0. (http://www.w3.org/TR/2001/REC-xml-c14n-20010315).

在包含文档的情况下,还可以根据主文档执行。

In the case of included documents, the canonisation has also to be executed according to the main document.

SHA-256用作散列算法。

SHA-256 is used as hash algorithm.

散列值以十六进制形式输入标签,大写字符用于十六进制数字A到F.当在SRZ过程中使用XML容器时,必须指定散列值(缩写SRZ
代表德语术语Servicerechenzentrum,意思是数据处理服务中心)。

The hash value is entered in hexadecimal form in the tag, capital characters are used for the hexadecimal digits A to F. When using an XML container within the SRZ procedure it is mandatory to specify the hash value (the abbreviation SRZ stands for the German term „Servicerechenzentrum" meaning "data processing service centre").

我尝试了不同的方法,但我不能得到正确的值。

I tryed different ways to do that but i am not able to get the correct value.

    [Test]
    public void GetHashTest()
    {
        // load document
        XmlDocument sepaContainer = new XmlDocument();
        sepaContainer.PreserveWhitespace = true;
        sepaContainer.Load("PathToFile");

        // do canonical 
        XmlDsigC14NTransform transformer = new XmlDsigC14NTransform();
        transformer.LoadInput(document);

        string compare = string.Empty;
        foreach (byte b in transformer.GetDigestedOutput(new SHA256Managed()))
        {
            compare += b.ToString("X2");
        }

        Assert.That(compare, Is.EqualTo("1FA8EE4F1E9551C82E1C7A82A88140325453A52BD08FF9FA5D13CA40F04AB305"));
    }

也不能将文件读入字符串并计算:

Also not working to read the file into a string and calculate:

    private string GetSHA256(string text)
    {
        UTF8Encoding UE = new UTF8Encoding();
        byte[] message = UE.GetBytes(text);

        SHA256Managed hashString = new SHA256Managed();
        string hex = string.Empty;

        byte[] hashValue = hashString.ComputeHash(message);
        foreach (byte x in hashValue)
        {
            hex += string.Format("{0:X2}", x);
        }

        return hex;
    }

目前我使用的SEPA XML容器从这里: http://entwickler-forum.de/showthread.php/64499-Auslesen-einer- XML-Datei

Currently i work with the SEPA XML container from here: http://entwickler-forum.de/showthread.php/64499-Auslesen-einer-XML-Datei

<?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>2010-10-26T14:48:17Z</CreDtTm>
  <MsgPain008>
    <HashValue>38B862BD35B95D8CB20448153B5F6F73B3657EB1BC81CF11D3491D16EEA94009</HashValue>
    <HashAlgorithm>SHA256</HashAlgorithm>
    <Document xmlns="urn:swift:xsd:$pain.008.002.01">
      <pain.008.001.01>
        <GrpHdr>
          <MsgId>D004201010261648081</MsgId>
          <CreDtTm>2010-10-26T14:48:08Z</CreDtTm>
          <NbOfTxs>1</NbOfTxs>
          <CtrlSum>0.20</CtrlSum>
          <Grpg>MIXD</Grpg>
          <InitgPty>
            <Nm>Testauftraggeber SEPA-LS</Nm>
          </InitgPty>
        </GrpHdr>
        <PmtInf>
          <PmtInfId>D00420101024444444081</PmtInfId>
          <PmtMtd>DD</PmtMtd>
          <PmtTpInf>
            <SvcLvl>
              <Cd>SEPA</Cd>
            </SvcLvl>
            <LclInstrm>
              <Cd>CORE</Cd>
            </LclInstrm>
            <SeqTp>OOFF</SeqTp>
          </PmtTpInf>
          <ReqdColltnDt>2010-11-02</ReqdColltnDt>
          <Cdtr>
            <Nm>Testauftraggeber SEPA-LS</Nm>
          </Cdtr>
          <CdtrAcct>
            <Id>
              <IBAN>DE352505018444402014</IBAN>
            </Id>
          </CdtrAcct>
          <CdtrAgt>
            <FinInstnId>
              <BIC>SPKHDE2HXXX</BIC>
            </FinInstnId>
          </CdtrAgt>
          <ChrgBr>SLEV</ChrgBr>
          <DrctDbtTxInf>
            <PmtId>
              <EndToEndId>Lastschriftreferenz 002</EndToEndId>
            </PmtId>
            <InstdAmt Ccy="EUR">0.20</InstdAmt>
            <DrctDbtTx>
              <MndtRltdInf>
                <MndtId>Mandat002</MndtId>
                <DtOfSgntr>2010-10-26</DtOfSgntr>
                <AmdmntInd>false</AmdmntInd>
              </MndtRltdInf>
              <CdtrSchmeId>
                <Id>
                  <PrvtId>
                    <OthrId>
                      <Id>DE98ZZZ09999999999</Id>
                      <IdTp>SEPA</IdTp>
                    </OthrId>
                  </PrvtId>
                </Id>
              </CdtrSchmeId>
            </DrctDbtTx>
            <DbtrAgt>
              <FinInstnId>
                <BIC>SPKHDE2HXXX</BIC>
              </FinInstnId>
            </DbtrAgt>
            <Dbtr>
              <Nm>Test Zahlungspflichtiger</Nm>
            </Dbtr>
            <DbtrAcct>
              <Id>
                <IBAN>DE132505018005555552</IBAN>
              </Id>
            </DbtrAcct>
            <UltmtDbtr>
              <Nm>Test Miete</Nm>
            </UltmtDbtr>
            <RmtInf>
              <Ustrd>Test SEPA-LS Einzug durch 10002014 Zahlungspflichtiger 10002022</Ustrd>
            </RmtInf>
          </DrctDbtTxInf>
        </PmtInf>
      </pain.008.001.01>
    </Document>
  </MsgPain008>
</conxml>

我手动和通过xpath提取了文档节点,但仍然有一个不同的值,那么

I extracted the "Document"-node by hand and by xpath but still got a different value then there is calculated for the check hash.

希望您有任何想法?

编辑:26.08.2013 - 更改(更正)xml文件的给定哈希值

26.08.2013 - changed (corrected) the given hashvalue of the xml file

确定我想通知解决方案,找到这些主题:

文档节点必须以这种方式直接从容器中选择:
XmlNodeList documentNodeList = sepaContainer.GetElementsByTagName(Document);

Ok i want to inform about the solution, maybe any one will find these topic:
The document node has to selected directly in that way from the container: "XmlNodeList documentNodeList = sepaContainer.GetElementsByTagName("Document");"

那么第一个条目的外部xml必须被规范化并转换为哈希。

then the outer xml of the first entry have to be canonized and convert to hash.

还有第一个发布值:7DDB2138E8C91037DA7A6E9552478C59A2AACE26F8112EBC8012A8DE11592025
错误的正确值将是38B862BD35B95D8CB20448153B5F6F73B3657EB1BC81CF11D3491D16EEA94009

also the first posted value: 7DDB2138E8C91037DA7A6E9552478C59A2AACE26F8112EBC8012A8DE11592025 is wrong the correct value will be 38B862BD35B95D8CB20448153B5F6F73B3657EB1BC81CF11D3491D16EEA94009