使用OpenSSL进行MD4散列,并将结果保存到char数组中

mfuanj7w  于 2023-08-03  发布在  其他
关注(0)|答案(1)|浏览(129)

我用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 message
    MD4((unsigned char*)&string, strlen(string), (unsigned char*)&digest);

    // Save md4 result into a char array. It doesn’t 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. It works, but it's not into the char array as I wanted it to be
    for(int i = 0; i < MD4_DIGEST_LENGTH; i++)
        printf("%02x", digest[i]);
    printf("\n\n");

    // It works, but I don’t understand why 'mdString' is 33 size
    char mdString[33];
    for(int i = 0; i < MD4_DIGEST_LENGTH; i++)
    // And I also don’t 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

rqqzpn5f

rqqzpn5f1#

首先,您对MD4()的调用为stringdigest数组提供了错误的地址:通过使用&,您将获得数组的地址(char **),而不是第一个字符的地址。由于您显式地将&string&digest转换为unsigned char*,因此编译器不会警告您。删除这些转换,您将收到此警告:
warning: passing argument 1 of 'MD4' from incompatible pointer type
因此,可以这样调用MD4()
MD4(string, strlen(string), digest);
我个人倾向于避免显式地强制转换指针,除非真的有必要,这样你就可以更容易地捕捉到不正确的类型强制转换。
接下来,尝试使用sprintf()digest转换为十六进制整数:sprintf(test, "%02x", (unsigned int)digest);。这里有两个错误:(a)由于digest本质上是一个字符指针,即:内存地址,你把这个地址转换成一个无符号整数,然后把那个整数转换成十六进制;(B)你需要循环遍历digest的元素,并将每个元素转换为一个字符,snprintf不会为你做这件事!
我看到你可能是相对新的C给出的错误,但不要气馁,犯错误是学习的方式!:)
如果你买得起这本书,我强烈推荐斯蒂芬·普拉塔的《C初级读本》。这是一个伟大的介绍任何人开始编程,它是一个非常完整的参考,供以后使用时,你已经熟悉的语言。否则,网上有大量的材料,谷歌“C指针教程”会返回几个有用的结果。
希望这对你有帮助!
编辑:
忘记评论另一段代码,它确实工作,但使用33字节来存储字符串化的MD 4哈希:

// 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);

字符串
MD4()states的openssl手册页显示散列长度为16字节。知道这一点,以及每个unsigned char可以保存从0到255的值,那么digest中任何单个元素的最大十六进制表示是0xFF,换句话说,每个unsigned char 2个ASCII字符。
msString(33)的大小看起来很神秘的原因是因为MD4_DIGEST_LENGTH应该被用来计算数组的大小:你需要2个字符来表示digest中的每个元素+ 1个null terminator('\0')来结束字符串:

char mdString[(MD4_DIGEST_LENGTH * 2) + 1];


sprintf将打印2个字符到mdString数组,每当它从digest馈送1个字节时,因此您需要为digest中的每个位置在mdString中提前2个索引位置,因此使用i * 2。下面的代码与使用i * 2的结果相同:

for(int i = 0, j = 0; i < MD4_DIGEST_LENGTH; i++, j += 2)
     sprintf(&mdString[j], "%02x", (unsigned int)digest[i]);

相关问题