在ABAP中计算文件的MD5哈希值

4
我希望在ABAP中生成文本文件的MD5哈希值。我没有找到任何标准解决方案来为非常大的文件生成哈希值。函数模块CALCULATE_HASH_FOR_CHAR不能满足我的要求,因为它将字符串作为输入参数。虽然它适用于较小的文件,但是例如4 GB文件的情况下,无法构建如此大的字符串。
是否有人知道是否有标准的代码可以完成这个功能(我的谷歌搜索没有找到任何信息),或者有没有在ABAP中实现MD5算法以计算文件的哈希值的人?

你真的想为一个4 GB的文本文件创建哈希吗?在这种情况下,最好调用一些外部工具... - vwegert
@vwegert:是的,我确定。例如调用系统命令是不可能的,因为首先,我希望它是平台无关的;其次,安全团队不会允许在生产环境中进行任何系统命令调用;第三,哈希值需要与头信息中的信息进行比较,并且必须在ABAP中完成。 - Jagger
3个回答

6
看起来由于语言不允许在计算过程中出现算术溢出,因此似乎无法在ABAP中实现这个算法。这也回答了为什么SAP系统迄今为止还没有实现它的问题。无论如何,似乎没有其他办法,只能调用一个外部工具,但很遗憾,这几乎不是平台无关的。
编辑:好吧!在René的大力帮助和Java中快速MD5实现的代码的帮助下,我创建了ABAP中MD5算法的实现。该实现允许使用更多字节更新计算出的哈希值,这些字节当然可能来自不同的源。
到目前为止还没有接受文件的方法,但大部分工作已经完成。
代码中包含了一些简单的ABAP单元测试,这也记录了如何使用它。

感谢分享你的工作 :) 我已经进行了几次测试,目前看来它似乎正常工作。但是速度真的很慢;对于我正在测试的系统,处理1MB文件需要大约6分钟的时间来进行哈希处理。 - René
运行时分析告诉我,位左移方法占用约65%的时间,位加方法占用约20%的时间。看来我得找到一种优化这些方法的方式了。 - René
我尝试了一个2MB的文件,花了略微超过13分钟。在我的情况下,运行时分析显示左移方法使用的时间占了75%。 - Jagger
另一台机器上进行了另一个操作系统的测试。文件大小为1.2 MB,处理时间为3:30。在left_shift_i的开头进行了一些微调:CATCH SYSTEM-EXCEPTIONS arithmetic_errors = 4 OTHERS = 8. returning = value * 2 ** positions. ENDCATCH. IF sy-subrc <> 0. *your code* ENDIF. 运行时间缩短至2分51秒。 - Jagger
我已经更新了zcl_bitwise gist,并为left_shift_i方法提供了新的实现。现在它的速度快了4倍。我会尽快更改其他方法(可能是周一)。 - René
显示剩余4条评论

2
也许您可以按照建议的方法,将文件分块读取,每块大小为几兆字节,并使用推荐的函数创建哈希列表。然后使用生成的哈希列表创建一个单一的顶级哈希。

很抱歉,根据条件f(x1 + x2 + ... +xn) = f(x1) + f(x2) + ... + f(xn),MD5哈希函数无法满足此要求,所以这是不可能的。 - Jagger
你确定吗?其他语言似乎有这样的实现,允许你以这种方式处理大文件。例如在PHP中。 - René
是的,我非常确定。PHP中的函数是hash_update。在ABAP中似乎没有这样的函数。CALCULATE_HASH_FOR_RAWCALCULATE_HASH_FOR_CHAR不是这种方式工作的。它们只是计算给定字符串或字节序列的哈希值,您不能通过提供更多的字节来继续计算哈希值。 - Jagger
我非常绝望,以至于我开始编写带有“update”函数的MD5算法实现。不幸的是,我遇到了“CX_SY_ARITHMETIC_OVERFLOW”异常。有人知道是否有选项可以关闭在ABAP中检查是否存在算术溢出吗? - Jagger
谢谢!我已经在使用你的位移操作。现在我会尝试你的add方法,因为看起来这是我目前唯一需要的。 - Jagger
显示剩余2条评论

1

SDN通常是寻找ABAP相关解决方案的很好起点。我能够找到这篇文章:http://scn.sap.com/thread/1483479

作者建议:

  • 上传.txt文件,但作为BIN。
  • 使用函数MD5_CALCULATE_HASH_FOR_RAW计算哈希码

您能否以二进制格式获取文件并使用MD5_CALCULATE_HASH_FOR_RAW

编辑:这篇文章甚至有一个更详细的答案,使用CALCULATE_HASH_FOR_RAWhttp://scn.sap.com/thread/1298723

Shivanand Kalagi的回答摘录:

STR_LEN = XSTRLEN( DATA ).

CALL FUNCTION 'CALCULATE_HASH_FOR_RAW'
  EXPORTING
    ALG            = 'MD5'
    DATA           = DATA
    LENGTH         = STR_LEN
  IMPORTING
    HASH           = L_MD5_HASH.

很抱歉,这个方法不会奏效,因为这个函数模块与CALCULATE_HASH_FOR_CHAR所述的完全相同,所有数据都必须加载到一个内部表格DATA中,对于8GB文件来说这没有任何意义。 - Jagger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接