#define _CRT_SECURE_NO_WARNINGS
#define OPENSSL_API_COMPAT 10100
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <ctype.h>
#include <conio.h> // 用于getch()函数
enum { ALG_MD5, ALG_SHA256 };
// 修改函数返回类型和错误处理
int calc_hash(const char* filename, int alg, unsigned char* digest, const char** error_msg) {
FILE* file = fopen(filename, "rb");
if (!file) {
*error_msg = "打开文件失败";
return 0;
}
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
if (!ctx) {
fclose(file);
*error_msg = "创建哈希上下文失败";
return 0;
}
const EVP_MD* md = (alg == ALG_MD5) ? EVP_md5() : EVP_sha256();
if (!EVP_DigestInit_ex(ctx, md, NULL)) {
fclose(file);
EVP_MD_CTX_free(ctx);
*error_msg = "初始化哈希算法失败";
return 0;
}
unsigned char buffer[8192];
size_t bytes;
while ((bytes = fread(buffer, 1, sizeof(buffer), file)) > 0) {
if (!EVP_DigestUpdate(ctx, buffer, bytes)) {
fclose(file);
EVP_MD_CTX_free(ctx);
*error_msg = "更新哈希失败";
return 0;
}
}
unsigned int digest_len;
if (!EVP_DigestFinal_ex(ctx, digest, &digest_len)) {
fclose(file);
EVP_MD_CTX_free(ctx);
*error_msg = "获取最终哈希失败";
return 0;
}
fclose(file);
EVP_MD_CTX_free(ctx);
return 1;
}
char* to_hex(const unsigned char* hash, int len) {
char* hex = (char*)malloc((len * 2) + 1);
if (!hex) return NULL;
for (int i = 0; i < len; i++) {
snprintf(hex + (i * 2), 3, "%02x", hash[i]);
}
hex[len * 2] = '\0';
return hex;
}
int compare_hash(const char* hash1, const char* hash2) {
if (!hash1 || !hash2) return 0;
if (strlen(hash1) != strlen(hash2)) return 0;
for (int i = 0; hash1[i] && hash2[i]; i++) {
if (tolower((unsigned char)hash1[i]) != tolower((unsigned char)hash2[i]))
return 0;
}
return 1;
}
// 修复:添加函数原型
int show_menu(const char* current_file, int current_alg);
char* select_file();
// 修复:修改参数为 const char*
int show_menu(const char* current_file, int current_alg) {
system("cls"); // 清屏 (Windows)
// system("clear"); // 如果是Linux/macOS使用这个
printf("\n ===============================\n");
printf(" 文件哈希校验工具 - 命令行交互版\n");
printf(" ===============================\n\n");
printf(" 当前文件: %s\n", current_file ? current_file : "未选择");
printf(" 当前算法: %s\n\n", current_alg == ALG_MD5 ? "MD5" : "SHA-256");
printf(" 请选择操作:\n");
printf(" 1. 选择文件\n");
printf(" 2. 切换算法 (当前: %s)\n", current_alg == ALG_MD5 ? "MD5" : "SHA-256");
printf(" 3. 计算哈希值\n");
printf(" 4. 验证文件完整性\n");
printf(" 5. 退出程序\n\n");
printf(" 输入选项 (1-5): ");
int choice;
if (scanf("%d", &choice) != 1) {
// 清除输入缓冲区
while (getchar() != '\n');
return -1;
}
getchar(); // 消耗换行符
return choice;
}
// 修复:避免使用 strdup
char* select_file() {
char filename[256];
printf("\n 请输入文件路径 (或按回车返回): ");
if (fgets(filename, sizeof(filename), stdin) == NULL) {
return NULL;
}
// 去除换行符
size_t len = strlen(filename);
if (len > 0 && filename[len-1] == '\n') {
filename[len-1] = '\0';
}
// 如果用户没有输入内容,返回NULL
if (strlen(filename) == 0) {
return NULL;
}
// 检查文件是否存在
FILE* file = fopen(filename, "r");
if (!file) {
printf("\n ! 文件不存在或无法访问!\n");
printf(" 按任意键继续...");
getchar();
return NULL;
}
fclose(file);
// 避免使用 strdup
char* result = (char*)malloc(strlen(filename) + 1);
if (result) {
strcpy(result, filename);
}
return result;
}
int main() {
char* filename = NULL;
int alg = ALG_SHA256; // 默认算法
int running = 1;
while (running) {
int choice = show_menu(filename, alg);
switch (choice) {
case 1: { // 选择文件
char* new_file = select_file();
if (new_file) {
if (filename) free(filename);
filename = new_file;
}
break;
}
case 2: { // 切换算法
printf("\n 当前算法: %s\n", alg == ALG_MD5 ? "MD5" : "SHA-256");
printf(" 请选择新算法:\n");
printf(" 1. MD5\n");
printf(" 2. SHA-256\n");
printf(" 输入选项 (1-2): ");
int alg_choice;
if (scanf("%d", &alg_choice) != 1) {
// 清除输入缓冲区
while (getchar() != '\n');
printf("\n ! 输入无效!\n");
break;
}
getchar(); // 消耗换行符
if (alg_choice == 1) {
alg = ALG_MD5;
printf("\n 算法已切换为 MD5\n");
} else if (alg_choice == 2) {
alg = ALG_SHA256;
printf("\n 算法已切换为 SHA-256\n");
} else {
printf("\n ! 无效的选项!\n");
}
printf(" 按任意键继续...");
getchar();
break;
}
case 3: { // 计算哈希值
if (!filename) {
printf("\n ! 请先选择文件!\n");
printf(" 按任意键继续...");
getchar();
break;
}
unsigned char digest[32];
const char* error_msg = NULL;
if (calc_hash(filename, alg, digest, &error_msg)) {
const int digest_len = (alg == ALG_MD5) ? 16 : 32;
char* hash_hex = to_hex(digest, digest_len);
if (hash_hex) {
printf("\n ===== 计算结果 =====\n");
printf(" 文件: %s\n", filename);
printf(" 算法: %s\n", alg == ALG_MD5 ? "MD5" : "SHA-256");
printf(" 哈希值: %s\n", hash_hex);
printf(" ====================\n");
free(hash_hex);
} else {
printf("\n ! 内存分配失败!\n");
}
} else {
printf("\n ! 计算失败: %s\n", error_msg);
}
printf("\n 按任意键继续...");
getchar();
break;
}
case 4: { // 验证文件完整性
if (!filename) {
printf("\n ! 请先选择文件!\n");
printf(" 按任意键继续...");
getchar();
break;
}
char compare_hash_str[128];
printf("\n 请输入要比较的哈希值: ");
if (fgets(compare_hash_str, sizeof(compare_hash_str), stdin) == NULL) {
printf("\n ! 输入读取失败!\n");
break;
}
// 去除换行符
size_t len = strlen(compare_hash_str);
if (len > 0 && compare_hash_str[len-1] == '\n') {
compare_hash_str[len-1] = '\0';
}
if (strlen(compare_hash_str) > 0) {
unsigned char digest[32];
const char* error_msg = NULL;
if (calc_hash(filename, alg, digest, &error_msg)) {
const int digest_len = (alg == ALG_MD5) ? 16 : 32;
char* hash_hex = to_hex(digest, digest_len);
if (hash_hex) {
printf("\n ===== 验证结果 =====\n");
printf(" 文件: %s\n", filename);
printf(" 算法: %s\n", alg == ALG_MD5 ? "MD5" : "SHA-256");
printf(" 计算哈希值: %s\n", hash_hex);
printf(" 提供哈希值: %s\n", compare_hash_str);
if (compare_hash(hash_hex, compare_hash_str)) {
// 使用Windows API设置颜色
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, 10); // 绿色
printf(" 结果: 文件完整\n");
SetConsoleTextAttribute(hConsole, 7); // 恢复默认
} else {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, 12); // 红色
printf(" 结果: 文件已被修改!\n");
SetConsoleTextAttribute(hConsole, 7); // 恢复默认
}
printf(" ====================\n");
free(hash_hex);
} else {
printf("\n ! 内存分配失败!\n");
}
} else {
printf("\n ! 计算失败: %s\n", error_msg);
}
} else {
printf("\n ! 未输入哈希值!\n");
}
printf("\n 按任意键继续...");
getchar();
break;
}
case 5: // 退出程序
running = 0;
break;
default:
if (choice != -1) {
printf("\n ! 无效的选项!\n");
}
printf(" 按任意键继续...");
getchar();
break;
}
}
if (filename) free(filename);
printf("\n 感谢使用文件哈希校验工具!再见!\n");
return EXIT_SUCCESS;
}
"HANDLE”:未声明的标识符
语法错误: 缺少”."(在标识符”hConsole"的前面
"hConsole”:未声明的标识符
"STD OUTPUT HANDLE”: 未声明的标识符
"GetStdHandle": 找不到标识符
"hConsole: 未声明的标识符
“SetConsoleTextAttribute": 找不到标识符
"hConsole": 未声明的标识符
"SetConsoleTextAttribute"”: 找不到标识符
"HANDLE”: 未声明的标识符
语法错误: 缺少”"(在标识符”hConsole”的前面
"hConsole”: 未声明的标识符
"STD OUTPUT HANDLE”: 未声明的标识符
"GetStdHandle": 找不到标识符
"hConsole": 未声明的标识符
"SetConsoleTextAttribute": 我不到标识符
"hConsole": 未声明的标识符
"SetConsoleTextAttribute": 找不到标识特
报错了