如何为 XML 消息正文创建 SHA-256 哈希值
我正在尝试创建一个人类可读但可以验证为未修改的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这就是我实施该解决方案的方式。
This is how I implemented the solution.
你不是想重新发明轮子吗?
有
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.