php 计算eth_signTypedData的消息哈希

vbopmzt1  于 2023-05-21  发布在  PHP
关注(0)|答案(2)|浏览(165)

我试图用Metamask和一个小玩具例子来理解eth_signTypedMessage。
浏览器中的代码(使用Metamask和Chrome):

ethereum.request({ method: 'eth_signTypedData', params: [
  [
    {
      type: 'string',
      name: 'testname',
      value: '1234567890'
    }
  ],
  publicAddress
] }).then((signedData) => {
    SendSignedDataToBackend(signedData);
});

我试图弄清楚如何计算类型化数据的消息散列,但我不能用the standard直接计算:
后端php代码(使用旧的php ECRecover):

$typeHash     = Keccak::hash('(string testname)',256); // Also no success without the brackets
$encodeData   = keccak::hash("1234567890",256);
$typedMsgHash = keccak::hash(hex2bin($typeHash.$encodeData),256);

$ecRecover    = new EcRecover();
$address      = $ecRecover->personalEcRecover($typedMsgHash,$signedData);

这会导致错误的公共地址。有什么建议吗?

4bbkushb

4bbkushb1#

在浏览了Metamask的代码之后,似乎Metamask签署了普通消息:

sign(message)

和我想的不一样

sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))

这似乎并不遵循EIP-712,但也许我误解了它。在服务器上删除“\x19Ethereum...”的额外哈希计算解决了这个问题。$typeHash计算是没有括号的代码中的问题。我还需要在我的代码中添加一个额外的“0x”:

$typedMsgHash = '0x'.keccak::hash(hex2bin($typeHash.$encodeData),256);
uqdfh47h

uqdfh47h2#

也许还不算太晚,两年后登陆这里,仍然没有解决方案,我不得不写一个包来解决这个问题。sleepfinance/eip712
根据EIP-712指定的JSON模式格式化数据。例如:

use SleepFinance\Eip712;
use kornrunner\Secp256k1;


$mailTypedData = [
    "types" => [
        "EIP712Domain" => [
            [
                "name" => "name",
                "type" => "string"
            ],
            [
                "name" => "version",
                "type" => "string"
            ],
            [
                "name" => "chainId",
                "type" => "uint256"
            ],
            [
                "name" => "verifyingContract",
                "type" => "address"
            ]
        ],
        "Person" => [
            [
                "name" => "name",
                "type" => "string"
            ],
            [
                "name" => "wallet",
                "type" => "address"
            ]
        ],
        "Mail" => [
            [
                "name" => "from",
                "type" => "Person"
            ],
            [
                "name" => "to",
                "type" => "Person"
            ],
            [
                "name" => "contents",
                "type" => "string"
            ]
        ]
    ],
    "primaryType" => "Mail",
    "domain" => [
        "name" => "Ether Mail",
        "version" => "1",
        "chainId" => 1,
        "verifyingContract" => "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
    ],
    "message" => [
        "from" => [
            "name" => "Cow",
            "wallet" => "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"
        ],
        "to" => [
            "name" => "Bob",
            "wallet" => "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
        ],
        "contents" => "Hello, Bob!"
    ]
];
$eip712 = new Eip712($mailTypedData);

$hashToSign = $eip712->hashTypedDataV4();

//signing with account 0xf3022686aa43B98362c989659561b9B348977897
$pvk="0x2870b52bfe2401ac0eed7f62fd4bd03eb579c61369c6b4dd6931fb4a57d71b09";

$secp256k1 = new Secp256k1();

$signed   = $secp256k1->sign($hashToSign, $pvk);

//Hex
$signatureToSubmit = $signed->toHex();

相关问题