常见哈希函数FNV和MD5
28 July 2014
关于Golang语言的哈希函数FNV和MD5的简单介绍。
介绍哈希函数之前,先说一下Golang的哈希结果。在包/hash/
下的hash.go文件,定义了哈希函数的接口。所有哈希函数都要实现此接口。
// Hash is the common interface implemented by all hash functions.
type Hash interface {
// Write (via the embedded io.Writer interface) adds more data to the running hash.
// It never returns an error.
io.Writer
// Sum appends the current hash to b and returns the resulting slice.
// It does not change the underlying hash state.
Sum(b []byte) []byte
// Reset resets the Hash to its initial state.
Reset()
// Size returns the number of bytes Sum will return.
Size() int
// BlockSize returns the hash's underlying block size.
// The Write method must be able to accept any amount
// of data, but it may operate more efficiently if all writes
// are a multiple of the block size.
BlockSize() int
}
此接口提供了常用的Sum
等函数,此外,它还继承了io.Writer
接口。该接口定义在io
包里的io.go文件里。该接口定义了Write
写入函数。
// Writer is the interface that wraps the basic Write method.
//
// Write writes len(p) bytes from p to the underlying data stream.
// It returns the number of bytes written from p (0 <= n <= len(p))
// and any error encountered that caused the write to stop early.
// Write must return a non-nil error if it returns n < len(p).
type Writer interface {
Write(p []byte) (n int, err error)
}
常见的哈希函数调用过程大体如此,初始化hash.Hash之后,通过Write
写入数据,通过Sum
函数得到哈希结果。其中,Sum(b []byte) []byte
函数的参数b,当传入nil
的时候,将直接返回哈希结果,而b不为空的时候,就会将哈希结果追加到b后面。
MD5的加密算法调用如下,源码:
package main
import (
"crypto/md5"
"encoding/hex"
)
func main() {
m := md5.New()
m.Write([]byte("hello, world"))
s := hex.EncodeToString(m.Sum(nil))
println(s)
}
FNV的加密调用也很简单,源码。fnv.New32()
使用的是32位的FNV-1算法进行的哈希。
package main
import "fmt"
import "hash/fnv"
import "encoding/hex"
func main() {
a := fnv.New32()
a.Write([]byte("hello"))
fmt.Println(hex.EncodeToString(a.Sum(nil)))
}
FNV是一种非加密的哈希算法,支持32位、64位、128位、256位、512位和1024位的哈希。碰撞还算比较低,具体的碰撞的对比可以网上查一下。
直接哈希得到的都是整数类型,直接输出的话就会是乱码了,如果想查看正常的哈希结果,需要将结果转成对应表示的字符即可。使用包encoding/hex
可以帮助实现十六进制编码。
补充一下。。。基础不好的坑自己。。。
MD5加密结果是32个16进制数,而一个字节能表示的范围是0~255,256=16×16,也就是两个十六进制数代表一个字节。所以Sum
函数得到的byte数组长度是16,纠结了我半天。。。
参考文献
- 【1】Package fnv - The Go Programming Language
- 【2】Fowler–Noll–Vo hash function - wikipedia
- 【3】FNV哈希算法 - 思思入code
原文链接:常见哈希函数FNV和MD5,转载请注明来源!
–EOF–