活动介绍
file-type

C语言实现MD5小写:一种常用的信息完整性保护算法

TXT文件

下载需积分: 10 | 7KB | 更新于2024-09-10 | 152 浏览量 | 4 下载量 举报 收藏
download 立即下载
MD5小写C语言教程 MD5,全称Message-Digest Algorithm 5,是一种广泛应用于计算机安全领域的哈希函数,用于保护信息的完整性。它在RFC 1321标准中定义,由Rivest等人于1992年开发,与MD2、MD3和MD4一起构成了MD系列的杂凑算法。MD5的核心功能是将任意长度的数据转换为一个固定长度的128位(16字节)散列值,这使得它在验证数据完整性和防篡改方面具有重要作用。 C语言中的MD5实现通常包括以下几个关键组件: 1. **MD5 Context结构**: - `MD5_CTX` 结构体定义了MD5算法处理数据的基本容器,包含一个4元素的`buf`数组存储中间计算结果,两个32位的`bits`数组用于追踪当前处理的数据块,以及一个64字节大小的`in`数组暂时存储待处理的数据。 2. **初始化函数**: - `MD5Init()` 函数用于初始化一个新的MD5 Context,设置初始的哈希值缓冲区,分别为0x67452301、0xefcdab89、0x98badcfe和0x10325476。 3. **更新函数**: - `MD5Update()` 函数接受一个输入数据指针`buf`和长度`len`,将数据块添加到当前处理的哈希计算中,通过一系列复杂的数学运算更新内部状态。 4. **最终化函数**: - `MD5Final()` 函数用于处理最后一个数据块并完成哈希计算,将最终的结果存储在MD5 Context中。 5. **辅助函数**: - `byteReverse()` 函数,虽然不是MD5核心算法的一部分,但可能在某些C语言实现中用于处理16位字节的字序调整,以适应不同平台的字长规定。 MD5算法的特点: - **压缩性**:无论输入数据多大,MD5生成的散列值固定为128位。 - **容易计算**:计算过程相对简单,但需要高效的算法实现。 - **抗修改性**:对原始数据的微小改动会导致散列值的巨大变化,提高了数据完整性检查的可靠性。 - **强抗碰撞**:尽管理论上找到两个具有相同散列值的不同数据(即“碰撞”)的概率极低,但并非绝对不可能,所以MD5不适用于加密等安全性要求极高的应用。 C语言中的MD5实现提供了对这种强大工具的直接访问,开发者可以方便地在自己的程序中集成MD5哈希来验证数据或作为密钥生成的一部分。然而,随着更安全的算法如SHA-256的出现,MD5在现代安全环境中已经不再推荐使用,尤其是在密码学和加密应用中。

相关推荐

filetype
C版本MD5库 参考README.md 内容 #file list makefile #编译文件 md5.c md5.h test_md5_hash.c #测试样例文件 README.md #帮助文件 ========== 该库目前仅仅支持Gun/Linux/Unix 系列的编译 若是winxp/win7/win8 系列请自己包含进去,或者自己重新打包 代码是从bPostgreSQL中的库文件copy出来的,经过自己的测试,重新提取打包出来的 目前这个库的代码是在 PG 的 8.5RS 里面用的 MD5 返回的是一个 32位的消息hash因此需要一个char 类型的返回buf query_md5 =(char *)malloc(33); 函数调用 md5_hash(argv[1],query_len,query_md5); argv1 需要加密的数据 argv2 加密数据长度 argv3 密文 MD5.c 里面其他函数不常用,有兴趣的自己看一下吧,注释是用英文写的,基本上都能看 懂,不能看懂的,Google翻译一下就行了 自己的文件编译已测试样例文件为例 make后同时生成静态库和动态库 libminmd5.a 静态库 libminmd5.so 动态库 1、静态库的用法 gcc -o test test_md5_hash.c -L. -lminmd5 -I. -L #库文件的路径, -l #库名字,通常情况下就是 去掉后缀和前缀lib的名字 -I #头文件的路径 PS:动态库和静态库文件同名的建议不要放在一起,不然 ld的时候有可能找错文件 2、动态库的用法 gcc -o test test_md5_hash.c -g -L. -lminmd5 -I. 编译完后,建议将so 文件copy 到/usr/lib 然后执行 ldconfig 或者写死一点 gcc -o test test_md5_hash.c -g -L. -lminmd5 -I. -Wl,-rpath,. -Wl,-rpath,. #告诉ld 从本地找库(W后面是L小写的),rpath里面接的是库文件存在 的路径,正常应用建议用第一种方案,第二种方案在写小测试程序的时候,可以考虑。 至于选静态库还是动态库,就看具体应用场景了,静态库的坏处是把库代码编译进去了, 若是程序按字节收费还是可以的,(PS,吐槽那个写了一个10w,10G的程序中国神童)
filetype

#include <openssl/evp.h> #include <stdio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/evp.h> #include <openssl/md5.h> #include <openssl/sha.h> // 哈希算法枚举 enum HashAlgorithm { ALG_MD5, ALG_SHA1, ALG_SHA256 }; // 计算文件哈希值 int calculate_file_hash(const char* filename, enum HashAlgorithm alg, unsigned char* digest, unsigned int* digest_len) { FILE* file = fopen(filename, "rb"); if (!file) { perror("文件打开失败"); return 0; } const EVP_MD* md_type = NULL; switch (alg) { case ALG_MD5: md_type = EVP_md5(); break; case ALG_SHA1: md_type = EVP_sha1(); break; case ALG_SHA256: md_type = EVP_sha256(); break; default: fclose(file); return 0; } EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); EVP_DigestInit_ex(mdctx, md_type, NULL); unsigned char buffer[4096]; size_t bytes_read; while ((bytes_read = fread(buffer, 1, sizeof(buffer), file))) { EVP_DigestUpdate(mdctx, buffer, bytes_read); } EVP_DigestFinal_ex(mdctx, digest, digest_len); EVP_MD_CTX_free(mdctx); fclose(file); return 1; } // 将哈希值转换为十六进制字符串 void hash_to_hex(const unsigned char* hash, int len, char* output) { for (int i = 0; i < len; i++) { sprintf(output + (i * 2), "%02x", hash[i]); } output[len * 2] = '\0'; } // 比较哈希值 int compare_hashes(const unsigned char* hash1, const unsigned char* hash2, int len) { return memcmp(hash1, hash2, len) == 0; } // 显示算法信息 void print_algorithm_info() { printf("\n哈希算法比较:\n"); printf("----------------------------------------\n"); printf("MD5 | 128位 | 已证明存在碰撞,不安全\n"); printf("SHA-1 | 160位 | 已发现碰撞,不推荐安全用途\n"); printf("SHA-256 | 256位 | 当前安全,推荐使用\n"); printf("----------------------------------------\n"); } int main(int argc, char* argv[]) { if (argc < 3) { printf("用法: %s <文件路径> <算法>\n", argv[0]); printf("算法选项: md5, sha1, sha256\n"); printf("可选: -c <校验值> 进行完整性验证\n"); print_algorithm_info(); return 1; } const char* filename = argv[1]; const char* alg_str = argv[2]; const char* check_value = NULL; enum HashAlgorithm alg; if (strcmp(alg_str, "md5") == 0) alg = ALG_MD5; else if (strcmp(alg_str, "sha1") == 0) alg = ALG_SHA1; else if (strcmp(alg_str, "sha256") == 0) alg = ALG_SHA256; else { printf("不支持的算法: %s\n", alg_str); return 1; } // 检查是否提供了校验值 if (argc == 4 && strcmp(argv[2], "-c") == 0) { check_value = argv[3]; alg = ALG_SHA256; // 默认使用SHA-256校验 } else if (argc == 5 && strcmp(argv[3], "-c") == 0) { check_value = argv[4]; } unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_len = 0; if (!calculate_file_hash(filename, alg, digest, &digest_len)) { printf("哈希计算失败\n"); return 1; } char hash_hex[EVP_MAX_MD_SIZE * 2 + 1]; hash_to_hex(digest, digest_len, hash_hex); if (check_value) { printf("计算哈希值: %s\n", hash_hex); printf("预期校验值: %s\n", check_value); // 转换为小写比较 char check_lower[129]; for (int i = 0; check_value[i]; i++) { check_lower[i] = tolower(check_value[i]); } check_lower[strlen(check_value)] = '\0'; if (strcmp(hash_hex, check_lower) == 0) { printf("结果: 文件完整 (哈希值匹配)\n"); } else { printf("结果: 文件已被修改! (哈希值不匹配)\n"); } } else { printf("%s 文件的 %s 哈希值:\n%s\n", filename, alg_str, hash_hex); } print_algorithm_info(); return 0; }

bobsiji
  • 粉丝: 0
上传资源 快速赚钱