单向散列函数及案例(代码片段)

小圣. 小圣.     2023-02-19     602

关键词:

1. 概述

单向散列函数(one-way hash function),又称单向Hash函数、杂凑函数。有一个输入和一个输出,输入的数据称为消息(message),输出的数据称为散列值(hash value)。单向散列函数根据输入消息的内容计算出散列值,而散列值可以被用来检验消息的完整性等。

1.1 单向散列函数的性质

  • 根据任意长度的消息计算出固定长度的散列值
  • 消息不同散列值也不同,又称抗碰撞性
  • 无法或很难通过散列值计算的到消息,又称单向性

1.2 单向散列函数的应用

  • 检测软件是否被篡改:如果软件被篡改后,那么散列值就会发生变化。
  • 消息认证码:消息认证码是将发送者和接收者之间的共享密钥和消息进行混合后计算出的散列值。使用消息认证码可以防止通信过程中的错误、篡改以及伪装。
  • 数字签名:单向散列函数加上非对称加密算法就是数字签名,利用数字签名可以防止对数据的否认。
  • 伪随机数生成器:为了保障随机数的不可预测性,可以利用单向散列函数的单向性。

2. MD4、MD5

2.1 介绍

MD4是由 Ronald Rivest于1990年设计的一种信息摘要算法。它是一种用来测试信息完整性的密码散列函数的实现。其散列值长度为128位
MD5也是由Ronald Rivest设计,于1992年公开,用于取代MD4算法。是被广泛使用的密码散列函数,可以产生出一个128位的散列值(hash value),主要用于确保信息传输完整一致。1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。

MD4和MD5中的MD就是消息摘要(Message Digest),在Go语言中,默认只提供了MD5的包。

2.2 案例

// 对少量数据进行MD5
func MD5Test1(data string) 
	// 计算散列值
	result := md5.Sum([]byte(data))
	fmt.Printf("少量数据hash后的数据:%x\\n", result)


// 对文件进行hash
func MD5Test2(fileName string) 
	// 获取文件句柄
	f, err := os.Open(fileName)
	if err != nil 
		fmt.Println("open file err:", err)
		return
	
	defer f.Close()

	// 获取hash器
	hasher := md5.New()
	// 把文件内容拷贝到hash器
	_, err = io.Copy(hasher, f)
	if err != nil 
		fmt.Println("copy data err: ", err)
		return
	

	// 计算散列值
	result := hasher.Sum(nil)

	fmt.Printf("大量数据hash后的数据:%x", result)

3. RIPEMD160

3.1 介绍

RIPMD(RIPEMD(RACE Integrity Primitives Evaluation Message Digest,RACE 原始完整性校验讯息摘要)。是一种加密哈希函数,由鲁汶大学 Hans Dobbertin,Antoon Bosselaers 和 Bart Prenee组成的COSIC 研究小组发布于1996年。 RIPEMD以MD4为基础原则进行设计。RIPEMD-160是其中的一种,这一系列函数还包括RIPEMD-128、RIPEMD-256、RIPEMD-320。

3.2 案例

// 对少量数据进行hash
func Ripemd160Test1(data string) 
	// 获取hash器
	hahser := ripemd160.New()
	// 计算散列值
	result := hahser.Sum([]byte(data))
	fmt.Printf("少量数据hash后的数据:%x\\n", result)


// 对文件进行hash
func Ripemd160Test2(fileName string) 
	// 获取文件句柄
	f, err := os.Open(fileName)
	if err != nil 
		fmt.Println("open file err:", err)
		return
	
	defer f.Close()

	// 获取hash器
	hasher := ripemd160.New()
	// 把文件内容拷贝到hash器
	_, err = io.Copy(hasher, f)
	if err != nil 
		fmt.Println("copy data err: ", err)
		return
	

	// 计算散列值
	result := hasher.Sum(nil)

	fmt.Printf("大量数据hash后的数据:%x", result)

4. SHA-1、SHA-2

4.1 介绍

SHA-1是由NIST(NationalInstituteOfStandardsandTechnology,美国国家标准技术研究所)设计的一种能够产生160比特的散列值的单向散列函数。1993年被作为美国联邦信息处理标准规格(FIPS PUB 180)发布的是SHA,1995年发布的修订版FIPS PUB 180-1称为SHA-1。但是SHA-1 的强抗碰撞性已于2005年被攻破, 也就是说,现在已经能够产生具备相同散列值的两条不同的消息。
于是就是产生了SHA-2,SHA2的单向散列函数包括SHA-256、SHA-384、SHA-512。目前SHA-2还没有被攻破。

4.2 SHA-256案例

// 对少量数据进行hash
func Sha256Test1(data string) 
	// 计算散列值
	result := sha256.Sum256([]byte(data))
	fmt.Printf("少量数据hash后的数据:%x\\n", result)


// 对文件进行hash
func Sha256Test2(fileName string) 
	// 获取文件句柄
	f, err := os.Open(fileName)
	if err != nil 
		fmt.Println("open file err:", err)
		return
	
	defer f.Close()

	// 获取hash器
	hasher := sha256.New()
	_, err = io.Copy(hasher, f)
	if err != nil 
		fmt.Println("copy data err: ", err)
		return
	

	// 计算散列值
	result := hasher.Sum(nil)

	fmt.Printf("文件数据hash后的数据:%x", result)

5. POW共识算法的实现

5.1 介绍

工作量证明(Proof-of-Work,PoW)是一种对应服务与资源滥用、或是拒绝服务攻击的经济对策。一般要求用户进行一些耗时适当的复杂运算,并且答案能被服务方快速验算,以此耗用的时间、设备与能源做为担保成本,以确保服务与资源是被真正的需求所使用。比特币的共识算法就是工作量证明。

在比特币系统中,完成工作量证明的条件是:不断地对区块头进行哈希,直到计算出一个小于目标值的hash值。在计算期间,会不断的变化区块头中的nonce值。

5.2 代码实现

// 定义区块结构
type Block struct 
	// 版本号
	Version uint64
	// 前区块哈希
	PrevHash []byte
	// Merkel根
	MerkelRoot []byte
	// 时间戳
	TimeStamp uint64
	// 难度值
	Bits uint64
	// 随机数,也就是挖矿要找的数据
	Nonce uint64


func Pow(block *Block) *Block 

	// 模拟目标值
	target := "0000100000000000000000000000000000000000000000000000000000000000"

	// 定义bigInt类型
	targetInt := big.Int
	// 将难度值转换成bigInt类型,指定为16进制格式
	targetInt.SetString(target, 16)

	// 计算出指定的哈希值
	var nonce uint64
	var hash [32]byte
	for 
		// 拼装区块数据,主要是nonce这个字段
		tempBlock := [][]byte
			Uint64ToByte(block.Version),
			block.PrevHash,
			block.MerkelRoot,
			Uint64ToByte(block.TimeStamp),
			Uint64ToByte(block.Bits),
			// 这个值不断变换
			Uint64ToByte(nonce),
		
		// 将二维切片转成一维切片
		blockInfo := bytes.Join(tempBlock, []byte)

		// 做哈希运算
		hash = sha256.Sum256(blockInfo)

		// 将计算出的hash转成bigInt,好和目标值比较
		blockInt := big.Int
		blockInt.SetBytes(hash[:])

		// 与目标值比较,如果小于目标值,就代表找到了
		if blockInt.Cmp(&targetInt) == -1 
			block.Nonce = nonce
			return block
		 else 
			// 没有找到,nonce值加1
			nonce++
		

	

运行结果:

文章中的所有代码已上传到github: https://github.com/bigzoro/cryptography/tree/main/hash

单向散列函数及案例(代码片段)

1.概述单向散列函数(one-wayhashfunction),又称单向Hash函数、杂凑函数。有一个输入和一个输出,输入的数据称为消息(message),输出的数据称为散列值(hashvalue)。单向散列函数根据输入消息... 查看详情

一文搞懂单向散列函数(代码片段)

微信搜索:码农StayUp主页地址:https://gozhuyinglong.github.io源码分享:https://github.com/gozhuyinglong/blog-demos1.定义单向散列函数(one-wayhashfunction)是指对不同的输入值,通过单向散列函数进行计算, 查看详情

图解密码技术笔记单向散列函数——获取消息的指纹

单向散列函数——获取消息的指纹单向散列函数(one-wayhashfunction),有一个输入和输出,其中输入称为消息(message),输出称为散列值(hashvalue)。单向散列函数可以根据消息的内容计算出散... 查看详情

密码技术之认证

...内容,只要对比它们的“指纹”就行了。  一、单向散列函数(one-way hash function)    单向散列函数也称为消息摘要函数(message digest function)、哈希函数或者杂凑函数。    单向散列函数有一个... 查看详情

单向散列函数的价值和具体实现的详细使用

关于术语不同的参考书使用的术语有所不同:单向散列函数(one-wayhashfunction)、消息摘要函数(messagedigestfunction)、哈希函数、杂凑函数输入的是消息(message)也称为原像(pre-image)输出的是散列值(hashvalue),或消息摘要(messa... 查看详情

加密算法及hashlib模块(代码片段)

加密算法介绍HASHHash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散... 查看详情

哈希表(散列)(代码片段)

哈希表的基本介绍●散列表(Hashtable,也叫哈希表),是根据关键码值(Keyvalue)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录... 查看详情

单向散列加密

...并存储到数据库。或者验证文件唯一性等。这时就要用到单向散列加密。  单向散列函数特点  1.对任意长度的消息散列值是定长的。  2.散列计算速度快,非常高效。  3.明文不同,散列加密后的密文一定不同;明文相... 查看详情

hashlib模块的使用(代码片段)

...两把不同的密钥,公钥用于加密数据,私钥用于解密数据单向加密:只能加密数据,而不能解密数据hash:散列函数,一般翻译为哈希,把的任意长度的数据,通过散列函数进行转化,变成一个长度固定的值(散列值),这个值基本是... 查看详情

常用sql语句及案例(oracle)(代码片段)

目录1)基本2)数学函数3)rownum4)分页5)时间处理6)字符函数7)to_number8)聚合函数9)学生选课10)图书馆借阅 基本--新建表:createtabletable1(idvarchar(300)primarykey,namevarchar(200)notnull);--插入数据insertintotable1(id,name)values(‘aa‘,... 查看详情

react生命周期(新旧)及案例(代码片段)

...亡它会经历一些特定的阶段。React组件中包含一系列钩子函数(生命周期回调函数),会在特定的时刻调用。在定义组件时,会在特定的生命周期回调函数中,做特定的工作旧生命周期生命周期的三个阶段(旧)三个... 查看详情

hive窗口函数极速入门及在拉链表上的运用案例(代码片段)

1over()窗口函数1.1语法结构分析函数over(partitionby列名orderby列名rowsbetween开始位置and结束位置)1.2over中的三个函数具体含义orderby:排序的意思,跟sql一样partitionby:分区的概念,后面接字段表示跟什么分区,比如日期partitionbydayrowsbetw... 查看详情

opencv-python图像平滑处理2:blur函数及滤波案例(代码片段)

...为盒状滤波器。在《OpenCV-Python图像平滑处理1:卷积函数filter2D详解及用于均值滤波的案例》介绍了使用 查看详情

linux网络编程基础及多线程并发案例(代码片段)

...  2.socket头文件  sys/socket.h     3.字节序4.ip地址转换函数5.sockaddr和sockaddr_in6.服务器端基本函数bind listenaccept7.客户端基本函数  connect8.send和recv 8.多线程9.通信流程10.多线程并发样例程序 1.ip:端口 TCP/IP协议    AF_INET   ... 查看详情

opencv-python图像平滑处理3:boxfilter函数详解及均值滤波案例(代码片段)

...为盒状滤波器。在《OpenCV-Python图像平滑处理1:卷积函数filter2D详解及用于均值滤波的案例》介绍了使用 查看详情

python中hash值计算的学习笔记(代码片段)

...成一个定长的输出,即散列值。这种散列变换是一种单向运算,具有不可逆性即不能根据散列 查看详情

哈希函数的三个性质

...机数是一个指定的解,基于某种率先加密的哈希函数具有单向性和隐秘性,既不能反向解出输入值也无法仅凭尝试找到输入值。此外,不同的输入产生不同的哈希函数,每次返回设定大小的位数形成信息摘要,极大地节省了网络... 查看详情

md5算法原理及实现

参考技术A散列函数,也称作哈希函数,消息摘要函数,单向函数或者杂凑函数。散列函数主要用于验证数据的完整性。通过散列函数,可以创建消息的“数字指纹”,消息接收方可以通过校验消息的哈希值来验证消息的完整性... 查看详情