首页 > 解决方案 > 对为什么 hashsum、encode、print 与 Go 中的 write、hashum、encode、print 不同感到困惑?

问题描述

对不起标题。我想不出更好的方式来表达我的问题,如果其他人可以的话,我会很高兴地改变它。

哈希器定义为

hasher := md5.New()

无论如何,我很好奇为什么会这样:

fmt.Println(hex.EncodeToString(hasher.Sum([]byte(input))))

给我 6869d41d8cd98f00b204e9800998ecf8427e,而这个:

hasher.Write([]byte(input))
fmt.Println(hex.EncodeToString(hasher.Sum(nil))

给我 49f68a5c8493ec2c0bf489821c21fc3b 和这个:

fmt.Printf("%x\n", md5.Sum([]byte(input)))

给我 49f68a5c8493ec2c0bf489821c21fc3b。

标签: gocryptography

解决方案


一般hasher.Sum() 不会散列传递的切片。传递的切片用作目标:它将当前哈希附加到它,并且不会更改底层哈希状态。hasher.Write()显然在哈希计算中包含传递的切片。这两个例子根本不同,不同的结果不过是意料之中的。

始终阅读文档。hash.Hash.Sum()

// Sum appends the current hash to b and returns the resulting slice.
// It does not change the underlying hash state.
Sum(b []byte) []byte

因此,当您第一次调用时hasher.Sum(),无论您传递给它什么,就结果哈希而言都无关紧要。如果您之前没有写入任何内容hasher,您将看到初始哈希。

当你下一次调用时hasher.Write([]byte(input)),你会将 的字节写input入哈希器,所以当你调用hasher.Sum(nil)下一次时,你会看到计算出的 的哈希值input。由于您通过nil了,因此将分配一个新切片来容纳结果。

当您再次调用hasher.Write([]byte(input))时,如前所述:这不会更改哈希状态,传递的切片不用作输入,而仅用作“返回”结果的目的地,即当前哈希值。因此,您将获得与上次hasher.Sum(nil)调用相同的哈希值。显然,如果传递的切片没有足够的容量来存储结果,则会分配/使用一个新的切片。

请参阅这个完整的、可运行的示例,它重现了您的输出:

input := "hi"
hasher := md5.New()
fmt.Println(hex.EncodeToString(hasher.Sum([]byte(input))))

hasher.Write([]byte(input))
fmt.Println(hex.EncodeToString(hasher.Sum(nil)))

fmt.Printf("%x\n", md5.Sum([]byte(input)))

在Go Playground上尝试一下。


推荐阅读