首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实体中的验证go签名(EIP712 TypedData)

实体中的验证go签名(EIP712 TypedData)
EN

Ethereum用户
提问于 2022-07-14 14:22:23
回答 1查看 597关注 0票数 2

我正在尝试恢复TypedData消息(eip712)的签名者。

我能够签署和验证与ethersJS以及在合同中的有效性。

使用Go,我也可以签署和验证,但是验证在合同中失败了。

证明这段代码运行良好。

The TypedData;

代码语言:javascript
复制
signerData := TypedData{
        Types: Types{
            "Quote": []Type{
                {Name: "cost", Type: "uint256"},
                {Name: "deadline", Type: "uint256"},
            },
            "EIP712Domain": []Type{
                {Name: "name", Type: "string"},
                {Name: "chainId", Type: "uint256"},
                {Name: "version", Type: "string"},
                {Name: "verifyingContract", Type: "string"},
                {Name: "salt", Type: "string"},
            },
        },
        PrimaryType: "Quote",
        Domain: TypedDataDomain{
            Name:              "MyDomain",
            Version:           "1",
            ChainId:           ethMath.NewHexOrDecimal256(ChainId.Int64()),
            VerifyingContract: contractAddress.String(),
            Salt:              "0",
        },
        Message: TypedDataMessage{
            "cost":     "0",          
            "deadline": "1659095005", 
        },
    }

编码数据;

代码语言:javascript
复制
func EncodeForSigning(typedData TypedData) (hash common.Hash, err error) {
    domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())

    if err != nil {
        return
    }

    typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message)
    if err != nil {
        return
    }

    rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash)))
    hash = common.BytesToHash(crypto.Keccak256(rawData))
    return
}

符号TypedData;

代码语言:javascript
复制
func (s Signer) SignTypedData(typedData TypedData) (sig []byte, err error) {
    hash, err := EncodeForSigning(typedData)
    if err != nil {
        return
    }

    sig, err = crypto.Sign(hash.Bytes(), s.key)
    if err != nil {
        return
    }
    
    sig[64] += 27

    return
}

我能在Go中验证它;

代码语言:javascript
复制
func Ecrecover(hash, signature []byte) (addr common.Address, err error) {
    sig := make([]byte, len(signature))
    copy(sig, signature)
    if len(sig) != 65 {
        err = fmt.Errorf("invalid length of signture: %d", len(sig))
        return
    }

    if sig[64] != 27 && sig[64] != 28 && sig[64] != 1 && sig[64] != 0 {
        err = fmt.Errorf("invalid signature type")
        return
    }
    if sig[64] >= 27 {
        sig[64] -= 27
    }

    recoverPub, err := crypto.Ecrecover(hash, sig)
    if err != nil {
        err = fmt.Errorf("can not ecrecover: %v", err)
        return
    }
    pubKey, err := crypto.UnmarshalPubkey(recoverPub)
    if err != nil {
        err = fmt.Errorf("can not unmarshal pubkey: %v", err)
        return
    }

    addr = crypto.PubkeyToAddress(*pubKey)
    return
}

然而,在合同失败的情况下,我尝试了ECDSA和_hashTypedDataV4,他们都返回了相同的地址,但这是错误的。

代码语言:javascript
复制
function validateQuote(uint256 _cost,uint256 _deadline, bytes memory _signature) public view returns (address) {

        Quote memory quote = Quote({
            cost: _cost,
            deadline: _deadline
        });

        bytes32 msghash = _hashTypedDataV4(hash(quote));

        uint8 v;
        bytes32 r;
        bytes32 s;

         (v, r, s) = splitSignature(_signature);

        (address signer, ) = ECDSA.tryRecover(msghash,_signature);

        console.log("v4 signer", signer);
        console.log("v", v);

        return (verifyQuote(quote, v,r,s)); 
    }

签名的十六进制表示在go和实体中是相同的,但是实体返回的签名人无效。

V= 27

go验证返回正确的地址

代码语言:javascript
复制
//validate signature
hash, err = EncodeForSigning(signerData)
signerAddress, err := Ecrecover(hash.Bytes(), sig)

fmt.Println("Signer Recovery", signerAddress) // good

合同一方失败的原因是什么?

我能够用以太验证相同的签名,其中V=28相同的签名与go集的V为27。不确定这是相关的。

EN

回答 1

Ethereum用户

发布于 2022-10-25 08:51:32

代码语言:javascript
复制
ethers.utils.splitSignature(signature).compact

在用go.I生成签名之后,您可以用ether.js来尝试这一点,我不确定它是否有效,但您可以尝试它。

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

https://ethereum.stackexchange.com/questions/131756

复制
相关文章

相似问题

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