我需要实现 MD5 校验和来验证 XML 文件中的 MD5 校验和,其中包括所有 XML 标记并且从我们的客户端接收到。接收到的 MD5 校验和的长度是 32 字节的十六进制数字。
在校验和计算之前,我们需要在接收到的 XML 文件中设置 MD5 校验和字段应为 0,并且我们必须独立计算和验证接收到的 XML 文件中的 MD5 校验和值。
我们的应用程序是用 C 实现的。请帮助我如何实现它。
谢谢
这直接取决于用于 XML 解析的库。然而,这很棘手,因为您不能将 MD5 嵌入 XML 文件本身,因为在将校验和嵌入其中之后,除非您仅从特定元素执行校验和。据我了解,您独立收到 MD5 吗?它是从整个文件中计算出来的,还是仅从标签/内容中计算出来的?
确切的解决方案取决于使用的代码。
根据您的评论,您需要执行以下步骤:
您应该使用 MD5 的公共域实现,而不是自己编写。我听说 Colin Plumb 的版本被广泛使用。
不要重新发明轮子,使用经过验证的现有解决方案:http ://userpages.umbc.edu/~mabzug1/cs/md5/md5.html
顺便说一句,这是我在谷歌上搜索“md5 c implementation”时出现的第一个链接。
这是比较恶心的。建议的方法似乎暗示您需要将 XML 文档解析为 DOM 树之类的东西,找到 MD5 校验和并将其存储以供将来参考。然后,在重新序列化文档并计算它的 MD5 哈希值之前,您将用 0 替换校验和。这一切听起来可行但可能很棘手。我看到的主要困难是您对文档的新序列化可能与原始序列化不同,并且(与 XML 无关)差异,例如在属性值周围使用单引号或双引号,添加换行符甚至不同的编码将导致哈希不同。如果你走这条路,你需要确保你的应用程序和用于创建文档的过程首先做出相同的选择。对于这类问题,规范 XML 是标准解决方案(http://www.w3.org/TR/xml-c14n)。
但是,我会做一些不同的事情。如果运气好的话,应该很容易编写一个正则表达式来定位文件中的 MD5 哈希并将其替换为 0。然后您可以使用它来获取哈希并在重新计算哈希之前在 XML 文件中将其替换为 0。这回避了解析、更改和重新序列化 XML 文档的所有可能问题。为了说明,我将假设哈希 '33d4046bea07e89134aecfcaf7e73015' 存在于 XML 文件中,如下所示:
<docRoot xmlns='some-irrelevant-uri>
<myData>Blar blar</myData>
<myExtraData number='1'/>
<docHash MD5='33d4046bea07e89134aecfcaf7e73015' />
<evenMoreOfMyData number='34'/>
</docRoot>
(我称之为 hash.xml),MD5 应该被 32 个零替换(所以散列是正确的)并使用 perl、md5 和 bash 在 shell 命令行上说明过程。(鉴于正则表达式和散列库的存在,希望将其翻译成 C 语言不会太难。)
分解问题,您首先需要能够找到文件中的哈希:
perl -p -e'if (m#<docHash.+MD5="([a-fA-F0-9]{32})#) {$_ = "$1\n"} else {$_ = ""}' hash.xml
(这通过寻找 docHash 元素的 MD5 属性的开头,允许可能的其他属性,然后抓取接下来的 32 个十六进制字符来工作。如果找到它们,它会将它们插入神奇的 $_ 变量中,如果没有,它会设置$_ 为空,然后为每一行打印 $_ 的值。这将导致打印字符串“33d4046bea07e89134aecfcaf7e73015”。)
然后你需要计算文件的哈希值,并用零替换:
perl -p -e's#(<docHash.+MD5=)"([a-fA-F0-9]{32})#$1"000000000000000000000000000000#' hash.xml | md5
(其中正则表达式几乎相同,但这次十六进制字符被零替换并打印整个文件。然后通过 md5 散列程序将结果管道化来计算其 MD5。把它和一点放在一起bash 给出:
if [ `perl -p -e'if (m#<docHash.+MD5="([a-fA-F0-9]{32})#) {$_ = "$1\n"} else {$_ = ""}' hash.xml` = `perl -p -e's#(<docHash.+MD5=)"([a-fA-F0-9]{32})#$1"000000000000000000000000000000#' hash.xml | md5` ] ; then echo OK; else echo ERROR; fi
它执行这两个小命令,比较输出并在输出匹配时打印“OK”,如果不匹配则打印“ERROR”。显然这只是一个简单的原型,并且使用了错误的语言,我认为它说明了最直接的解决方案。
顺便说一句,为什么要将散列放在 XML 文档中?据我所知,与在侧通道上传递哈希相比(甚至像在名为 documentname.md5 的第二个文件中这样简单的东西)相比,它没有任何优势,并且使哈希验证更加困难。