使用strcmp对比哈希值时else语句返回错误结果(已更新)
解决文件哈希生成与比对的问题
我明白你现在的需求是生成文件的SHA512哈希并存储,同时能比对当前文件哈希和已存储的哈希是否一致。你的代码里确实有几个关键问题需要修正,我来一步步帮你解决:
原代码的主要问题
- else块未重新计算当前文件哈希:你在else块里直接使用了
c[i],但这个变量是第一次生成哈希时的结果,不是当前文件的最新哈希,这会导致比对完全错误。 - 哈希格式不匹配:你用
sprintf(ch1, "%d", c[i])把哈希字节转成了十进制数字字符串,但存储的哈希是十六进制格式的,两者无法正确比对。 - 读取存储哈希的方式错误:存储的哈希是一行完整的十六进制字符串,不需要循环读取,直接读取整个字符串即可。
- 代码重复:哈希计算的逻辑在if块里写了一遍,比对时又需要重复写,应该封装成函数避免重复调用。
修正后的完整实现
首先,我们把哈希计算的逻辑封装成一个可复用的函数,这样无论是生成哈希还是比对,都可以调用同一个函数:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <openssl/sha.h> // 封装哈希计算函数:计算指定文件的SHA512哈希,存入out_hash缓冲区(需至少SHA512_DIGEST_LENGTH*2 +1字节) int calculate_sha512(const char *file_path, char *out_hash) { FILE *file = fopen(file_path, "rb"); if (!file) { perror("Failed to open file"); return -1; } SHA512_CTX mdContext; SHA512_Init(&mdContext); unsigned char data[1024]; size_t bytes; while ((bytes = fread(data, 1, sizeof(data), file)) != 0) { SHA512_Update(&mdContext, data, bytes); } unsigned char digest[SHA512_DIGEST_LENGTH]; SHA512_Final(digest, &mdContext); fclose(file); // 将哈希字节转换为十六进制字符串 for (int i = 0; i < SHA512_DIGEST_LENGTH; i++) { sprintf(out_hash + (i * 2), "%02x", digest[i]); } out_hash[SHA512_DIGEST_LENGTH * 2] = '\0'; // 确保字符串以null结尾 return 0; } int main() { // 假设这些变量是你预先定义的 const char *hashInBuf = "your_target_file.bin"; // 要计算哈希的目标文件路径 const char *hashOutBuf = "hash_store.txt"; // 存储哈希的文件路径 char current_hash[SHA512_DIGEST_LENGTH * 2 + 1]; if (calculate_sha512(hashInBuf, current_hash) != 0) { return 1; } // 检查哈希存储文件是否存在 if (access(hashOutBuf, F_OK) == -1) { // 哈希文件不存在,生成并存储哈希 FILE *hash_file = fopen(hashOutBuf, "wt"); if (!hash_file) { perror("Failed to open hash file for writing"); return 1; } fprintf(hash_file, "%s", current_hash); printf("Generated and stored hash: %s\n", current_hash); fclose(hash_file); } else { // 哈希文件存在,读取存储的哈希并比对 char stored_hash[SHA512_DIGEST_LENGTH * 2 + 1]; FILE *hash_file = fopen(hashOutBuf, "r"); if (!hash_file) { perror("Failed to open hash file for reading"); return 1; } // 读取完整的哈希字符串 if (fscanf(hash_file, "%s", stored_hash) != 1) { perror("Failed to read stored hash"); fclose(hash_file); return 1; } fclose(hash_file); // 比对两个哈希字符串 if (strcmp(current_hash, stored_hash) == 0) { printf("File is identical - hash matches: %s\n", current_hash); } else { printf("File has changed!\n"); printf("Stored hash: %s\n", stored_hash); printf("Current hash: %s\n", current_hash); } } return 0; }
关键改进点说明
- 封装哈希函数:把SHA512计算和字符串转换的逻辑抽成
calculate_sha512函数,避免重复代码,也让主逻辑更清晰。不管是生成还是比对,只需要调用一次这个函数就能得到当前文件的哈希,解决了重复调用的问题。 - 统一哈希格式:生成和读取的哈希都是十六进制字符串,确保比对时格式完全一致。
- 正确的比对流程:先计算当前文件的最新哈希,再读取存储的哈希,然后用
strcmp直接比较整个字符串,简单可靠。 - 错误处理:增加了文件操作的错误检查,避免程序在文件打不开时出现未定义行为。
内容的提问来源于stack exchange,提问作者Joseph Smith
相关产品推荐
相关产品推荐

