如果已知所有消息都具有特定的固定长度和特定的字节,是否可以优化 MD5 实现?

the*_*ang 0 c optimization assembly md5 cryptography

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

例子:

bytes 1 to 32 -> is always the value 42
bytes 128 to 156 -> is always the value 128
Run Code Online (Sandbox Code Playgroud)

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

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

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

Pet*_*des 5

给定一个现有的高度优化的 MD5 实现(例如,对 x86 使用 SSE),您可以修改它。

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

但是,如果我正确阅读了伪代码,则只有第一轮的前半部分仅涉及前 32 个字节的数据及其自身,因此您可以预先计算尽可能多的数据。(if 0 ? i ? 15 then...g := i部分:g = 0..7 是低 8 个 32 位字,即前 32 个字节)。

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

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


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

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


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

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

为了跳出循环而进行额外的分支是不值得的。