为什么输入相同的值时哈希值不同?在 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);
我正在使用 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);