前言
以太坊的簽名與驗簽可以用來metamask錢包登錄,多簽錢包等應(yīng)用屉凯。但沒有全面的文檔進行相關(guān)的解釋,這里筆者整理了相關(guān)的方法
簽名
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'
// 亦可以用私鑰來構(gòu)建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)
}
// 6事汀!扒披!_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