如果已知所有消息都具有某个固定长度并且已知某些字节,是否可以优化 MD5 实现?

Can a MD5 implementation be optimized if all message are known to be of a certain fixed length and with certain bytes known?

非常不言自明的问题。 我有一组消息,每条消息在某些字节偏移量中都具有相同的已知数据。

示例:

bytes 1 to 32 -> is always the value 42
bytes 128 to 156 -> is always the value 128

但是对于不同的消息,每隔一个字节都是不同的。

假设每条消息的长度为 256 字节。

有了像上面这样的约束(或类似的约束),是否可以优化每条消息的 MD5 实现(比如用 C 语言)?任何关于算法的指示都会有所帮助。

鉴于现有的高度优化的 MD5 实现(例如,将 SSE 用于 x86),您可以对其进行修改。

您可以在处理前 32 个字节后预先计算状态,并且每次都从那里开始,加载这些常量而不是计算它们。这将削减两个 128 位的工作块。 MD5 内部 (wikipedia) 使用 128 位(16 字节)状态,但以 512 位(64 字节)的块处理消息。所以你实际上只知道消息第一块的一半:/

但是如果我正确地阅读了伪代码,只有第一轮的前半部分只涉及前 32 个字节的数据及其自身,所以这就是您可以预先计算的数量。 (if 0 ≤ i ≤ 15 then ... g := i 部分:g = 0..7 是低八位 32 位字,即前 32 个字节)。

但在那之后,未知数据(来自第 3 个和第 4 个 16 字节)开始混入(XORed 等),之后就没有任何简单的节省,可能 none甚至可能。当一个输入是已知常量时,普通 CPU 上的 XOR 并不快。 (在 硬件 中,是的,它是一个 NOT 或一条线,具体取决于常数。)如果已知数据是 (或者可能是全部 -的),可能会有所不同。

所以最重要的是,通过这种方式操作,您可能会从 256 字节消息的总时间中节省几个 %,为 4 轮中的第一轮节省 1 轮(共 4 轮)的一部分 要与 asm 或 SIMD 内部函数优化实现竞争,您需要使用它们相同的实现技术,只需从加载一些常量开始,然后跳到第一轮中途的某个点。


因为这看起来像是一个假设,如果您知道前 64 个字节,您可以跳过处理这些字节的所有“轮次”,只从第二个 64 个字节开始具有预先计算的 128 位状态。

另请注意,248 字节的消息长度会(显着?)更快,因为 MD5 填充消息以便有空间附加 64 位(8 字节)消息长度并且仍然是 64 的倍数字节。因此消息长度 > 248 必须执行另一组 4 轮,其中大部分为零。


我认为已知的 128..156 范围没有帮助。之前有未知数据,每一轮MD5的所有操作都依赖于之前的内部状态。请记住,MD5 被设计为加密安全散列。 (现在已知它的位长不如我们希望的那么安全,但我认为已经发现的弱点即使有帮助也不会有多大帮助 - 向前计算它仍然很快。)

可能甚至不值得在中间对那些已知字节进行特殊封装;只需将它们作为您对缓冲区其余部分的循环的一部分即可。您所能保存的只是数据的初始加载,但它少于整个缓存行,因此您甚至不会避免触及该行。

为了跳出循环不值得额外的分支。