如何为 XML 消息正文创建 SHA-256 哈希值

发布于 2024-12-04 23:28:59 字数 2365 浏览 1 评论 0原文

我正在尝试创建一个人类可读但可以验证为未修改的 XML 文件。

我采用的方法如下:

  • 生成 xml 消息正文(应用规范化 (C14N))
  • 生成消息正文的哈希值 (SHA-256)
  • 加密哈希值 (AES-256)
  • 使用加密的消息生成消息头hash

我在这个任务的每个阶段都遇到了问题,但当前的问题是从 XML 主体生成哈希值。

我收到异常“此 XmlReader 不支持 ReadContentAsBase64 方法。使用 CanReadBinaryContent 属性来查明阅读器是否实现它。”但我不知道如何实现 XElement 的读取。

下面是 xml 的一个示例

<?xml version="1.0" encoding="UTF-8"?>
<Application>
    <MessageHeader>
        <MessageID>00000001</MessageID>
        <MessageCheck>
            dHPHxMJGgDCHtFttgPROo24yi+R1RGx6Ahno2r0nV7zrcgR2+BX4f+RmNCVCsT5g
        </MessageCheck>
    </MessageHeader>
    <MessageBody>
        <Receipt>
            <Status>OK</Status>
            <FormReference>E00000000001</FormReference>
        </Receipt>
    </MessageBody>
</Application>

,这是我一直尝试但无济于事的代码:

/// <summary>
/// Convert the message body into a Hash value
/// </summary>
/// <param name="MessageBody">XElement holding all the message body XML nodes</param>
/// <returns>a base 64 string representing the hash code</returns>
private string GenerateMessageBodyHash(XElement MessageBody)
{
    string hash = string.Empty;
    try
    {
        // Convert the XElement into a stream of data
        using (XmlReader xr = MessageBody.CreateReader())
        {
            // Now that we have a reader, lets read the data into a byte array
            List<byte> dataList = new List<byte>();

            byte[] buffer = new byte[1000];
            int fileIndex = 0;
            int bytesRead = 0;

            while ((bytesRead = xr.ReadContentAsBase64(buffer, fileIndex, buffer.Length)) != 0 )
            {
                // Update the position into the file
                fileIndex += bytesRead;

                //add the data into the list
                dataList.AddRange(buffer);

                // reset the buffer
                buffer = new byte[1000];
            }

            SHA256 shaM = new SHA256Managed();
            hash = Convert.ToBase64String( shaM.ComputeHash( dataList.ToArray() ) );
        }
    }
    catch (Exception ex)
    {
        // TODO: Add some logging in here
    }

    return hash;
}

I'm trying to create an XML file that is human readable but can be verified as being unmodified.

The approach I am taking is as follows:

  • Generate the xml message body (canonicalization applied (C14N))
  • Generate the hash value for the message body (SHA-256)
  • Encrypt the hash value (AES-256)
  • Generate a message header using the encrypted hash

I'm hitting problems at every stage of this task but the current issue is generating the hash value from the XML body.

I get an exception "ReadContentAsBase64 method is not supported on this XmlReader. Use CanReadBinaryContent property to find out if a reader implements it." but I don't know how else to implement the reading of the XElement.

An example of the xml is below

<?xml version="1.0" encoding="UTF-8"?>
<Application>
    <MessageHeader>
        <MessageID>00000001</MessageID>
        <MessageCheck>
            dHPHxMJGgDCHtFttgPROo24yi+R1RGx6Ahno2r0nV7zrcgR2+BX4f+RmNCVCsT5g
        </MessageCheck>
    </MessageHeader>
    <MessageBody>
        <Receipt>
            <Status>OK</Status>
            <FormReference>E00000000001</FormReference>
        </Receipt>
    </MessageBody>
</Application>

And here is the code I've been trying to get working to no avail:

/// <summary>
/// Convert the message body into a Hash value
/// </summary>
/// <param name="MessageBody">XElement holding all the message body XML nodes</param>
/// <returns>a base 64 string representing the hash code</returns>
private string GenerateMessageBodyHash(XElement MessageBody)
{
    string hash = string.Empty;
    try
    {
        // Convert the XElement into a stream of data
        using (XmlReader xr = MessageBody.CreateReader())
        {
            // Now that we have a reader, lets read the data into a byte array
            List<byte> dataList = new List<byte>();

            byte[] buffer = new byte[1000];
            int fileIndex = 0;
            int bytesRead = 0;

            while ((bytesRead = xr.ReadContentAsBase64(buffer, fileIndex, buffer.Length)) != 0 )
            {
                // Update the position into the file
                fileIndex += bytesRead;

                //add the data into the list
                dataList.AddRange(buffer);

                // reset the buffer
                buffer = new byte[1000];
            }

            SHA256 shaM = new SHA256Managed();
            hash = Convert.ToBase64String( shaM.ComputeHash( dataList.ToArray() ) );
        }
    }
    catch (Exception ex)
    {
        // TODO: Add some logging in here
    }

    return hash;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光礼记 2024-12-11 23:28:59

这就是我实施该解决方案的方式。

/// <summary>
/// Convert the message body into a Hash value
/// </summary>
/// <param name="MessageBody">XElement holding all the message body XML nodes</param>
/// <returns>a base 64 string representing the hash code</returns>
private string GenerateMessageBodyHash(XElement MessageBody)
{
    string hash = string.Empty;
    try
    {
        using( MemoryStream ms = new MemoryStream() )
        {
            XmlWriterSettings xws = new XmlWriterSettings();
            xws.OmitXmlDeclaration = true;
            xws.Indent = false;

            using( XmlWriter xw = XmlWriter.Create( ms, xws ))
            {
                // Assign the xml to be written to the writer and then memory stream
                MessageBody.WriteTo(xw);

                SHA256 shaM = new SHA256Managed();
                hash = Convert.ToBase64String(shaM.ComputeHash( ms ));
            }
        }
    }
    catch (Exception ex)
    {
        Log.WriteLine(Category.Warning, "Exception detected generating the XML hash", ex);
    }

    return hash;
}

This is how I implemented the solution.

/// <summary>
/// Convert the message body into a Hash value
/// </summary>
/// <param name="MessageBody">XElement holding all the message body XML nodes</param>
/// <returns>a base 64 string representing the hash code</returns>
private string GenerateMessageBodyHash(XElement MessageBody)
{
    string hash = string.Empty;
    try
    {
        using( MemoryStream ms = new MemoryStream() )
        {
            XmlWriterSettings xws = new XmlWriterSettings();
            xws.OmitXmlDeclaration = true;
            xws.Indent = false;

            using( XmlWriter xw = XmlWriter.Create( ms, xws ))
            {
                // Assign the xml to be written to the writer and then memory stream
                MessageBody.WriteTo(xw);

                SHA256 shaM = new SHA256Managed();
                hash = Convert.ToBase64String(shaM.ComputeHash( ms ));
            }
        }
    }
    catch (Exception ex)
    {
        Log.WriteLine(Category.Warning, "Exception detected generating the XML hash", ex);
    }

    return hash;
}
快乐很简单 2024-12-11 23:28:59

你不是想重新发明轮子吗?

System.Security.Cryptography.Xml.SignedXml 类专为此目的而设计。

Aren't you trying to reinvent the wheel?

There's the System.Security.Cryptography.Xml.SignedXml class designed for such purposes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文