Geth ecrecover 无效签名恢复id
Geth ecrecover invalid signature recovery id
我正在尝试使用 geth golang 库验证从客户端传入的签名。我从我的一个 cryptokitties 帐户中获取示例数据(签名/地址)(我可以在请求中看到它)。如果我将 blow 凭据粘贴到 https://etherscan.io/verifySig,它会得到验证,所以我知道参数是正确的。
我的代码:
import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
)
sig := 0x80f5bac5b6300ed64835d5e2f167a368c892ccc2d0e252bc84befbcb093f5a2d36294b95d86683cec778c8c796049933c04c71576c56c1d6e9a9fa10342beca31c
data := "Cryptokitties"
decoded = hexutil.MustDecode(sig) // j8aUTtPid0ZnNa/s4Ef5gisYYh1bCeLSmFrtJtDjNRRqxShUr+1A3BVgoAPwiZ+lKN0POB1JOdVhVHI9tcHmABs=
hash := crypto.Keccak256([]byte(data)) // "ljQQTm25oqIbD+LMl70aRUcTzXCeeDGfkRj9YJYsgKY="
pubKey, err := crypto.Ecrecover(hash, sig) // error: "invalid signature recovery id"
我确定我遗漏了一些简单的东西,但不确定去哪里找。
**更新
在查看了一些答案后我尝试了什么:
像这样更改消息:
fmt.Sprintf("\u0019Ethereum Signed Message:\n%d%s", len(data), data)
//"\u0019Ethereum Signed Message:\n13Cryptokitties"
在散列之前对消息进行十六进制编码:
data=hexutil.Encode(data)
结合上面两个,所以先加上'Ethereum Signed Message',然后十六进制编码。
如有任何意见,我将不胜感激,我确定这是一个菜鸟问题。
**更新
查看源码,发现其期望的recovery id大于4:
sig[64] >= 4
在我的例子中,结果是 27:
sig[64] --> 27
// EcRecover returns the address for the account that was used to create the signature.
// Note, this function is compatible with eth_sign and personal_sign. As such it recovers
// the address of:
// hash = keccak256("\x19Ethereum Signed Message:\n"${message length}${message})
// addr = ecrecover(hash, signature)
//
// Note, the signature must conform to the secp256k1 curve R, S and V values, where
// the V value must be be 27 or 28 for legacy reasons.
//
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) {
if len(sig) != 65 {
return common.Address{}, fmt.Errorf("signature must be 65 bytes long")
}
if sig[64] != 27 && sig[64] != 28 {
return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)")
}
sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1
rpk, err := crypto.Ecrecover(signHash(data), sig)
if err != nil {
return common.Address{}, err
}
pubKey := crypto.ToECDSAPub(rpk)
recoveredAddr := crypto.PubkeyToAddress(*pubKey)
return recoveredAddr, nil
}
这是我的要点:https://gist.github.com/dcb9/385631846097e1f59e3cba3b1d42f3ed#file-eth_sign_verify-go
我正在尝试使用 geth golang 库验证从客户端传入的签名。我从我的一个 cryptokitties 帐户中获取示例数据(签名/地址)(我可以在请求中看到它)。如果我将 blow 凭据粘贴到 https://etherscan.io/verifySig,它会得到验证,所以我知道参数是正确的。
我的代码:
import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
)
sig := 0x80f5bac5b6300ed64835d5e2f167a368c892ccc2d0e252bc84befbcb093f5a2d36294b95d86683cec778c8c796049933c04c71576c56c1d6e9a9fa10342beca31c
data := "Cryptokitties"
decoded = hexutil.MustDecode(sig) // j8aUTtPid0ZnNa/s4Ef5gisYYh1bCeLSmFrtJtDjNRRqxShUr+1A3BVgoAPwiZ+lKN0POB1JOdVhVHI9tcHmABs=
hash := crypto.Keccak256([]byte(data)) // "ljQQTm25oqIbD+LMl70aRUcTzXCeeDGfkRj9YJYsgKY="
pubKey, err := crypto.Ecrecover(hash, sig) // error: "invalid signature recovery id"
我确定我遗漏了一些简单的东西,但不确定去哪里找。
**更新
在查看了一些答案后我尝试了什么:
像这样更改消息:
fmt.Sprintf("\u0019Ethereum Signed Message:\n%d%s", len(data), data)
//"\u0019Ethereum Signed Message:\n13Cryptokitties"
在散列之前对消息进行十六进制编码:
data=hexutil.Encode(data)
结合上面两个,所以先加上'Ethereum Signed Message',然后十六进制编码。
如有任何意见,我将不胜感激,我确定这是一个菜鸟问题。
**更新
查看源码,发现其期望的recovery id大于4:
sig[64] >= 4
在我的例子中,结果是 27:
sig[64] --> 27
// EcRecover returns the address for the account that was used to create the signature.
// Note, this function is compatible with eth_sign and personal_sign. As such it recovers
// the address of:
// hash = keccak256("\x19Ethereum Signed Message:\n"${message length}${message})
// addr = ecrecover(hash, signature)
//
// Note, the signature must conform to the secp256k1 curve R, S and V values, where
// the V value must be be 27 or 28 for legacy reasons.
//
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) {
if len(sig) != 65 {
return common.Address{}, fmt.Errorf("signature must be 65 bytes long")
}
if sig[64] != 27 && sig[64] != 28 {
return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)")
}
sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1
rpk, err := crypto.Ecrecover(signHash(data), sig)
if err != nil {
return common.Address{}, err
}
pubKey := crypto.ToECDSAPub(rpk)
recoveredAddr := crypto.PubkeyToAddress(*pubKey)
return recoveredAddr, nil
}
这是我的要点:https://gist.github.com/dcb9/385631846097e1f59e3cba3b1d42f3ed#file-eth_sign_verify-go