一、哈希概述
Hash,音译“哈希”,翻译“散列”。哈希计算就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。这种操作有点类似于数据的“指纹”,任何数据哪怕修改一个Bit也是会产生不同散列值的,这就让消息传输的安全校验有了实现的方法。
哈希计算的特点是:
- 从源数据计算出哈希值容易,其生成快速,算力代价较小;
- 而从哈希值反推出源数据几乎不可能,即使可能也要付出高昂的算力成本;
- 哈希算法有可能产生碰撞。所谓“碰撞”,即两个不同的源数据根据同一种哈希算法生成同样的值。一般产生碰撞的概率非常小,这也检验哈希算法的优秀程度。
开发一套高安全性的哈希算法非常困难,业界里一般使用公开的被认证的哈希算法,如md5,sha1,sha256,sha512等,目前md5、sha1已被破解,但还是需要一定代价的,所以现在还在沿用,如果对安全性要求较高,建议使用sha256以上的哈希算法,但对于一些非外部传输的内部校验,还是可以使用md5的,毕竟正向算力成本低。
二、Go 使用哈希加密
Go标准库提供生成消息摘要(指纹)的哈希算法包:
- crypto/md5:实现了MD5哈希算法
- crypto/sha1:实现了SHA1哈希算法
- crypto/sha256:实现了SHA224和SHA256哈希算法
- crypto/sha512:实现了SHA384和SHA512哈希算法
下面我们来演示一下使用示例:
//基本的md5哈希运算
func BaseHash() {
src := "go func chan"
//md5计算
md5 := md5.New()
md5Bytes := md5.Sum([]byte(src))
md5String := hex.EncodeToString(md5Bytes)
fmt.Println("MD5 HASH:", md5String)
//sha224
sha224Bytes := sha256.Sum224([]byte(src))
sha224String := hex.EncodeToString(sha224Bytes[:])
fmt.Println("SHA224 HASH:", sha224String)
//sha256
sha256Bytes := sha256.Sum256([]byte(src))
sha256String := hex.EncodeToString(sha256Bytes[:])
fmt.Println("SHA256 HASH:", sha256String)
//sha384
sha384Bytes := sha512.Sum384([]byte(src))
sha384String := hex.EncodeToString(sha384Bytes[:])
fmt.Println("SHA384 HASH:", sha384String)
//sha512
sha512Bytes := sha512.Sum512([]byte(src))
sha512String := hex.EncodeToString(sha512Bytes[:])
fmt.Println("SHA512 HASH:", sha512String)
//OUTPUT:十六进制字符输出
//MD5 HASH: 676f2066756e63206368616ed41d8cd98f00b204e9800998ecf8427e
//SHA224 HASH: 5c6ce52ae98e2b27d9aac4d5e4d7b48dfe25fcc11e3f61a8afbeb5ef
//SHA256 HASH: 69ffe43189a4bc21eca8d70d74786366dd3afcb4a74cdd9c909bf15b538ecac6
//SHA384 HASH: 4692aa44548c74a5225ce399030039b7c7b5bd963f9c884d5a4810006ab4e3175bc88f27fe3377afab91140ecbd32de8
//SHA512 HASH: e4c52638805b941dce1d045c5211b307a7486c5e0110c1efe6f627a1b3e7a296d4c5558c10bd015f71c00483770afebc600962cd329aa1565a68231a824cab6c
}
对上述哈希计算分别进行压测得到性能结果的比较:
goos: darwin
goarch: amd64
pkg: cryptography/myHASH
BenchmarkMd5-4 2000000 611 ns/op 1280 B/op 5 allocs/op
--- BENCH: BenchmarkMd5-4
HashBenchmark_test.go:9: 开始基准测试MD5!!!!
...
BenchmarkSha224-4 2000000 674 ns/op 288 B/op 3 allocs/op
--- BENCH: BenchmarkSha224-4
HashBenchmark_test.go:19: 开始基准测试Sha224!!!!
...
BenchmarkSha256-4 2000000 676 ns/op 288 B/op 3 allocs/op
--- BENCH: BenchmarkSha256-4
HashBenchmark_test.go:29: 开始基准测试Sha256!!!!
...
BenchmarkSha384-4 2000000 683 ns/op 352 B/op 3 allocs/op
--- BENCH: BenchmarkSha384-4
HashBenchmark_test.go:39: 开始基准测试Sha384!!!!
...
BenchmarkSha512-4 2000000 721 ns/op 416 B/op 3 allocs/op
--- BENCH: BenchmarkSha512-4
HashBenchmark_test.go:49: 开始基准测试Sha512!!!!
...
PASS
ok cryptography/myHASH 10.184s
由上可见其:
性能 : md5>sha224>sha256>sha384>sha512
内存消耗:md5>sha512>sha384>sha256=sha224
相较取舍后,建议平常使用sha256即可,安全性可靠且消耗资源不高。
除了对单个字符串进行哈希,也可分多次添加字符串哈希,下面简单示例:
//多输入源的哈希运算
func MultiSha256(srcs ...string) string {
hash := sha256.New()
//往哈希运算器里添加数据
for _, v := range srcs {
io.WriteString(hash, v)
}
//一般这种方式的参数为nil,因为很少有拼接b哈希运算的情况
bytes := hash.Sum(nil)
//十六进制字符串转换输出
hashString := hex.EncodeToString(bytes)
return hashString
}
网友评论