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,纠结了我半天。。。


参考文献

原文链接:常见哈希函数FNV和MD5,转载请注明来源!

EOF