我用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
?
1条答案
按热度按时间rqqzpn5f1#
首先,您对
MD4()
的调用为string
和digest
数组提供了错误的地址:通过使用&
,您将获得数组的地址(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哈希:
字符串
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')来结束字符串:型
sprintf
将打印2个字符到mdString
数组,每当它从digest
馈送1个字节时,因此您需要为digest
中的每个位置在mdString
中提前2个索引位置,因此使用i * 2
。下面的代码与使用i * 2
的结果相同:型