跳到主要内容
ecdsa.com
golang-jwt/jwt (Go)Go

错误信息

token signature is invalid: key is of invalid type: ECDSA verify expects *ecdsa.PublicKey

也可能输出为

  • token signature is invalid: key is of invalid type: HMAC verify expects []byte
  • token signature is invalid: key is of invalid type: RSA verify expects *rsa.PublicKey
  • key is of invalid type: ECDSA sign expects *ecdsa.PrivateKey
  • key is of invalid type

v5 会给出所需的类型(“ECDSA verify expects *ecdsa.PublicKey”、“HMAC verify expects []byte”);v4 只打印“key is of invalid type”。由于 v5 把它归入 `ErrTokenSignatureInvalid`,乍一看像是签名验证失败。

golang-jwt/jwt (Go) — jwt.ErrInvalidKeyType

含义

你的 `Keyfunc` 返回的值(或者传给 `SignedString` 的密钥)的 Go 类型与令牌的算法不符。golang-jwt 会对密钥做类型断言:ES* 验证需要 `*ecdsa.PublicKey`,RS*/PS* 需要 `*rsa.PublicKey`,EdDSA 需要 `ed25519.PublicKey`,HS* 需要 `[]byte`;签名则需要对应的私钥。这里根本没有执行任何密码学运算——密钥还没有机会出错,它本身就是错误类型的对象。

原因

修复方法

  1. 1.

    将 PEM 一次性解析为具体类型的密钥

    golang-jwt 为每种密钥类型都提供了辅助函数。在启动时解析,然后从 Keyfunc 返回具体类型的密钥。

    go
    pub, err := jwt.ParseECPublicKeyFromPEM(pemBytes)      // ES256/384/512
    // rsaPub, err := jwt.ParseRSAPublicKeyFromPEM(pemBytes) // RS*/PS*
    // edPub, err := jwt.ParseEdPublicKeyFromPEM(pemBytes)   // EdDSA
    if err != nil {
    	log.Fatal(err)
    }
    token, err := jwt.Parse(raw, func(t *jwt.Token) (any, error) { return pub, nil },
    	jwt.WithValidMethods([]string{"ES256"}))
  2. 2.

    以 []byte 返回 HMAC 密钥

    把密钥转换为字节,并用 `WithValidMethods` 把算法限定为该 HMAC 算法,使 `alg` 为非对称算法的令牌无法进入这条代码路径。

    go
    secret := []byte(os.Getenv("JWT_HMAC_SECRET")) // []byte, not string
    token, err := jwt.Parse(raw, func(t *jwt.Token) (any, error) { return secret, nil },
    	jwt.WithValidMethods([]string{"HS256"}))

相关错误

浏览完整的签名错误库