为什么输入相同的值时哈希值不同?在 C 中

Why is it hashed differently when the same value is entered? In C

我正在使用 SHA1 加密我的 ID。

但是,即使我输入相同的 ID,它的哈希值也会不同。

这是我的代码:

#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>

char *sha1_hash(char *input_url, char *hashed_url) {
    unsigned char hashed_160bits[20];
    char hashed_hex[41];
    int i;
    
    SHA1(input_url, 160, hashed_160bits);

    for(i=0; i < sizeof(hashed_160bits); i++) {
        sprintf(hashed_hex + i*2, "%02x", hashed_160bits[i]);
    }        

    strcpy(hashed_url, hashed_hex);

    return hashed_url;
}

int main()
{   
    char *input_url;
    char *hashed_url;
    
    while(1) {
        input_url = malloc(sizeof(char)* 1024);
        hashed_url = malloc(sizeof(char) * 1024);
        
        printf("input url> ");
        scanf("%s", input_url);
        
                if (strcmp(input_url, "bye") == 0) {
                        free(hashed_url);
                        free(input_url);
                        break;
                }

        sha1_hash(input_url, hashed_url);
    
        printf("hashed_url: %s\n", hashed_url);
        free(hashed_url);
        free(input_url);
        }

    return 0;
}

如果我为第一次尝试和第二次尝试输入相同的值,它的散列值将不同,但第三次尝试的散列值将与第二次尝试相同。

我认为动态分配有问题,但我想不出解决它的方法。

问题似乎出在您分配的未初始化内存上。

malloc为你预留内存,但内容是'whatever has been in there before'。由于您不仅对字符串内容进行哈希处理,而且对整个缓冲区进行哈希处理,因此每次都会得到不同的结果。

尝试在缓冲区上使用 calloc、运行 memset 或将哈希限制为 strlen(input) 看看是否有帮助。

SHA1(input_ID, 160, hashed_ID_160bits);

那一行是错误的。你总是得到 160 个字节的散列。我假设您只需要输入文本的哈希值,所以使用该长度:

SHA1(input_ID, strlen(input_ID), hashed_ID_160bits);

SHA1 始终生成 160 位的散列,因此您无需将 160 作为参数传递。如果你想要不同大小的 SHA 散列,你需要使用不同的函数,documented here,然后当然修改其余代码以匹配该散列大小。


为什么你在不同的时间得到不同的哈希值是因为访问了 malloc 缓冲区的未初始化部分。这是未定义的行为,所以“任何事情”都可能发生,尝试弄清楚到底发生了什么通常没有用,因为它不一定非常确定。如果你想深入挖掘,你可以使用调试器来检查不同循环迭代中的内存地址和内容,看看到底发生了什么变化。但是,由于这是未定义的行为,因此当您尝试在调试器下 运行 或添加调试打印时,错误代码的行为不同是众所周知的。

您没有正确调用 SHA1

SHA1(input_ID, 160, hashed_ID_160bits);

第二个参数是要哈希的数据长度。您而是传递散列中的位数。结果,您正在读取 input_ID 中包含的字符串的末尾进入未初始化的内存,并且可能超过分配的内存段的末尾。这会触发 undefined behavior.

你反而想要:

SHA1(input_ID, strlen(input_ID), hashed_ID_160bits);