[英]How do I recover ECDSA public key correctly from hashed message and signature in R || S || V format?
I have used the following code to generate an ecdsa key-pair( privKey
and pubKey
), encode them and then decode them back: https://stackoverflow.com/a/41315404/1901320 . 我使用以下代码生成ecdsa密钥对(
privKey
和pubKey
),对它们进行编码然后将其解码回来: https : pubKey
。
Next I create a hash for a message ( txnData.Payload()
is of type []byte
) using crypto.Keccak256()
and sign it using crypto.Sign()
from Ethereum's crypto package ( github.com/ethereum/go-ethereum/crypto
). 接下来,我创建哈希用于消息(
txnData.Payload()
的类型为[]byte
)使用crypto.Keccak256()
并使用签名crypto.Sign()
从复仇的加密封装( github.com/ethereum/go-ethereum/crypto
)。 This creates a 65 bit ECDSA signature in R || 这在R ||中创建了65位ECDSA签名 S ||
S || V format.
V格式。
hashData := crypto.Keccak256(txnData.Payload)
sig, _ := crypto.Sign(hashData, privKey)
pkey, _ := crypto.Ecrecover(hashData, sig) // This and pubKey do not match
When I try to get back the public key from the hashData
and the ECDSA signature using crypto.Ecrecover()
and compare it with the public key pubKey
corresponding to the privKey
used to create the signature, I find that the public keys do not match. 当我尝试使用
crypto.Ecrecover()
从hashData
和ECDSA签名中crypto.Ecrecover()
并将其与用于创建签名的privKey
对应的公钥pubKey
进行比较时,我发现公钥不匹配。 This doesn't seem like something that should happen. 这似乎不应该发生。 Any idea as to where I am going wrong with this?
知道我在哪里出错吗?
Here's a complete working example of how to generate and verify signatures using go-ethereum. 这是一个完整的工作示例,说明如何使用go-ethereum生成和验证签名。
package main
import (
"bytes"
"crypto/ecdsa"
"fmt"
"log"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
)
func main() {
privateKey, err := crypto.HexToECDSA("fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19")
if err != nil {
log.Fatal(err)
}
publicKey := privateKey.PublicKey
publicKeyBytes := crypto.FromECDSAPub(&publicKey)
data := []byte("hello")
hash := crypto.Keccak256Hash(data)
fmt.Println(hash.Hex()) // 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8
signature, err := crypto.Sign(hash.Bytes(), privateKey)
if err != nil {
log.Fatal(err)
}
fmt.Println(hexutil.Encode(signature)) // 0x789a80053e4927d0a898db8e065e948f5cf086e32f9ccaa54c1908e22ac430c62621578113ddbb62d509bf6049b8fb544ab06d36f916685a2eb8e57ffadde02301
sigPublicKey, err := crypto.Ecrecover(hash.Bytes(), signature)
if err != nil {
log.Fatal(err)
}
matches := bytes.Equal(sigPublicKey, publicKeyBytes)
fmt.Println(matches) // true
sigPublicKeyECDSA, err := crypto.SigToPub(hash.Bytes(), signature)
if err != nil {
log.Fatal(err)
}
sigPublicKeyBytes := crypto.FromECDSAPub(sigPublicKeyECDSA)
matches = bytes.Equal(sigPublicKeyBytes, publicKeyBytes)
fmt.Println(matches) // true
signatureNoRecoverID := signature[:len(signature)-1] // remove recovery id
verified := crypto.VerifySignature(publicKeyBytes, hash.Bytes(), signatureNoRecoverID)
fmt.Println(verified) // true
}
Check out the Ethereum Development with Go guide book for more examples on using go-ethereum. 有关使用go-ethereum的更多示例,请查看以太坊开发与Go指南。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.