【问题标题】:How to access millions of bits for hashing如何访问数百万位进行散列
【发布时间】:2013-03-29 18:27:09
【问题描述】:

我正在对一个可执行文件进行 MD5 散列。我使用 python 脚本将二进制文件从可执行文件读取到文本文件中,但是如果我要将这个构造的文件读入 C 程序,我将处理 MB 的数据,因为 1 和 0 被视为chars,每个 1 位数字占用 8 位。是否可以将这些作为单个位读取?如果我制作一个 10MB 的数组来保存二进制转换长度和哈希填充可能需要的所有字符,那么程序的性能会有多糟糕?如果这是不可想象的,是否有更好的方法来处理数据?

【问题讨论】:

  • 首先,不要使用 MD5——在当今时代使用它没有任何合理的理由。
  • 这是我正在进行的研究的第一步。最重要的是让自己熟悉散列。之后我们将切换到更好的哈希算法。
  • 真的没有意义——基本上你所做的一切(或者你提到的一切)都是散列。所以基本上,你是在谈论做某事,然后完全抛弃它,从第一天开始重新开始。如果您从 1 和 0 作为字符的字符串开始,这将是双重事实,正如您所描述的那样。
  • @Dolphiniac 您是说您正在读取的文件每位使用一个字节吗?就像一个只有字符 01 的文本文件?
  • 我个人喜欢将我的位存储在 bytes 中。叫我疯子。

标签: c++ c binary char md5


【解决方案1】:

既然你标记了 C 和 C++ 的问题,我会选择 C。

是否可以将它们作为单个位读取?

是的,只需从文件中一次读取 8 个字节,然后将 1s 和 0s 连接起来形成一个新字节。你不需要为此创建一个 10MB 的数组。

首先,从文件中读取 8 个字节。读取的 char 值将转换为整数值(01),然后进行位移以生成一个新字节。

unsigned char bits[8];
while (fread(bits, 1, 8, file) == 8) {
    for (unsigned int i = 0; i < 8; i++) {
        bits[i] -= '0';
    }

    char byte = (bits[0] << 7) | (bits[1] << 6) |
                (bits[2] << 5) | (bits[3] << 4) |
                (bits[4] << 3) | (bits[5] << 2) |
                (bits[6] << 1) | (bits[7]     );

    /* update MD5 Hash here */
}

然后,您将使用新读取的字节更新您的 MD5 哈希。


编辑:由于典型的 MD5 实现必须在处理之前将输入分解为 512 位的块,因此您可以在实现本身中摆脱这种开销(虽然不推荐),并且只需从文件中读取 512 位(64 字节),然后直接更新哈希。

unsigned char buffer[64];
unsigned char bits[8];
unsigned int index = 0;

while (fread(bits, 1, 8, file) == 8) {
    for (unsigned int i = 0; i < 8; i++) {
        bits[i] -= '0';
    }

    buffer[index++] = (bits[0] << 7) | (bits[1] << 6) |
                      (bits[2] << 5) | (bits[3] << 4) |
                      (bits[4] << 3) | (bits[5] << 2) |
                      (bits[6] << 1) | (bits[7]     );

    if (index == 64) {
        index = 0;
        /* update MD5 hash with 64 byte buffer */
    }
}

/* This sends the remaining data to the MD5 hash function */
/* It's not likely that your file has exactly 512N chars */
if (index != 0) {
    while (index != 64) {
        buffer[index++] = 0;
    }
    /* update MD5 hash with the padded buffer. */
}

【讨论】:

  • 我个人会拍摄 (8 * N) 个字符,其中 N 是底层哈希算法的块大小。例如 SHA-1 具有 512 位块大小,SHA-2 (224,256) 同样是 512 位,SHA-2(384/512) 是 1024 位,等等...
  • 这是个好主意。在这种情况下,他必须在更新哈希之前读取 64 个字节。这样,他就不需要将输入处理成 512 位块的开销。
  • 他不会不得不这样做,但是任何自尊的哈希算法实现都只会坐在数据上,直到块大小已满或终止器被触发。例如,对于 SHA-1,读取 8*512 字符,将它们转换为字节,然后提交块可能至少有助于减少 hash-api-calls 的数量。当然,如果内存合理,则将其发挥到极致,您可以通过过滤器流式传输数据,该过滤器用实际字节填充 std::vector ,一旦完成位文件,发送单个 hash+finalize 中的向量。
  • 是的,那优化事情,但我在输入答案时更关心内存使用情况:/
  • 请问当文件中没有512字节的块时,上面编辑的算法会发生什么?另外,EOF 会如何影响它?
猜你喜欢
  • 2014-12-12
  • 2020-07-23
  • 2013-07-12
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
相关资源
最近更新 更多