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

Go语言自定义类JWT逻辑的ECDSA签名验证实现疑问

关于Go中ECDSA签名验证的r、s参数及签名解析问题

首先来解答你的核心疑问:

什么是r和s?

在ECDSA算法中,签名结果本质上是由两个大整数r和s组成的对。这两个值是签名过程中通过私钥和随机数计算得出的,验证时必须同时提供这两个值、公钥以及消息的哈希结果,才能完成签名合法性的校验。

如何从签名中正确提取r和s?

你当前的代码直接将签名字节对半拆分来获取r和s是错误的!因为JWT中的ECDSA签名通常采用ASN.1 DER编码格式存储,不是简单的r和s字节直接拼接。正确的步骤应该是:

  1. 先对Base64编码的签名字符串进行解码(你的sig是Base64格式);
  2. 使用ASN.1解析工具将解码后的字节流解析为包含r和s的结构体。

修正后的代码示例

下面是调整后的正确实现,我会逐行解释:

import (
    "crypto/ecdsa"
    "crypto/sha512"
    "encoding/asn1"
    "encoding/base64"
    "math/big"
)

// 假设j是你要验证的原始消息内容
j := "your-jwt-payload-or-message"
sig := "MEUCIQDLUXOWIw8xuJ1pALV8qeao0ZCBFjBnGLzY_RP-2Y5hdwIgQgB4skfOppPTsuDicJ1O25S50MokqtlQKrXSrnoDEVE"

// 第一步:解码Base64格式的签名
sigBytes, err := base64.RawURLEncoding.DecodeString(sig)
// 注意:JWT的签名通常用RawURLEncoding(不带填充),如果解码失败可以试试StdEncoding
if err != nil {
    // 处理解码错误
    panic(err)
}

// 定义一个结构体来匹配ASN.1 DER编码的签名格式
type ecdsaSignature struct {
    R, S *big.Int
}

// 第二步:解析ASN.1 DER字节流得到r和s
var sigStruct ecdsaSignature
if err := asn1.Unmarshal(sigBytes, &sigStruct); err != nil {
    // 处理解析错误
    panic(err)
}

// 第三步:计算消息的SHA-512哈希
hasher := sha512.New()
hasher.Write([]byte(j))
msgHash := hasher.Sum(nil)

// 第四步:执行ECDSA验证
verify := ecdsa.Verify(publicKey, msgHash, sigStruct.R, sigStruct.S)

为什么你的原始代码不对?

ASN.1 DER编码的签名会包含额外的标签、长度字段,不是r和s的字节简单拼接。比如一个典型的DER签名结构是:

0x30 [总长度] 0x02 [r的长度] [r的字节] 0x02 [s的长度] [s的字节]

直接对半拆分字节会破坏这种结构,导致解析出的r、s值完全错误,验证自然会失败。

内容的提问来源于stack exchange,提问作者matthew.clarke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:19:27