【OpenSSL】单向散列函数

news2024/11/25 18:48:29

什么是单向散列函数

  1. 任意长度数据生成固定长度是散列
  2. 快速计算
  3. 消息变化散列变化
  4. 单向不可逆,抗碰撞

应用场景

  1. 文件完整性
  2. 口令加密
  3. 消息认证
  4. 伪随机数
  5. 配合非对称加密做数字签名
  6. 比特币工作量证明

单向hash抗碰撞

弱抗碰撞

给定Xhash值的情况下,找到另外个数,hash值相同。

强抗碰撞

  • 找到散列值相同的两个字符串
  • MD5,SHA-1已经被攻破可以找到相同散列值的不同消息

常用的Hash算法

  • MD5
  • SHA1
  • SHA2(SHA-256 SHA-384 SHA-512)
  • SHA3 Keccak256 选举产生
  • 国密SM3

MD5算法

  • 消息摘要(Message Digest)
  • 产生128比特(16字节) 散列值(RFC1321)
  • 强抗碰撞已经被破, 2004年王小云攻破
  • 已经不安全, 如果应用加salt
  • 历史系统最广泛,效率高

原理

  1. 补结尾处的字节, 取余448,补1后再补0,补足到448位
  2. 剩余64位做存储原始数据的长度
  3. 初始化MD缓冲, A: 01 23 45 67,B:89 1b cd ef …
  4. 4个函数处理消息块

Open SSL实现MD5

#include <iostream>
#include <openssl/md5.h>

using namespace std;

//将二进制转换成16进制的文本字符
string char2Hex(unsigned char *out,  int len)
{
	const unsigned char hex_chars[] = "0123456789ABCDEF";
	string result;
	for (int i = 0; i < len; i++) 
	{
		unsigned char ch = out[i];
		unsigned int hc = (ch >> 4) & 0xf;
		unsigned int lc = ch & 0x0f;
		//采用大端存储的方式拼接
		result += hex_chars[hc];
		result += hex_chars[lc];
	}
	return result;
}

string MD5Hash(unsigned char *data, size_t len)
{
	//初始化MD5环境
	MD5_CTX ctx;
	MD5_Init(&ctx);

	// 计算MD5hash数据
	MD5_Update(&ctx, data, len);

	//读取数据
	unsigned char out[16] = { 0 }; // 只有16个字节
	//把数据读取到out中
	MD5_Final(out, &ctx);
	return char2Hex(out, 16);
}

//采用简化模式实现MD5
string MD5HashSimple(unsigned char* data, size_t len)
{
	//读取数据
	unsigned char out[16] = { 0 }; // 只有16个字节
	//把数据读取到out中
	MD5(data, len, out);
	return char2Hex(out, 16);
}

int main(int argc, char* argv[])
{
	unsigned char data[] = "测试md5数据";
	int len = sizeof(data);
	string result = MD5Hash(data, len);
	cout <<"MD5:"<<result<< endl;
	data[0] = '9';
	result = MD5HashSimple(data, len);
	cout << "MD5:" << result << endl;
}

计算文件的MD5值

string GetFileListHash(string filepath) 
{
	string hash;
	/ 以二进制方式
	ifstream ifs(filepath, ios::binary);
	if (!ifs)
		return hash;

	int block_size = 128;
	// 文件读取buf
	unsigned char buf[1024] = { 0 };
	//hash输出
	unsigned char out[1024] = { 0 };
	while (!ifs.eof())
	{
		ifs.read((char*)buf, block_size);
		int read_size = ifs.gcount();
		if (read_size < 0)
		{ 
			break; 
		}
		MD5(buf, read_size, out);
		hash.insert(hash.end(), out, out + 16);
	}
	ifs.close();
	MD5((unsigned char*)hash.data(), hash.size(), out);
	return char2Hex(out, 16);
}

SHA-1算法

  • 安全散列算法(Secure Hash Algorithm)
  • 消息摘要(Message Digest)
  • 产生160比特(20字节) 散列值H0 H1 H2 H3 H4
  • 强抗碰撞已经攻破, 在2005年王小云攻破。
  • MD5一样都是由MD4导出。

代码演示

代码实现与MD5类似, 分为三步.

  1. 初始化SHA上下文
  2. 对数据进行hash计算
  3. 读取hash计算结果
    代码如下:
string SHA1Hash(unsigned char* data, size_t len)
{
	// 首先也是初始化SHA1的上下文
	SHA_CTX ctx;
	SHA1_Init(&ctx);

	// 编码数据
	SHA1_Update(&ctx, data, len);
	//读取数据
	unsigned char out[20];
	SHA1_Final(out, &ctx);
	//将字节内容转换为字符
	return char2Hex(out, 20);
}

同样,为了方便调用,open ssl对上述过程进行了封装。仅用一个SHA1函数即可实现以上3步。测试代码如下

//简化函数实现SHA1
string SHA1HashSimple(unsigned char* data, size_t len)
{
	unsigned char out[20];
	SHA1(data, len, out);
	return char2Hex(out, 20);
}

测试:

int main(int argc, char* argv[])
{
	// --- 测试MD5
	unsigned char data[] = "测试md5数据";
	int len = sizeof(data);
	// 测试SHA1
	string hash = SHA1Hash(data, len);
	cout << "SHA1:\t" << hash << endl;

	//简介函数测试
	hash = SHA1HashSimple(data, len);
	cout << "SHA1:\t" << hash << endl;
	return 0;
}

运行结果:
在这里插入图片描述
使用sha1测试Merkle Tree算法


//文件可信树
string GetFileMerkleHash(string filepath)
{
	string hash;
	// 存放hash列表, 后面所有结果都存在其中
	vector<string> hashs;
	ifstream ifs(filepath, ios::binary);
	if (!ifs)
	{
		cout << "文件" << filepath << "不存在" << endl;
		return hash;
	}

	unsigned char buf[1024] = { 0 };
	unsigned char out[1024] = { 0 };
	int block_size = 128;
	while (!ifs.eof())
	{
		ifs.read((char*)buf, block_size);
		int read_size = ifs.gcount();
		if (read_size <= 0)
		{
			break;
		}
		SHA1(buf, read_size, out);
		hashs.push_back(string(out, out + 20));
	}
	while (hashs.size() > 1) // ==1表示已经计算到root节点
	{
		// 不是二的倍数补节点(二叉树)
		if (hashs.size() & 1)
		{
			hashs.push_back(hashs.back());
		}
		// 把hash结果的hash结果还吸入到hashs中
		for (int i = 0; i < hashs.size() / 2; i++)
		{
			// 两个节点拼起来, i表示的父节点
			string tmp_hash = hashs[i * 2]; // 左节点
			tmp_hash += hashs[i * 2 + 1]; // 右节点
			SHA1((const unsigned char*)tmp_hash.data(), tmp_hash.size(), out);
			// 写入结果
			hashs[i] = string(out, out + 20);
		}
		// hash列表删除上一次多余的hash值
		hashs.resize(hashs.size() / 2);
	}

	if (hashs.size() == 0) return hash;
	return char2Hex((unsigned char*)hashs[0].data(), 20);
}

SHA-2算法

类别SHA-1SHA-224SHA-256SHA-384SHA-512
消息摘要长度160224256384512
消息长度小于 2 64 2^{64} 264小于 2 64 2^{64} 264小于 2 64 2^{64} 264小于 2 128 2^{128} 2128小于 2 128 2^{128} 2128
分组长度51251251210241024
计算字长度3232326464
计算步骤数8064648080
  • 消息填充摸512与448同余补充消息长度。
  • 初始化链接变量 缓冲区用8个32位寄存器(SHA256
  • 取自前8个素数(2、3、5、7、11、13、17、19)的平方根的小数部分其二进制表示的前32位 8 ∗ 32 = 256 8*32=256 832=256.
  • SHA512是用64位寄存器
  • 以512位(64)分组位单位处理, 进行64步循环, SHA512以1024(128)位为以个分组
  • SHA-384SHA-512也都有6个迭代函数
string SHA256Hash(const unsigned char* data, size_t len) 
{
	// 初始化SHA256的上下文
	SHA256_CTX ctx;
	SHA256_Init(&ctx);
	
	// 开始写入数据
	SHA256_Update(&ctx, data, len);

	// 读取数据
	unsigned char out[32] = {0};
	SHA256_Final(out, &ctx);
	return char2Hex(out, 32);
}
string SHA256HashSimple(const unsigned char* data, size_t len) 
{
	unsigned char out[32];
	SHA256(data, len, out);
	return char2Hex(out, 32);
}

SHA-3算法

海绵结构, 把数据压到海绵里面。

  1. 填充,
  2. 分组4组
  3. 与初始值异或
    在这里插入图片描述

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

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

相关文章

2. PCIE TLP解包封包

第二十一讲、PCIE的TLP包的封包解包原理.pdf 00 Packet Coding.docx 掌握如何发送接收 Mrd&#xff08;memory read TLP&#xff09;、Mwr(Memory write TLP)、Cpl(Completion TLP)和Cpld(Completion with data TLP) 命令包 1、 TLP 包是由 PCIE 的 Endpoint 或者 Root Complex…

使用PageHelper进行分页

使用PageHelper进行分页 1. 使用Spring Boot2. 不使用Spring Boot的实现 1. 使用Spring Boot 要在Spring MVC中使用PageHelper进行分页&#xff0c;你需要完成以下几个步骤&#xff1a; 添加PageHelper依赖&#xff1a;在你的项目中添加PageHelper的Maven或Gradle依赖。例如&…

22年4月后树莓派烧录镜像、联网以及ssh 远程投屏失败的注意事项

1. 树莓派刷机 树莓派在22年4月后新增了关于对用户安全的修改&#xff0c;所以之前的在SD 卡中放入ssh文件以及wifi 账号和密码的方法已经不好使了。很多用户发现烧录镜像后找不到树莓派ip了&#xff0c;特别是没有屏幕的用户&#xff0c;ssh更是连接不上。 解决办法就是官网…

[C#]vs2022安装后C#创建winform没有.net framework4.8

问题&#xff0c;我已经在visualstudio安装程序中安装了.net框架4.8的SDK和运行时。 然而&#xff0c;我在visual studio 2022中找不到已安装的框架。 我已经检查了我的VS 2019&#xff0c;它可以很好地定位网络框架4.8&#xff0c;它可以构建我的项目。但VS 2022不能。 我已经…

RocketMQ源码解析(上)

一、ACL权限控制 应用场景&#xff1a; ​RocketMQ提供了针对队列、用户等不同维度的非常全面的权限管理机制。通常来说&#xff0c;RocketMQ作为一个内部服务&#xff0c;是不需要进行权限控制的&#xff0c;但是&#xff0c;如果要通过RocketMQ进行跨部门甚至跨公司的合作&…

公司如何监控员工自己的电脑(监控单位员工电脑的几个好用的方法)

在现代的商业环境中&#xff0c;公司需要在保护敏感数据和确保员工生产力之间找到平衡。为此&#xff0c;许多公司选择监控员工的电脑使用情况。本文将详细介绍如何专业且有效地监控公司员工电脑。 一、为何需要监控员工电脑 公司可能会出于各种原因去监控员工的电脑使用&…

CSS中的定位

position 的属性与含义 CSS 中的 position 属性用于控制元素在页面中的定位方式&#xff0c;有四个主要的取值&#xff0c;每个取值都会影响元素的布局方式&#xff0c;它们是&#xff1a; static&#xff08;默认值&#xff09;&#xff1a; 这是所有元素的初始定位方式。在静…

字符函数和字符串函数(C语言进阶)

字符函数和字符串函数 一.求字符串长度1.strlen 二.长度不受限制的字符串函数介绍1.strcpy2.strcat3.strcmp 前言 C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在常量字符串中或者字符数组中。 字符串常量适用于那…

[刷题记录]牛客面试笔刷TOP101(二)

(一)传送门: [刷题记录]牛客面试笔刷TOP101(一)_HY_PIGIE的博客-CSDN博客 目录 1.合并二叉树 2.二叉树的镜像 3.判断是否为二叉搜索树 4.判断是不是完全二叉树 1.合并二叉树 合并二叉树_牛客题霸_牛客网 (nowcoder.com) 思路: 在后序遍历的基础上进行,两颗二叉树可…

【网络协议】Http-中

搜索引擎&#xff1a;搜索引擎是指根据一定的策略、运用特定的计算机程序从互联网上采集信息&#xff0c;在对信息进行组织和处理后&#xff0c;为用户提供检索服务&#xff0c;将检索的相关信息展示给用户的系统。搜索引擎是工作于互联网上的一门检索技术&#xff0c;它旨在提…

WPF 类库 使用handycontrol 配置

在学习wpf发现了一个非常好用的UI库 handycontrol 但是很多地方讲的都是WPF应用程序怎么用&#xff0c;很少有讲类库那么引用的问题&#xff0c;所以在这里自己总结一下&#xff0c;希望能帮助到大家&#xff1a; 1.添加 handycontrol 的引用&#xff1b;安装&#xff0c;我已…

Webpack打包图片

一、在js文件中引入图片 二、在package.config.js中配置加载器 module.exports {mode: "production", // 设置打包的模式&#xff1a;production生产模式 development开发模式module: {rules: [// 配置img加载器{test: /\.(jpg|png|gif)$/i,type:"asset/resou…

计算机竞赛 深度学习+python+opencv实现动物识别 - 图像识别

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 inception_v3网络5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; *…

基于TensorFlow+CNN+协同过滤算法的智能电影推荐系统——深度学习算法应用(含微信小程序、ipynb工程源码)+MovieLens数据集(六)

目录 前言总体设计系统整体结构图系统流程图 运行环境模块实现1. 模型训练1&#xff09;数据集分析2&#xff09;数据预处理3&#xff09;模型创建4&#xff09;模型训练5&#xff09;获取特征矩阵 2. 后端Django3. 前端微信小程序1&#xff09;小程序全局配置文件2&#xff09…

【广州华锐互动】煤矿坍塌VR事故警示教育突破了哪些限制?

煤矿坍塌事故是煤矿行业的一种常见事故&#xff0c;对于矿工的生命安全和生产设备都存在着严重威胁。传统的安全培训方式往往难以真实地呈现事故场景&#xff0c;难以达到理想的安全教育效果。而虚拟现实&#xff08;VR&#xff09;技术的出现&#xff0c;为煤矿安全教育带来了…

测试人职场生存必须避开的5个陷阱

在互联网职场的工作发展道路上&#xff0c;软件测试人员其实在公司中也面临着各种各样的职场陷阱&#xff0c;有些可能是因为项目业务不熟练造成的&#xff0c;有些可能是自身技术能力不足导致的...等等。软件测试入门相对来说比较容易些&#xff0c;但是想要在测试行业长久发展…

力扣刷题-数组-数组理论基础

数组是存放在连续内存空间上的相同类型数据的集合。 需要两点注意的是 数组下标都是从0开始的。数组内存空间的地址是连续的 正是因为数组的在内存空间的地址是连续的**&#xff0c;所以我们在删除或者增添元素的时候&#xff0c;就难免要移动其他元素的地址。** 注意&…

S型加减速行车位置控制(支持点动和停靠位置搜索)

S型加减速位置控制详细算法和应用场景介绍&#xff0c;请查看下面文章博客。本篇文章不再赘述&#xff0c;这里主要介绍点动动和位置点搜索功能。 S速度曲线轨迹规划(普通变频位置闭环控制算法详细介绍SCL代码)_s曲线轨迹规划_RXXW_Dor的博客-CSDN博客位置控制用PD控制器&…

Rsync学习笔记2

Rsync&#xff1a; 增量操作&#xff1a; 1&#xff09; server01服务文件变动。 [rootserver03 tp5shop]# rsync -av /usr/local/nginx/html/tp5shop root192.168.17.109:/usr/local/nginx/html/ sending incremental file listsent 88,134 bytes received 496 bytes 177,…

KMP,ACM集训

目录 831. KMP字符串 输入格式 输出格式 数据范围 输入样例&#xff1a; 输出样例&#xff1a; 解析&#xff1a;KMP模板 D - Cyclic Nacklace 解析&#xff1a;KMP-next数组应用循环字符串判断 F - Power Strings 解析&#xff1a;KMP-next数组应用循环字符串判断 H - …