C语言实例_获取文件MD5值
一、MD5介绍
MD5(Message Digest Algorithm 5)是一种常用的哈希函数算法。将任意长度的数据作为输入,并生成一个唯一的、固定长度(通常是128位)的哈希值,称为MD5值。MD5算法以其高度可靠性和广泛应用而闻名。
MD5算法主要具备以下特点:
(1)不可逆性:给定MD5值无法通过逆运算得到原始数据。
(2)唯一性:不同的输入数据会生成不同的MD5值。
(3)高效性:对于给定的数据,计算其MD5值是非常快速的。
MD5值的应用场景包括:
(1)数据完整性验证:MD5值可以用于验证文件是否在传输过程中被篡改。发送方计算文件的MD5值并发送给接收方,接收方在接收到文件后重新计算MD5值,然后与发送方的MD5值进行比较,如果一致,则说明文件未被篡改。
(2)密码存储:在许多系统中,用户密码通常不会以明文形式存储,而是将其转换为MD5值后存储。当用户登录时,系统会将用户输入的密码转换为MD5值,然后与存储的MD5值进行比较,以验证密码的正确性。
(3)安全认证:MD5值也可用于数字证书等安全认证中,用于验证文件的完整性和认证信息的真实性。
(4)数据指纹:MD5值可以作为数据的唯一标识符,用于快速比对和查找重复数据。
二、示例代码
2.1 获取数据MD5值(openssl库)
在C语言中获取一段数据的MD5值,可以使用现有的第三方库实现。以下是一个使用 OpenSSL 库计算数据的MD5值的示例代码:
(1)需要安装 OpenSSL 库(如果尚未安装)并包含相关头文件:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/md5.h>
(2)创建一个子函数来计算数据的MD5值:
void calculate_md5(const unsigned char* data, size_t length, unsigned char* md5_hash) {MD5_CTX ctx;MD5_Init(&ctx);MD5_Update(&ctx, data, length);MD5_Final(md5_hash, &ctx);
}
该函数接受三个参数:data
为待计算的数据指针,length
为数据长度,md5_hash
为存储MD5值的数组。
下面是一个完整的程序,展示如何调用以上子函数并打印MD5值:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/md5.h>void calculate_md5(const unsigned char* data, size_t length, unsigned char* md5_hash) {MD5_CTX ctx;MD5_Init(&ctx);MD5_Update(&ctx, data, length);MD5_Final(md5_hash, &ctx);
}void print_md5(const unsigned char* md5_hash) {for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {printf("%02x", md5_hash[i]);}printf("\n");
}int main() {const unsigned char data[] = "Hello, World!";size_t length = sizeof(data) - 1; // 减去字符串末尾的空字符unsigned char md5_hash[MD5_DIGEST_LENGTH];calculate_md5(data, length, md5_hash);printf("MD5: ");print_md5(md5_hash);return 0;
}
这个示例程序将输出一段数据的MD5值。可以将待计算的数据存储在 data
数组中,并根据需要调整数据长度。
这里使用的是 OpenSSL 提供的 MD5 函数。在编译时,需要链接 OpenSSL 库。在 Linux 系统上,可以使用 -lssl -lcrypto
参数进行链接。在 Windows 系统上,需要下载并安装 OpenSSL 库,并配置正确的链接路径和库文件名称。
2.2 获取文件的MD5值(openssl库)
以下是使用 OpenSSL 库计算文件的MD5值的示例代码:
(1)需要安装 OpenSSL 库(如果尚未安装)并包含相关头文件:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/md5.h>
(2)创建一个子函数来计算文件的MD5值:
void calculate_file_md5(const char* filename, unsigned char* md5_hash) {FILE* file = fopen(filename, "rb");if (file == NULL) {printf("Failed to open file: %s\n", filename);return;}MD5_CTX ctx;MD5_Init(&ctx);unsigned char buffer[1024];size_t read;while ((read = fread(buffer, 1, sizeof(buffer), file)) != 0) {MD5_Update(&ctx, buffer, read);}fclose(file);MD5_Final(md5_hash, &ctx);
}
该函数接受两个参数:filename
为待计算的文件名,md5_hash
为存储MD5值的数组。
下面是一个完整的示例程序,展示如何调用以上子函数并打印文件的MD5值:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/md5.h>void calculate_file_md5(const char* filename, unsigned char* md5_hash) {// ... 函数实现见上文 ...void print_md5(const unsigned char* md5_hash) {for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {printf("%02x", md5_hash[i]);}printf("\n");
}int main() {const char* filename = "path/to/file";unsigned char md5_hash[MD5_DIGEST_LENGTH];calculate_file_md5(filename, md5_hash);printf("MD5: ");print_md5(md5_hash);return 0;
}
这个示例程序将打开指定文件并计算其MD5值。需要将文件路径存储在 filename
字符串中,并根据需要调整该字符串。
请这里使用的是 OpenSSL 提供的 MD5 函数。在编译时,需要链接 OpenSSL 库。在 Linux 系统上,可以使用 -lssl -lcrypto
参数进行链接。在 Windows 系统上,需要下载并安装 OpenSSL 库,并配置正确的链接路径和库文件名称。
2.3 自己写算法获取MD5值
实现MD5算法比较复杂,涉及位操作、逻辑运算、位移等。
以下是一个简化版本的纯C语言MD5算法实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef unsigned char uint8;
typedef unsigned int uint32;// MD5常量定义
const uint32 MD5_CONSTANTS[] = {0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
};// 循环左移
#define LEFT_ROTATE(x, n) (((x) << (n)) | ((x) >> (32 - (n))))// 转换为大端字节序
void to_big_endian(uint32 value, uint8* buffer) {buffer[0] = (uint8)(value & 0xff);buffer[1] = (uint8)((value >> 8) & 0xff);buffer[2] = (uint8)((value >> 16) & 0xff);buffer[3] = (uint8)((value >> 24) & 0xff);
}// 处理消息块
void process_block(const uint8* block, uint32* state) {uint32 a = state[0];uint32 b = state[1];uint32 c = state[2];uint32 d = state[3];uint32 m[16];// 将消息块划分为16个32位字,并进行字节序转换for (int i = 0; i < 16; i++) {m[i] = (((uint32)block[i * 4 + 0]) << 0) |(((uint32)block[i * 4 + 1]) << 8) |(((uint32)block[i * 4 + 2]) << 16) |(((uint32)block[i * 4 + 3]) << 24);}// MD5循环运算for (int i = 0; i < 64; i++) {uint32 f, g;if (i < 16) {f = (b & c) | ((~b) & d);g = i;} else if (i < 32) {f = (d & b) | ((~d) & c);g = (5 * i + 1) % 16;} else if (i < 48) {f = b ^ c ^ d;g = (3 * i + 5) % 16;} else {f = c ^ (b | (~d));g = (7 * i) % 16;}uint32 temp = d;d = c;c = b;b = b + LEFT_ROTATE((a + f + MD5_CONSTANTS[i] + m[g]), 7);a = temp;}// 更新状态state[0] += a;state[1] += b;state[2] += c;state[3] += d;
}// 计算MD5值
void calculate_md5(const uint8* message, size_t length, uint8* digest) {// 初始化状态uint32 state[4] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 };// 填充消息size_t padded_length = ((length + 8) / 64 + 1) * 64;uint8* padded_message = (uint8*)calloc(padded_length, 1);memcpy(padded_message, message, length);padded_message[length] = 0x80; // 添加一个1to_big_endian((uint32)(length * 8), padded_message + padded_length - 8); // 添加长度(以位为单位)// 处理消息块for (size_t i = 0; i < padded_length; i += 64) {process_block(padded_message + i, state);}// 生成摘要for (int i = 0; i < 4; i++) {to_big_endian(state[i], digest + i * 4);}free(padded_message);
}// 打印MD5值
void print_md5(const uint8* digest) {for (int i = 0; i < 16; i++) {printf("%02x", digest[i]);}printf("\n");
}int main() {const char* message = "Hello, World!";size_t length = strlen(message);uint8 digest[16];calculate_md5((const uint8*)message, length, digest);printf("MD5: ");print_md5(digest);return 0;
}
这个程序可以计算给定字符串的MD5值。将待计算的数据存储在 message
字符串中,根据需要调整数据长度。
相关文章:

C语言实例_获取文件MD5值
一、MD5介绍 MD5(Message Digest Algorithm 5)是一种常用的哈希函数算法。将任意长度的数据作为输入,并生成一个唯一的、固定长度(通常是128位)的哈希值,称为MD5值。MD5算法以其高度可靠性和广泛应用而闻名…...
Win11环境下 Unity个人版无法激活
网上教程大多都是在win10环境下运行,win11环境下遇到很多没有碰到的问题,故简单做个记录,也方便同样使用win11的朋友解决问题。 Unity2021无法打开 问题描述:下载Unity2021.3.4f1c1版本(LTS)后࿰…...

C++:模拟实现list及迭代器类模板优化方法
文章目录 迭代器模拟实现 本篇模拟实现简单的list和一些其他注意的点 迭代器 如下所示是利用拷贝构造将一个链表中的数据挪动到另外一个链表中,构造两个相同的链表 list(const list<T>& lt) {emptyinit();for (auto e : lt){push_back(e);} }void test_…...
k8s整合istio配置gateway入口、配置集群内部服务调用管理
一、 istio gateway使用demo kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata:name: ngdemo-gatewaynamespace: ssx spec:selector:istio: ingressgateway # use Istio default gateway implementationservers:- port:numbe…...

工程监测振弦采集仪采集到的数据如何进行分析和处理
工程监测振弦采集仪采集到的数据如何进行分析和处理 振弦采集仪是一个用于测量和记录物体振动的设备。它通过测量物体表面的振动来提取振动信号数据,然后将其转换为数字信号,以便进行分析和处理。在实际应用中,振弦采集仪是广泛应用于机械、建…...

(三)行为模式:2、命令模式(Command Pattern)(C++示例)
目录 1、命令模式(Command Pattern)含义 2、命令模式的UML图学习 3、命令模式的应用场景 4、命令模式的优缺点 5、C实现命令模式的实例 1、命令模式(Command Pattern)含义 命令模式(Command)ÿ…...

微信小程序 蓝牙设备连接,控制开关灯
1.前言 微信小程序中连接蓝牙设备,信息写入流程 1、检测当前使用设备(如自己的手机)是否支持蓝牙/蓝牙开启状态 wx:openBluetoothAdapter({}) 2、如蓝牙已开启状态,检查蓝牙适配器的状态 wx.getBluetoothAdapterState({}) 3、添加…...

Python 矢量数据库和矢量索引:构建 LLM 应用程序
推荐:使用 NSDT场景编辑器 助你快速搭建可二次编辑的3D应用场景 由于使用其硬件创建的生成式AI应用程序,Nvidia经历了显着的增长。另一项软件创新,矢量数据库,也正在乘着生成式人工智能的浪潮。 开发人员正在向量数据库上用Pytho…...

-Webkit-Box 在 Safari 中出现的兼容性问题
一、问题背景: UI要求要实现这样的效果,使用 display:-webket-box在chrome浏览器下完美解决 但是马上啪啪打脸,在safari浏览器下显示空白 ,不能不说浏览器之间的兼容性简直就是天坑 二、解决办法 通过浏览器调试发现原本float的…...

后端项目打包上传服务器记录
后端项目打包上传服务器记录 文章目录 后端项目打包上传服务器记录1、项目打包2、jar包上传服务器 本文记录打包一个后端项目,上传公司服务器的过程。 1、项目打包 通过IDEA的插件进行打包: 打成一个jar包,jar包的位置在控制台可以看到。 2、…...

ubuntu部署haproxy
HAProxy是可提供高可用性、负载均衡以及基于TCP和HTTP应用的代理. 1、更新系统报 通过在终端中运行以下命令,确保所有系统包都是最新的 sudo apt updatesudo apt upgrade2、安装Haproxy sudo apt install haproxy设置开机自动启动haproxy服务 sudo systemctl en…...

vue利用 sortable 完成表格拖拽
先讲一下vue2,使用sortable完成表格拖拽【不只是表格,div也可以实现,但我项目中是表格拖拽】 github地址 安装 npm install sortablejs --save使用 (我的项目中是拖拽一个小按钮移动,而不是整行) <te…...

CNN简介3
...

新能源电动车充电桩控制主板安全特点
新能源电动车充电桩控制主板安全特点 你是否曾经担心过充电桩的安全问题?充电桩主板又是什么样的呢?今天我们就来聊聊这个话题。 充电桩主板采用双重安全防护系统,包括防水、防护、防尘等,确保充电桩安全、可靠。不仅如此,充电桩主板采用先…...

公路桥梁有哪些安全隐患?
在现代社会,公路桥梁作为连接城市、串联交通的重要纽带,扮演着无可替代的角色。然而,我们常常忽视的是,这些高架构筑物也存在着潜在的安全隐患,可能随时影响着交通的畅通和人们的生命财产安全。为了更好地认识和理解这…...

【C语言】每日一题(错误的集合)
最近在牛客、力扣上做题,花费海量时间,苦不堪言,有时绞尽脑汁也想不出,痛定思痛,每日记录写的比较困难的题。 错误的集合 题目如上图所示 题主乍看之下觉得很简单,再看例子,不就是一个有序数组…...

[JavaWeb]【四】web后端开发-SpringBootWeb入门
目录 一 Spring 二 SpringBootWeb入门 2.1 入门需求 2.2 分析 2.3 开始创建SpringBootWeb 2.4 创建类实现需求 2.5 启动程序 2.6 访问 三 HTTP协议 3.1 HTTP-概述 3.2 HTTP-请求协议 3.3 HTTP-响应协议 3.3.1 响应状态码 && 响应类型 3.4 HTTP-协议解析 前言…...
前端css
day03-CSS基础 目标:掌握 CSS 属性基本写法,能够使用文字相关属性美化文章页。 01-CSS初体验 层叠样式表 (Cascading Style Sheets,缩写为 CSS),是一种 样式表 语言,用来描述 HTML 文档的呈现(…...
vb+sql医院门诊管理系统设计与系统
摘要 信息时代已经来临,计算机应用于医院的日常管理,为医院的现代化带来了从未有过的动力和机遇,为医疗卫生领域的发展提供了无限的潜力。采用计算机管理信息系统已成为医院管理科学化和现代化的标志,给医院带来了明显的经济效益和社会效益。 本文介绍了数据库管理系统的…...

bootstrap-modal调用ajax后不经过回调函数
说明:我用的是boostrap的弹框,表单用的是layui的,个人觉得bootstrap比layui的弹框好看点,能自适应高度。 如图:点击保存后里面的内容不执行 原因:type用的是submit 解决:把submit改为button...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
ffmpeg(三):处理原始数据命令
FFmpeg 可以直接处理原始音频和视频数据(Raw PCM、YUV 等),常见场景包括: 将原始 YUV 图像编码为 H.264 视频将 PCM 音频编码为 AAC 或 MP3对原始音视频数据进行封装(如封装为 MP4、TS) 处理原始 YUV 视频…...

JUC并发编程(二)Monitor/自旋/轻量级/锁膨胀/wait/notify/锁消除
目录 一 基础 1 概念 2 卖票问题 3 转账问题 二 锁机制与优化策略 0 Monitor 1 轻量级锁 2 锁膨胀 3 自旋 4 偏向锁 5 锁消除 6 wait /notify 7 sleep与wait的对比 8 join原理 一 基础 1 概念 临界区 一段代码块内如果存在对共享资源的多线程读写操作…...