Skip to content

Instantly share code, notes, and snippets.

@SilviaMargaritaOcegueda
Created August 14, 2022 03:33
Show Gist options
  • Save SilviaMargaritaOcegueda/0a9386089e4910c2a822539acffd5d20 to your computer and use it in GitHub Desktop.
Save SilviaMargaritaOcegueda/0a9386089e4910c2a822539acffd5d20 to your computer and use it in GitHub Desktop.
Solidity code to sign and verify a message
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
/*How to Sign and Verify a message
0. Create message to sign
1. Get message hash by calling getMessageHash()
2. Eth sign the message hash by calling getEthSignedMessageHash()
3. On the browser, unlock MetaMask account typing ethereum.enable()
4. Using browser, sign the message hash: | offchain to keep your private key secret
account = "copy paste account of signer here"
hash = "copy paste returned value from getMessageHash()"
ethereum.request({ method: "personal_sign", params: [account, hash]}).then(console.log)
#alternative> using web3:
web3.personal.sign(hash, web3.eth.defaultAccount, console.log)
Signature will be different for different accounts
5. Recover the signer copy pasting the Eth-signed and the browser-signature
6. To verify() pass the signer address, the original string message, and the signature from the browser*/
contract VerifySignature {
function verify( address _signer, string memory _message, bytes memory signature) external pure returns (bool) {
bytes32 messageHash = getMessageHash(_message);
bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);
return recoverSigner(ethSignedMessageHash, signature) == _signer;
}
function getMessageHash(string memory _message) public pure returns (bytes32) {
return keccak256(abi.encodePacked(_message));
}
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 recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature)
public pure returns (address)
{
(bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);
return ecrecover(_ethSignedMessageHash, v, r, s);
}
function splitSignature(bytes memory sig) internal 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)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment