美文网首页
以太坊签名与验签

以太坊签名与验签

作者: ozil_oo | 来源:发表于2022-07-04 14:18 被阅读0次

前言

以太坊的签名与验签可以用来metamask钱包登录,多签钱包等应用。但没有全面的文档进行相关的解释,这里笔者整理了相关的方法

签名

metamask的ethereum签名

const msg = '0x553d52098a30d90afbae2f14f7872b8ede6c2eb7020661813b9f75df14cb8da7'
const account = await signer.getAddress()
const signedMessage = await ethereum.request({ method: "personal_sign", params: [account, msg] })

ethers签名

const msg = '0x553d52098a30d90afbae2f14f7872b8ede6c2eb7020661813b9f75df14cb8da7'
//  亦可以用私钥来构建signer
const provider = new ethers.providers.Web3Provider(window.ethereum)
const signer = provider.getSigner()
//  这里一定要把msg通过arrayify方法,功能类似于下文中solidity中的getEthSignedMessageHash方法
const signedMessage = await signer.signMessage(ethers.utils.arrayify(msg))

验签

solidity验签

function getEthSignedMessageHash(bytes32 _messageHash)
        public
        pure
        returns (bytes32)
    {
        /*
        Signature is produced by signing a keccak256 hash with the following format:
        "\x19Ethereum Signed Message\n" + len(msg) + msg
        */
        return
            keccak256(
                abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash)
            );
    }

function splitSignature(bytes memory sig)
        public
        pure
        returns (
            bytes32 r,
            bytes32 s,
            uint8 v
        )
    {
        require(sig.length == 65, "invalid signature length");

        assembly {
            /*
            First 32 bytes stores the length of the signature

            add(sig, 32) = pointer of sig + 32
            effectively, skips first 32 bytes of signature

            mload(p) loads next 32 bytes starting at the memory address p into memory
            */

            // first 32 bytes, after the length prefix
            r := mload(add(sig, 32))
            // second 32 bytes
            s := mload(add(sig, 64))
            // final byte (first byte of the next 32 bytes)
            v := byte(0, mload(add(sig, 96)))
        }

        // implicitly return (r, s, v)
    }

//  !!!_ethSignedMessageHash需要把msg传入getEthSignedMessageHash再次hash
function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature)
        public
        pure
        returns (address)
    {
        (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);

        return ecrecover(_ethSignedMessageHash, v, r, s);
    }

ethers验签

//  理论上可以签名和验签都不加ethers.utils.arrayify(),但是为了和solidity验签签名保持一致,最好如此
const signerAddr = await ethers.utils.verifyMessage(ethers.utils.arrayify(msg), signedMessage)

参考

solidity-by-example
Sign Message with Ethers.js and Verify with Solidity Contract

相关文章

网友评论

      本文标题:以太坊签名与验签

      本文链接:https://www.haomeiwen.com/subject/pwudbrtx.html