首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用openssl进行MD4哈希,将结果保存到字符数组中

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

Stack Overflow用户
提问于 2013-07-14 01:22:01
回答 1查看 1.4K关注 0票数 3

我用C语言写了一个简单的openssl示例,我想从我的消息中计算MD4散列,但我想将结果保存到一个字符数组中。下面是我的代码和注释,它将帮助您理解我想要实现的目标:

代码语言:javascript
复制
#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值不同于它应该显示的值:

代码语言:javascript
复制
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?有人能解释这个吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-07-14 02:34:44

首先,您对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语言比较陌生,但不要灰心,犯错才是学习的方法!:)

如果你买得起这本书,我强烈推荐Stephen Prata的"C Primer Plus“。对于任何刚开始编程的人来说,这是一本很好的入门书,也是一本非常完整的参考资料,可以在你已经熟悉这门语言的时候使用。另外,网上有很多资料,搜索"C指针教程“会返回几个有用的结果。

希望这能有所帮助!

编辑:

忘记注释另一段可以工作的代码,但使用33个字节来存储字符串化的MD4散列:

代码语言:javascript
复制
// 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字节长。知道这一点,并且每个无符号字符可以包含从0到255的值,那么digest中任何单个元素的最大十六进制表示是0xFF,换句话说,每个无符号字符有2个ASCII字符。

msString (33)的大小看起来很神秘,因为MD4_DIGEST_LENGTH应该用来计算数组的大小:您需要2个字符来表示digest中的每个元素+1个空终止符('\0')来结束字符串:

代码语言:javascript
复制
char mdString[(MD4_DIGEST_LENGTH * 2) + 1];

每当从mdString输入1个字节时,sprintf都会将2个字符输出到digest数组中,因此需要在mdString中为digest中的每个位置前进2个索引位置,因此使用了i * 2。以下命令会产生与使用i * 2相同的结果

代码语言:javascript
复制
for(int i = 0, j = 0; i < MD4_DIGEST_LENGTH; i++, j += 2)
     sprintf(&mdString[j], "%02x", (unsigned int)digest[i]);
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17632485

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档