使用openssl进行MD4哈希,将结果保存到char数组中

时间:2013-07-13 17:22:01

标签: c openssl

我在C中用openssl写了一个简单的例子。我想从我的消息中计算MD4哈希,但我想将结果保存到char数组中。继承我的代码和评论,这将有助于您了解我想要实现的目标:

#include <string.h>
#include <openssl/md4.h>
#include <stdio.h>

int main()
{
    unsigned char digest[MD4_DIGEST_LENGTH];
    char string[] = "hello world";

    // run md4 for my msg
    MD4((unsigned char*)&string, strlen(string), (unsigned char*)&digest);

    // save md4 result into char array - doesnt work
    char test[MD4_DIGEST_LENGTH];
    sprintf(test, "%02x", (unsigned int)digest);
    for(int i = 0; i < MD4_DIGEST_LENGTH; i++)
        printf("%02x", test[i]);
    printf("\n\n");

    // print out md4 result - works, but its not intochar array as I wanted it to be
    for(int i = 0; i < MD4_DIGEST_LENGTH; i++)
        printf("%02x", digest[i]);
    printf("\n\n");

    // works but i dont understand why 'mdString' is 33 size
    char mdString[33];
    for(int i = 0; i < MD4_DIGEST_LENGTH; i++)
    // and I also dont get i*2 in this loop
         sprintf(&mdString[i*2], "%02x", (unsigned int)digest[i]);
    printf("md4 digest: %s\n", mdString);

    return 0;
}

问题是,为什么下面的代码不起作用,它显示的不同md4值应该是:

char test[MD4_DIGEST_LENGTH];
        sprintf(test, "%02x", (unsigned int)digest);
        for(int i = 0; i < MD4_DIGEST_LENGTH; i++)
            printf("%02x", test[i]);
        printf("\n\n");

我怎么知道应该是mdString的大小?为什么在最后一个循环中有i*2?有人可以解释一下吗?

1 个答案:

答案 0 :(得分:4)

首先,您对MD4()的调用为stringdigest数组提供了错误的地址:通过使用&,您将获得数组的地址({{1 }),而不是第一个字符的地址。 由于您明确地将char **&string强制转换为&digest,因此编译器不会向您发出警告。删除演员表,您将收到此警告:

unsigned char*

所以请用这种方式调用warning: passing argument 1 of 'MD4' from incompatible pointer type

MD4()

我个人更喜欢避免显式地转换指针,除非它确实是必要的,这样你就可以更容易地捕获错误的类型转换。

接下来,您尝试使用MD4(string, strlen(string), digest);sprintf()转换为十六进制整数:digest。 这里有两个错误:(a)因为sprintf(test, "%02x", (unsigned int)digest);本质上是一个字符指针,即:内存地址,你将这个地址转换为无符号整数,然后将那个整数转换为十六进制; (b)你需要遍历digest的元素并将每个元素转换为一个字符,digest不会为你做这个!

我发现,鉴于犯了错误,你可能对C比较陌生,但不要绝望,犯错是学习的方法! :)

如果你买得起这本书,我强烈推荐Stephen Prata的“C Primer Plus”。对于任何开始编程的人来说,这是一个很好的介绍,当你已经熟悉这门语言时,这是一个非常完整的参考供以后使用。 否则,网上有大量资料,谷歌搜索“C指针教程”将返回几个有用的结果。

希望这有帮助!


编辑:

忘记评论其他有效的代码片段,但使用33个字节来存储字符串化的MD4哈希:

snprintf

// works but i dont understand why 'mdString' is 33 size char mdString[33]; for(int i = 0; i < MD4_DIGEST_LENGTH; i++) // and I also dont get i*2 in this loop sprintf(&mdString[i*2], "%02x", (unsigned int)digest[i]); printf("md4 digest: %s\n", mdString); states的openssl联机帮助页,其哈希值为16个字节。 知道这一点,以及每个unsigned char可以保存0到255之间的值这一事实,MD4()中任何单个元素的最大十六进制表示形式为0xFF,换句话说,每个unsigned char为2个ASCII字符。

digest(33)的大小显得神秘的原因是因为msString应该用于计算数组的大小:你需要2个字符来表示{中的每一个元素{1}} + 1 null终结符('\ 0')结束字符串:

MD4_DIGEST_LENGTH

digest只要从char mdString[(MD4_DIGEST_LENGTH * 2) + 1]; 输入1个字节,就会向sprintf数组打印2个字符,因此您需要在mdString中为每个位置提前2个索引位置digest,因此使用mdString。以下结果与使用digest

的结果相同
i * 2