Code:
package main
import (
"crypto"
"fmt"
"io"
)
func main() {
h := crypto.MD5.New()
io.WriteString(h, "test1280")
fmt.Printf("%x\n", h.Sum(nil))
}
运行报错:
C:\Users\EB\Desktop\test1280>go run main.go
panic: crypto: requested hash function #2 is unavailable
goroutine 1 [running]:
crypto.Hash.New(0x2, 0xc0000441e0, 0xc000089f20)
D:/app2/go1.13.6/src/crypto/crypto.go:89 +0x109
main.main()
C:/Users/EB/Desktop/test1280/main.go:10 +0x35
exit status 2
解决:
import "crypto/md5"
最后代码:
package main
import (
"crypto"
_ "crypto/md5"
"fmt"
"io"
)
func main() {
h := crypto.MD5.New()
io.WriteString(h, "test1280")
fmt.Printf("%x\n", h.Sum(nil))
}
仔细看下 crypto.go 源码就能知道原因:https://golang.org/src/crypto/crypto.go。
在调用 crypto.MD5.New 时,调用:
// New returns a new hash.Hash calculating the given hash function. New panics
// if the hash function is not linked into the binary.
func (h Hash) New() hash.Hash {
if h > 0 && h < maxHash {
f := hashes[h]
if f != nil {
return f()
}
}
panic("crypto: requested hash function #" + strconv.Itoa(int(h)) + " is unavailable")
}
这里 Hash 其实是一个 int 类型,MD5即 int 中的 2。
调用 New 时,会从 hashes 表中查找 MD5 的工厂函数,并调用工厂函数创建 MD5 句柄对象(return f())。
但是明显,在查 MD5 工厂函数时没查到(if f != nil,实际上 f == nil),因此panic。
再看看什么时候注册的 MD5 工厂函数?
// RegisterHash registers a function that returns a new instance of the given
// hash function. This is intended to be called from the init function in
// packages that implement hash functions.
func RegisterHash(h Hash, f func() hash.Hash) {
if h >= maxHash {
panic("crypto: RegisterHash of unknown hash function")
}
hashes[h] = f
}
This is intended to be called from the init function in packages that implement hash functions.
在 Linux 下可以用 grep 查一下哪里调用了此函数:
[test1280@localhost crypto]$ pwd
/home/test1280/go/src/crypto
[test1280@localhost crypto]$ grep "RegisterHash" ./* -nr
./crypto.go:97:// RegisterHash registers a function that returns a new instance of the given
./crypto.go:100:func RegisterHash(h Hash, f func() hash.Hash) {
./crypto.go:102: panic("crypto: RegisterHash of unknown hash function")
./md5/md5.go:21: crypto.RegisterHash(crypto.MD5, New)
./sha1/sha1.go:19: crypto.RegisterHash(crypto.SHA1, New)
./sha256/sha256.go:17: crypto.RegisterHash(crypto.SHA224, New224)
./sha256/sha256.go:18: crypto.RegisterHash(crypto.SHA256, New)
./sha512/sha512.go:21: crypto.RegisterHash(crypto.SHA384, New384)
./sha512/sha512.go:22: crypto.RegisterHash(crypto.SHA512, New)
./sha512/sha512.go:23: crypto.RegisterHash(crypto.SHA512_224, New512_224)
./sha512/sha512.go:24: crypto.RegisterHash(crypto.SHA512_256, New512_256)
都是各个不同算法包,在其init函数中注册自己的工厂函数到crypto包中的。
因此,只需要让 crypto/md5 包加载,执行其 init 函数即可:
通过 import _ “crypto/md5” 即可实现。
参考:
1.https://stackoverflow.com/questions/17986762/openpgp-in-go-error-crypto-requested-hash-function-is-unavailable
2.https://github.com/Kong/go-srp/issues/1
3.https://stackoverflow.com/questions/17986762/openpgp-in-go-error-crypto-requested-hash-function-is-unavailable
4.https://www.cnblogs.com/yxdz-hit/p/8666464.html