【常见开源库的二次开发】基于openssl的加密与解密——MD5算法源码解析(五)

一、MD5算法分析 :

1.1 关于MD5

消息摘要”是指MD5(Message Digest Algorithm 5)算法。MD5是一种广泛使用的密码散列函数,它可以生成一个128位(16字节)的散列值。

RFC 1321: MD5由Ronald Rivest在1992年设计,并通过RFC 1321正式发布。它主要用于确保数据完整性,广泛应用于各种软件和系统中,用于验证数据未被篡改

抗碰撞性攻破: 抗碰撞性是指难以找到两个不同的输入值,使它们通过散列函数产生相同的输出值。2004年,中国的密码学家王小云发现了MD5、SHA-0和其他散列函数的碰撞漏洞,这表明MD5对于安全敏感的应用来说已不再安全。

不再安全: 由于MD5的碰撞漏洞,以及随后发现的更多安全弱点,MD5在安全性要求高的领域(如SSL证书、加密货币等)中已逐渐被其他更安全的算法(如SHA-256)所替代。

如果应用加salt: 加盐(salt)是一种安全措施,常用于存储密码。通过向原始密码添加一段随机数据(salt),然后再进行散列,可以增加破解的难度,减少使用彩虹表等攻击技术的风险。然而,即使加盐,由于MD5本身存在的安全漏洞,它仍然不推荐用于需要高安全性的密码存储。

1.2 算法原理

MD5算法将输入的消息分成512位的块,每个块再分成16个32位(4字节)的子块,命名为M0到M15。算法的核心是四轮处理,每轮使用不同的非线性函数(F、G、H、I),每轮包含16次操作,总共64次操作。

以下是MD5算法中四轮处理的概述:

  1. 第一轮:使用函数F,操作如下:

    FF(a, b, c, d, M0, 7, 0xd76aa478); 
    FF(d, a, b, c, M1, 12, 0xe8c7b756); // 继续处理直到M15
  2. 第二轮:使用函数G,操作如下:

    GG(a, b, c, d, M1, 5, 0xf61e2562); 
    GG(d, a, b, c, M6, 9, 0xc040b340); // 继续处理直到M11
  3. 第三轮:使用函数H,操作如下:

    HH(a, b, c, d, M5, 4, 0xfffa3942); 
    HH(d, a, b, c, M8, 11, 0x8771f681); // 继续处理直到M14
  4. 第四轮:使用函数I,操作如下:

    II(a, b, c, d, M0, 6, 0xf4292244);
    II(d, a, b, c, M7, 10, 0x432aff97); // 继续处理直到M15

在每轮中,函数FF、GG、HH、II分别定义了如何更新四个32位的寄存器(a, b, c, d)。这些函数通常包含一个非线性函数(F, G, H, I),一个常数(ac),一个消息块(x),以及一个位移量(s)。

例如,FF函数的定义可能如下:

#define FF(a, b, c, d, x, s, ac) { \ (a) += F((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ }

这里的F是一个非线性函数,ROTATE_LEFT是一个位移操作,将a左移s位,然后加上b

MD5算法的详细实现可以在RFC 1321文档中找到,该文档提供了算法的完整描述和实现细节。然而,由于MD5的安全性问题,现在推荐使用更安全的散列算法,如SHA-256。

二、MD5接口调用

演示如何使用OpenSSL库计算并输出字符串的MD5哈希值,主要用于学习和教学目的。通过这段代码,可以了解MD5哈希算法的基本使用方法,并学习如何使用OpenSSL库的函数来实现这一算法。

源代码:

#include <iostream>
#include <openssl/md5.h>using namespace std;int main() {cout << "Test Hash" << endl; // 输出测试信息unsigned char data[] = "测试MD5数据"; // 定义要进行MD5哈希的数据unsigned char out[MD5_DIGEST_LENGTH] = {0}; // 定义输出数组,大小为MD5哈希结果的长度int len = sizeof(data) - 1; // 计算数据长度,减去1是因为sizeof包含字符串末尾的'\0'MD5_CTX c; // 定义MD5上下文MD5_Init(&c); // 初始化MD5上下文MD5_Update(&c, data, len); // 更新MD5上下文,传入数据和数据长度MD5_Final(out, &c); // 完成MD5哈希,将结果存储在out数组中// 输出MD5哈希结果for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {cout << hex << (int)out[i]; // 以十六进制格式输出每个字节}cout << endl; // 输出换行符,使结果更清晰return 0; // 返回0表示程序成功执行
}

输出测试信息:提示用户程序开始运行。

unsigned char data[] = "测试MD5数据"; // 定义要进行MD5哈希的数据 
unsigned char out[MD5_DIGEST_LENGTH] = {0}; // 定义输出数组,大小为MD5哈希结果的长度 
int len = sizeof(data) - 1; // 计算数据长度,减去1是因为sizeof包含字符串末尾的'\0'

定义输入数据:一个用于计算MD5哈希的字符串。

定义输出数组:存储MD5哈希结果的数组,长度为16字节(MD5_DIGEST_LENGTH)。

计算数据长度sizeof(data) - 1用于获取实际字符串长度,不包括终止符'\0'

MD5_CTX c; // 定义MD5上下文 MD5_Init(&c); // 初始化MD5上下文 
MD5_Update(&c, data, len); // 更新MD5上下文,传入数据和数据长度 
MD5_Final(out, &c); // 完成MD5哈希,将结果存储在out数组中

MD5上下文:使用MD5_CTX结构体来保存MD5计算的中间状态。

初始化MD5上下文:使用MD5_Init函数。

更新MD5上下文:使用MD5_Update函数,将输入数据分块更新到MD5上下文中。

完成MD5哈希:使用MD5_Final函数,将最终的MD5哈希结果存储到输出数组中。

// 输出MD5哈希结果 for (int i = 0; 
i < MD5_DIGEST_LENGTH; i++) 
{ cout << hex << (int)out[i]; // 以十六进制格式输出每个字节 
} 
cout << endl; // 输出换行符,使结果更清晰

输出MD5哈希结果:使用循环遍历输出数组的每个字节,并以十六进制格式输出。

换行符:在输出结束后添加换行符,使输出更整齐。

当我们改变data数组中的某一个值后,我们整个哈希值都会发生改变,修改输入数据的一个字节,然后重新计算该数据的MD5哈希值,并输出结果。通过这种方式,可以观察到数据微小变化对MD5哈希值的影响,从而理解MD5哈希算法的敏感性。

data[1] = 9;
MD5(data,len, out);
for(int i = 0; i < 16; i++)cout << hex << (int)out[i];

三、运用MD5 哈希列表(Hash List)验证文件完整性

哈希列表(Hash List)是一种用于验证文件完整性的技术。通过将文件分割成多个块,并对每个块生成哈希值,然后将所有块的哈希值合并再生成一个总的哈希值,可以有效地验证文件是否在传输或存储过程中被篡改

3.1 读取文件并分块

首先,将文件读取并分割成多个固定大小的块。例如,可以将文件分割成1MB的块。

3.2 生成每个块的哈希值

对每个块生成哈希值。常用的哈希算法包括MD5、SHA-1、SHA-256等。

3.3 合并所有块的哈希值

将所有块的哈希值合并成一个总的哈希值。可以采用类似的方式,将所有块的哈希值拼接起来,然后对这个拼接后的数据生成一个总的哈希值。

3.4 验证文件完整性

在文件传输或存储后,重新执行上述步骤,生成新的哈希列表和总的哈希值。比较新生成的总的哈希值与原始的总的哈希值,如果一致,则文件未被篡改;如果不一致,则文件已被篡改。

3.5 演示代码

通过计算文件的MD5哈希值来监控文件的完整性。如果文件被修改,程序会检测到并输出新的哈希值。

源代码:

#include <iostream>
#include <openssl/md5.h>
#include <fstream>
#include <iomanip>
#include <thread>using namespace std;// 计算文件的MD5哈希值
string GetFileListHash(const string& filepath)
{// 以二进制方式打开文件ifstream ifs(filepath, ios::binary);if (!ifs) {// 如果无法打开文件,输出错误信息并返回空字符串cerr << "Failed to open file: " << filepath << endl;return "";}// 定义一次读取的块大小int block_size = 128;// 定义读取文件的缓冲区unsigned char buf[block_size] = { 0 };// 定义输出哈希的数组unsigned char out[MD5_DIGEST_LENGTH] = { 0 };// 定义并初始化MD5上下文MD5_CTX c;MD5_Init(&c);// 读取文件直至文件末尾while (!ifs.eof()) {ifs.read(reinterpret_cast<char*>(buf), block_size);int read_size = ifs.gcount(); // 获取实际读取的字节数if (read_size > 0) {// 将读取的数据添加到MD5上下文中MD5_Update(&c, buf, read_size);}}// 完成MD5计算并将结果存储在out数组中MD5_Final(out, &c);ifs.close(); // 关闭文件流// 将MD5结果转换为字符串并返回return string(reinterpret_cast<char*>(out), MD5_DIGEST_LENGTH);
}// 以十六进制格式输出数据
void PrintHex(const string& data) {for (unsigned char c : data) {cout << hex << setw(2) << setfill('0') << (int)c;}cout << endl;
}int main() {cout << "Test Hash" << endl; // 输出测试信息unsigned char data[] = "测试MD5数据"; // 定义要进行MD5哈希的数据unsigned char out[MD5_DIGEST_LENGTH] = { 0 }; // 定义输出数组,大小为MD5哈希结果的长度int len = sizeof(data) - 1; // 计算数据长度,减去1是因为sizeof包含字符串末尾的'\0'// 对数据进行MD5哈希计算MD5(data, len, out);// 输出哈希结果for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {cout << hex << setw(2) << setfill('0') << (int)out[i];}cout << endl;data[1] = 9; // 修改数据MD5(data, len, out); // 再次计算MD5哈希for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {cout << hex << setw(2) << setfill('0') << (int)out[i];}cout << endl;string filepath = "/home/book/Desktop/test.txt"; // 文件路径auto hash1 = GetFileListHash(filepath); // 计算文件的哈希值PrintHex(hash1); // 输出文件哈希值// 循环检查文件完整性for (;;) {auto hash = GetFileListHash(filepath); // 重新计算文件哈希值if (hash != hash1) {cout << "文件被修改" << endl;PrintHex(hash); // 输出新的哈希值hash1 = hash; // 更新旧哈希值}this_thread::sleep_for(1s); // 每秒检查一次}return 0; // 程序正常结束
}

新建一个txt文件作为存储文件:

文件所形成的哈希值:

当我们改变txt文件中的内容后不断输出文件被修改并且输出修改后文件的哈希值:

函数 GetFileListHash 用于计算指定文件的MD5哈希值。

以二进制模式打开文件。

定义缓冲区 buf 用于读取文件内容。

初始化 MD5 上下文 MD5_CTX

循环读取文件内容并更新 MD5 上下文。

完成 MD5 计算并返回哈希值。

函数 PrintHex 将数据以十六进制格式输出。

遍历输入数据的每个字节。

使用 hexsetw(2) 和 setfill('0') 格式化输出。

初始化并测试 MD5 哈希计算

定义一个字符串 data 进行MD5哈希计算。

输出初始字符串的 MD5 哈希值。

修改字符串 data 并再次计算其 MD5 哈希值。

文件哈希计算与监控

指定文件路径 filepath

计算文件的初始 MD5 哈希值 hash1 并输出。

进入无限循环,不断重新计算文件的 MD5 哈希值,并与初始哈希值进行比较。

如果哈希值发生变化,输出新的哈希值,并更新初始哈希值 hash1

每秒钟检查一次文件的哈希值。

通过计算文件的 MD5 哈希值来监控文件的完整性。它首先进行字符串的 MD5 哈希计算以测试功能,然后进入一个无限循环,定期检查指定文件的 MD5 哈希值。如果检测到文件发生了变化,程序会输出新的哈希值并更新记录的哈希值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/47559.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云计算核心算法(一)

目录 一、Paxos算法&#xff08;一&#xff09;Paxos算法背景知识&#xff08;二&#xff09;Paxos算法详解&#xff08;三&#xff09;Paxos算法举例 云计算的基础技术是集群技术&#xff0c;支撑集群高效协同工作需要一系列资源和任务调度算法&#xff0c;良好的调度算法可以…

【python】Numpy运行报错详细分析:IndexError: too many indices for array

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

创建vue3项目并配置PC端屏幕适配

一、创建vue3项目 1.使用vue cli创建 vue created 项目名2.选择自定义方式创建vue3项目 3.选择项目所需要的依赖项(刚学习vue的同学建议选择安装&#xff08;Linter / Formatter 支持代码风格检查和格式化&#xff09; 对于每一项的功能&#xff0c;做了一个简单的描述&a…

Web开发:一个可拖拽的模态框(HTML、CSS、JavaScript)

目录 一、需求描述 二、实现效果 三、完整代码 四、实现过程 1、HTML 页面结构 2、CSS 元素样式 3、JavaScript动态控制 &#xff08;1&#xff09;获取元素 &#xff08;2&#xff09;显示\隐藏遮罩层与模态框 &#xff08;3&#xff09;实现模态框拖动效果 一、需求…

增长新引擎,构建基于 CDP 的用户运营竞争力

本文将围绕“企业如何通过构建基于 CDP 的用户运营体系提升业务增长”这一核心&#xff0c;详细介绍企业数据化运营现状&#xff0c;拆解用户运营目标&#xff0c;展示神策 CDP 的关键能力以及用户运营策略落地的完整路径。 一、洞察&#xff1a;企业数据化运营面临的挑战 当前…

C语言-网络编程-UDP通信创建流程

UDP 通信创建流程 UDP 是⼀个传输层的⽆连接的协议&#xff0c;我们编写代码⼀般是分为两个端。⼀个我们称之为发送端&#xff0c;另⼀ 个我们称之为接收端。正常⼀般是接收端先运⾏&#xff0c;然后等待结束发送端发送过来的数据。 创建套接字 首先&#xff0c;我们需要创建…

四、GD32 MCU 常见外设介绍 (5) TIMER 模块介绍

5.1.TIMER 基础知识 TIMER分高级定时器&#xff0c;通用定时器L0&#xff0c;L1&#xff0c;L2和基本定时器。 5.2.硬件连接说明 TIMER 属于片内外设&#xff0c;对于外部硬件设计&#xff0c;只需要单独IO口外接信号线即可。 5.3.GD32 TIMER 外设原理简介&#xff08;以 G…

/秋招突击——7/21——复习{堆——数组中的第K大元素}——新作{回溯——全排列、子集、电话号码的字母组合、组合总和、括号生成}

文章目录 引言复习数组中的第K大的最大元素复习实现参考实现 新作回溯模板46 全排列个人实现参考实现 子集个人实现参考实现 电话号码的字母组合复习实现 组合总和个人实现参考实现 括号生成复习实现 总结 引言 昨天的科大讯飞笔试做的稀烂&#xff0c;今天回来好好练习一下&a…

JUC并发编程02-常见方法

start方法与run方法 直接调用run方法-》主线程实现&#xff0c;并不会启动一个新线程。多次调用start方法-》会抛出非法线程异常的错&#xff0c;当线程变成了runnable状态就不能用start方法了。 sleep方法与yield方法 调用sleep会让当前线程从running进入 timed waiting状态…

测试——Junit

内容大纲: 常用的五个注解 测试用例顺序指定 参数化 测试套件 断言 1. 常用的五个注解 1.1 Test 通常情况下,我们输入要写在main方法下,此时我想直接输出: Test void Test01(){System.out.println("第一个测试用例"); } 1.2 BeforeAll AfterAll BeforeALL在Tes…

RK3568笔记四十一:DHT11驱动开发测试

若该文为原创文章&#xff0c;转载请注明原文出处。 记录开发单总线&#xff0c;读取DHT11温湿度 一、DHT11介绍 DHT11是串行接口&#xff08;单线双向&#xff09;DATA 用于微处理器与 DHT11之间的通讯和同步&#xff0c;采用单总线数据格式&#xff0c;一次通讯时间4ms左右…

利用一维数组计算今天是今年的第几天

分析&#xff1a; 在一维数组里初始化12个月份&#xff0c;在进行判断是不是闰年&#xff0c;是闰年就把数组的二月的下标改为29&#xff0c;否则不变就按照平年计算&#xff0c;最后把想要计算的月份减1累加到sum里&#xff0c;在进行计算该月份的天也要累加。例如&#xff1a…

神经网络处理器模拟器的一点思考

一 神经网络处理器 通常基于FPGA的神经网络处理器进行部署某种网络&#xff0c;考虑的因素较多&#xff0c;具体包括网络模型的不同&#xff0c;涵盖不同的算子、激活函数、调度策略等等&#xff1b;具体硬件实现&#xff0c;涉及神经网络处理器并行度、硬件资源消耗&#xff0…

java高级——Collection集合之Set探索(底层为HashMap实现)

java高级——Collection集合之Set探索 前情提要文章介绍继承结构底层代码&#xff08;一张图你就悟了&#xff09;下期预告 前情提要 上一篇文章我们探索了HashMap&#xff0c;详细解说了哈希冲突&#xff0c;红黑树以及Map底层到底是怎么实现的&#xff0c;这一篇我们简单说一…

图像生成(Text-to-Image)发展脉络

这篇博客对 图像生成&#xff08;image generation&#xff09; 领域的经典工作发展进行了梳理&#xff0c;包括重要的一些改进&#xff0c;目的是帮助读者对此领域有一个整体的发展方向把握&#xff0c;并非是对每个工作的详细介绍。 脉络发展&#xff08;时间顺序&#xff0…

气膜工业仓储与气膜体育馆的配置区别—轻空间

气膜工业仓储和气膜体育馆在配置上有明显的区别&#xff0c;这主要是由于它们的使用功能和环境不同所导致的。 结构设计 气膜工业仓储&#xff1a; 主要设计为大跨度、大空间&#xff0c;以便容纳大量货物。 气膜体育馆&#xff1a; 设计注重支撑观众席、运动场地和相关设施&…

Golang | Leetcode Golang题解之第274题H指数

题目&#xff1a; 题解&#xff1a; func hIndex(citations []int) int {// 答案最多只能到数组长度left,right:0,len(citations)var mid intfor left<right{// 1 防止死循环mid(leftright1)>>1cnt:0for _,v:range citations{if v>mid{cnt}}if cnt>mid{// 要找…

One-Class SVM

前提知识&#xff1a;支持向量机&#xff08;SVM&#xff09;-CSDN博客 主要思想 找一个超平面将样本中的正例圈出来&#xff0c;预测就是用这个超平面做决策&#xff0c;在圈内的样本就认为是正样本&#xff0c;圈外的是其他样本&#xff0c;如图1所示&#xff1a; 图1 OSVM…

完整创建一个vite前端项目

目录 1.先创建一个vite项目 2.下载第三方依赖 ① 安装路由vue-router ② 安装vuex全局数据管理 ③ 安装element-plus ④ 安装element-plus图标 ⑤ 安装axios发送请求 ⑥ 完整main.js代码模板 3.开发组件 4.登陆页面开发用例 5. 完整项目代码 废话少说&#xff0c;直接…

【C#】| 与 及其相关例子

按位或&#xff08;|&#xff09; 按位或运算符 | 对两个数的每一位进行比较&#xff0c;如果两个数中至少有一个为 1&#xff0c;则结果位为 1&#xff1b;否则&#xff0c;结果位为0。 1010 (10 in decimal) | 1100 (12 in decimal) ------1110 (14 in decimal) 力扣相关…