You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go使用ES256算法签名JWT后解析报密钥类型无效错误如何解决

根因说明

ES256属于非对称签名算法,签名阶段使用ECDSA私钥生成签名,但验证阶段必须使用对应的ECDSA公钥。你在KeyFunc中直接返回私钥*ecdsa.PrivateKey类型不符合验证逻辑的类型要求,所以抛出类型错误。
另外你在KeyFunc内部打印t.Valid的时机不对,此时验证流程还未执行完成,该字段必然为false,需要等jwt.Parse执行完成后再读取该字段才有效。

修复方案

场景1:同进程持有私钥,直接复用私钥衍生公钥

直接从已解析的私钥中取出公钥返回即可,修正后的验证代码如下:

/// Parse token 修正后代码
token, err := jwt.Parse(tA.AccessToken, func(t *jwt.Token) (interface{}, error) {
    // 校验签名方法,避免算法切换攻击,属于最佳实践
    if _, ok := t.Method.(*jwt.SigningMethodECDSA); !ok {
        return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])
    }
    // 返回私钥对应的公钥即可
    return &privKey.PublicKey, nil
})
if err != nil {
    log.Fatal(err)
}
// 验证完成后再读取Valid字段
log.Println("token valid: ", token.Valid)

场景2:跨服务验证,使用已导出的公钥PEM验证

如果你是在其他服务做验证,没有私钥只有公钥PEM,可以用以下代码解析公钥:

// 填入你导出的公钥PEM内容
pubPEM := []byte(`-----BEGIN PUBLIC KEY-----
你的公钥PEM内容
-----END PUBLIC KEY-----`)
block, _ := pem.Decode(pubPEM)
pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
    log.Fatal(err)
}
// 类型断言确认是ECDSA公钥
ecdsaPubKey, ok := pubKey.(*ecdsa.PublicKey)
if !ok {
    log.Fatal("invalid public key type, expect ecdsa public key")
}

// 验证时直接返回ecdsaPubKey即可
token, err := jwt.Parse(tA.AccessToken, func(t *jwt.Token) (interface{}, error) {
    if _, ok := t.Method.(*jwt.SigningMethodECDSA); !ok {
        return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])
    }
    return ecdsaPubKey, nil
})

内容的提问来源于stack exchange,提问作者Epikoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 23:06:01