首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >恢复无效签名恢复id

恢复无效签名恢复id
EN

Stack Overflow用户
提问于 2018-03-03 15:23:52
回答 1查看 3.7K关注 0票数 7

我正在使用geth golang库来验证客户端传递的签名。我从我的一个加密帐户(我可以在请求中看到它)获取示例数据(签名/地址)。如果我将are凭证粘贴到https://etherscan.io/verifySig中,就会得到验证,因此我知道参数是正确的。

我的代码:

代码语言:javascript
复制
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签名消息”前加上,然后对其进行编码。

任何一点都会被感激的,我相信这是个问题。

**最新情况

通过查看源代码,我发现它的预期恢复id大于4:sig[64] >= 4

在我的例子中,结果是27:sig[64] --> 27

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-13 06:19:54

请参阅:https://github.com/ethereum/go-ethereum/blob/55599ee95d4151a2502465e0afc7c47bd1acba77/internal/ethapi/api.go#L452-L459

代码语言:javascript
复制
// 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
}

这是我的要点:verify-go

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49085737

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档