【问题标题】:Returning wrong MD5 hash in C在 C 中返回错误的 MD5 哈希
【发布时间】:2013-03-30 07:50:10
【问题描述】:

我正在尝试使用来自http://www.arp.harvard.edu 的原始/未触及的 md5.h 和 md5c.c 为字符串 "Hello World" 生成 MD5 哈希。但我的结果与我测试过的所有 md5 在线工具不同。这段代码有什么问题?谢谢。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "md5.h"

void MD5hash(unsigned char *data, unsigned int dataLen, unsigned char *digest) {
    MD5_CTX c;
    MD5Init(&c);
    MD5Update(&c, data, dataLen);
    MD5Final(digest, &c);
}

int main(int argc, const char * argv[]) {
    unsigned char digest[16];
    const char *s = "Hello World";
    unsigned int l = (unsigned int)strlen(s);

    MD5hash((unsigned char *)s, l, digest);
    for(int i = 0; i < 16; ++i)
         printf("%02x", digest[i]);
    return 0;
}

// My result: f2877a72c40494318c4b050bb436c582
// But online tools output: b10a8db164e0754105b7a99be72e3fe5

【问题讨论】:

  • 附带说明 - 我已经根据 OpenSSL 的 MD5 实现编译了您的代码 - 它按预期工作!所以确实md5.c你尝试使用可能只是以某种方式被破坏。

标签: c string hash md5


【解决方案1】:

正如@vipw 提到的,填充存在问题。此 MD5 实现无法正确管理不是 MD5 块大小(512 位/64 字节)倍数的消息大小的填充。

要修复它,请替换:

const char *s = "Hello World";

通过

const char s[64] = "Hello World";

编辑

在这个 MD5 实现中存在与可移植性相关的第二个问题。在md5.h 中有这个类型别名:

typedef unsigned long int UINT4;

在 Linux x86_64 系统(您正在使用)上,必须将其更改为:

typedef unsigned int UINT4;

【讨论】:

  • 这应该如何改变什么? MD5_Update() 无论如何都会处理 strlen(s) 字节。
  • 有任何功能修改s吗?您是否暗示该程序调用了未定义的行为?
  • @CodePainters 显然实现被破坏并且读取的长度超过了您在dataLen 中传递的长度。
  • 好的,我发现了第二个问题:对于 x86_64 Linux,md5.h 中的 typedef UINT4 应该更新为 unsigned int
  • 或者你可以使用stdint.h中的可移植类型,uint32_t总是四个字节。
【解决方案2】:

您遇到了填充问题。 MD5 哈希算法适用于 512 位块。当您的最终块小于 512 位时,需要对其进行填充。在您的示例中,第一个块也是最后一个块,因为它小于 512 位。

填充格式称为Merkle–Damgård construction

您可以找到一些包含填充 here 的伪代码。

【讨论】:

  • MD5Finalize() 不应该执行所有必要的填充吗?
  • @vipw,你是对的。我稍后会尝试(我的孩子现在在家里哭)。谢谢。
  • 只是我的好奇心 - 为什么这个答案被接受了,而 ouah 的答案要好得多?
  • @CodePainters 在测试之前似乎接受得太早了。
猜你喜欢
  • 2017-07-07
  • 1970-01-01
  • 2020-12-08
  • 1970-01-01
  • 2019-12-20
  • 2020-06-01
  • 2015-04-13
  • 1970-01-01
相关资源
最近更新 更多