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
相关产品推荐
相关产品推荐

