使用提供的公钥验证ECDSA签名

时间:2018-01-24 13:01:58

标签: go

我试图在go中为一些类似自定义jwt的逻辑编写验证程序。我不确定如何使用ecdsa验证方法。 rs代表什么以及如何从提供的签名中填充这些内容?到目前为止,我有以下内容,但我不确定它是否接近。

sig := "MEUCIQDLUXOWIw8xuJ1pALV8qeao0ZCBFjBnGLzY_RP-2Y5hdwIgQgB4skfOppPTsuDicJ1O25S50MokqtlQKrXSrnoDEVE"

hasher := crypto.Hash.New(crypto.SHA512)
hasher.Write([]byte(j))

r := new(big.Int).SetBytes(signature[:len(signature)/2])
s := new(big.Int).SetBytes(signature[len(signature)/2:])

verify := ecdsa.Verify(publicKey, hasher.Sum(nil), r, s)

2 个答案:

答案 0 :(得分:1)

如果您查看ecdsa.PrivateKey.Sign()的源,您将在结尾处找到它:

return asn1.Marshal(ecdsaSignature{r, s})

因此,您应该asn1.Unmarshal获得原始号码。不幸的是,ecdsa软件包既没有这种方法,也没有导出ecdsaSignature结构。因此,您应该复制粘贴它。在Go中,您可以使用未命名的结构:

var esig struct {
    R, S *big.Int
}
if _, err := asn1.Unmarshal(sig, &esig); err != nil {
    return err
}
verify := ecdsa.Verify(publicKey, hasher.Sum(nil), esig.R, esig.S)

我在这里找到了这个解决方案: https://swenotes.wordpress.com/2018/04/16/trying-to-learn-ecdsa-and-golang/

答案 1 :(得分:0)

rs只是代表签名的两个数字。毕竟,非对称加密只是一个很大的数字。您可以找到验证算法here的说明。

这两个数字如何被序列化和编码是真正重要的。如果签名刚刚连接Sign输出rs的原始字节,那么您的提案就是正确的。

但是,您显示的字符串看起来像是在url-safe base64中编码的。您需要首先对其进行解码,然后将其拆分(或者拆分,然后解码)。在不知道签名者如何选择代表签名的情况下,我们无法分辨。

处理jwt(或一般的加密)意味着确切知道所有内容是如何编码/表示的。您应该使用具有ecdsa签名验证的jwt-go之类的内容,而不是自己推出。如果你想自己动手,他们的ecdsa verification应该是一个很好的起点。