我在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
?有人可以解释一下吗?
答案 0 :(得分:4)
首先,您对MD4()
的调用为string
和digest
数组提供了错误的地址:通过使用&
,您将获得数组的地址({{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