golang: panic: crypto: requested hash function #2 is unavailable
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