本文发布于Cylon的收藏册,转载请著名原文链接~

散列函数(Hash function)又称散列算法、哈希函数,散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。该函数将数据打乱混合,重新创建一个叫做散列值(hash values)的指纹。这种转化是一种压缩映射,也就是散列值的空间通常远小于输入值的空间,不同的输入可能会散列成相同的输出,二不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要函数

散列函数性质

通过使用单向散列函数,即便是确认几百MB大小的文件的完整性,也只要对比很短的散列值就可以了。那么,单向散列函数必须具备怎样的性质呢?我们来整理一下。

  • 根据任意长度的消息计算出固定长度的散列值

  • 能够快速计算出散列值

计算散列值所花费的时间短。尽管消息越长,计算散列值的时间也会越长,但如果不能在现实的时间内完成计算就没有意义了。

  • 消息不同散列值也不同

  • 难以发现碰撞的性质称为抗碰撞性(collisionresistance)。密码技术中所使用的单向散列函数,都需要具备抗碰撞性。强抗碰撞性,是指要找到散列值相同的两条不同的消息是非常困难的这一性质。在这里,散列值可以是任意值。密码技术中的单向散列函数必须具备强抗碰撞性。

  • 具备单向性

单向散列函数必须具备单向性(one-way)。单向性指的是无法通过散列值反算出消息的性质。根据消息计算散列值可以很容易,但这条单行路是无法反过来走的。

散列函数的应用

散列函数应用具有多样性

安全加密:

  • 保护资料,散列值可用于唯一地识别机密信息。这需要散列函数是抗碰撞(collision-resistant)的,意味着很难找到产生相同散列值的资料。如数字签名、消息认证码。

数据校验:

  • 确保传递真实的信息:消息或数据的接受者确认消息是否被篡改的性质叫数据的真实性,也称为完整性。
  • 错误校正:使用一个散列函数可以很直观的检测出数据在传输时发生的错误。

负载均衡:

  • 通过hash算法,对客户端IP进行计算hash值,将取到值与服务器数量进行取模运算。

分布式存储:如一致性hash。

常用单项散列函数

MD4 MD5

MD5在1996年后被证实存在弱点,可以被加以破解,对于需要高度安全性的资料,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞攻击,因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。

SHA-1 SHA-2

SHA-1:1995年发布,SHA-1在许多安全协议中广为使用,包括TLS、GnuPG、SSH、S/MIME和IPsec,是MD5的后继者。但SHA-1的安全性在2010年以后已经不被大多数的加密场景所接受。2017年荷兰密码学研究小组CWI和Google正式宣布攻破了SHA-1。

SHA-2:2001年发布,包括SHA-224SHA-256SHA-384SHA-512SHA-512/224SHA-512/256SHA-2目前没有出现明显的弱点。虽然至今尚未出现对SHA-2有效的攻击,但它的算法跟SHA-1基本上仍然相似。 比特币使用的sha-256进行的数字签名

算法和变体 输出散列值长度 (bits) 中继散列值长度 (bits) 资料区块长度 (bits) 最大输入消息长度 (bits)
MD5 128 128 (4 × 32) 512 无限
SHA-0 160 160 (5 × 32) 512 264 − 1
SHA-1 160 160 (5 × 32) 512 264 − 1
SHA-2 SHA-224 SHA-256 224 256 256 (8 × 32) 512
SHA-384 SHA-512 SHA-512/224 SHA-512/256 384 512 224 256 512 (8 × 64) 1024 2128 − 1

Go语言中使用散列函数

Go语言使用MD5

方式一:

1
md5.Sum("123")

方式2:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
func getMD5_2(str []byte) string {
	// 1. 创建一个使用MD5校验的Hash对象`
	myHash := md5.New()
	// 2. 通过io操作将数据写入hash对象中
	io.WriteString(myHash, "hello")
	//io.WriteString(myHash, ", world")
	myHash.Write([]byte(", world"))
	// 3. 计算结果
	result := myHash.Sum(nil)
	fmt.Println(result)
	// 4. 将结果转换为16进制格式字符串
	res := fmt.Sprintf("%x", result)
	fmt.Println(res)
	// --- 这是另外一种格式化切片的方式
	res = hex.EncodeToString(result)
	fmt.Println(res)

	return res
}

Go语言SHA-1、SHA-2的使用

方法一:

1
2
sha512.Sum512()
sha256.Sum256()

方法二与md5的使用类似

本文发布于Cylon的收藏册,转载请著名原文链接~

链接:https://www.oomkill.com/2020/11/hash-function/

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」 许可协议进行许可。