golang: panic: crypto: requested hash function #2 is unavailable

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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值