我试图在go中为一些类似自定义jwt的逻辑编写验证程序。我不确定如何使用ecdsa验证方法。 r
和s
代表什么以及如何从提供的签名中填充这些内容?到目前为止,我有以下内容,但我不确定它是否接近。
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)
答案 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)
r
和s
只是代表签名的两个数字。毕竟,非对称加密只是一个很大的数字。您可以找到验证算法here的说明。
这两个数字如何被序列化和编码是真正重要的。如果签名刚刚连接Sign
输出r
和s
的原始字节,那么您的提案就是正确的。
但是,您显示的字符串看起来像是在url-safe base64中编码的。您需要首先对其进行解码,然后将其拆分(或者拆分,然后解码)。在不知道签名者如何选择代表签名的情况下,我们无法分辨。
处理jwt(或一般的加密)意味着确切知道所有内容是如何编码/表示的。您应该使用具有ecdsa签名验证的jwt-go之类的内容,而不是自己推出。如果你想自己动手,他们的ecdsa verification应该是一个很好的起点。