Hi, I’m trying to sign a message with an my address as the owner of a contract to send that signature in a method of my contract. Then have my contract to verify that the signature comes from my address. Sign it like you mean it: creating and verifying Ethereum signatures I have the signing part in my dapp
this line: const signerIdentity = EthCrypto.createIdentity();, generates a new private key, which then you use to sign the message (the address for it is stored at signerIdentity.address). That's probably why the call to checkSignature is failing (i'm assuming you are following the article and deployed with remix). You would have to deploy the contract with that same key or change the contract owner.
Try interacting with the contract below. It's single purpose is to verify EOAs (contract's don't have private keys, can't sign messages). It generates an hash for the address provided (messageHash), which is then signed and the signature passed to verifyEOA. verifiedEOA returns true or false depending on the account verification.
Can't provide much input on the JS side of things (i use python in my environment + web3js on the frontend).
You will need to generate a new key with const signerIdentity = EthCrypto.createIdentity();, then call the contract method messageHash with signerIdentity.address as argument, and sign the hash returned, probably with const signature = EthCrypto.sign(signerIdentity.privateKey, hashRetrivedFromTheContract);.
pragma solidity ^0.8.0;
interface IEOAVerify {
event EOAVerification(address indexed account);
function verifiedEOA(address account) external view returns (bool);
function messageHash(address acc) external pure returns (bytes32);
function verifyEOA(address signer, bytes memory signature) external;
}
contract EOAVerify is IEOAVerify {
mapping(address => bool) public override verifiedEOA;
function messageHash(address acc) public pure override returns (bytes32) {
return keccak256(abi.encodePacked("EOAVerification:", acc));
}
function verifyEOA(address signer, bytes memory signature) public override {
bytes32 h = messageHash(signer);
bytes32 ethSignedMessageHash = signedMessageHash(h);
address s = signer == address(0) ? msg.sender : signer;
require(recoverSigner(ethSignedMessageHash, signature) == s, 'EOAVerify: Signed mismatch');
verifiedEOA[s] = true;
emit EOAVerification(s);
}
function signedMessageHash(bytes32 _messageHash) internal pure returns (bytes32) {
// "\x19Ethereum Signed Message\n" + len(msg) + msg
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash));
}
function recoverSigner(bytes32 signedHash, bytes memory _signature)
internal pure
returns (address)
{
(bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);
return ecrecover(signedHash, 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, 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)))
}
}
}
So this is what I got so far but I kept getting different address of the signer and they are all incorrect (signer should accounts[0] address). Could you please help? @helio.rosa Thank you
as i mentioned my test environment is python, don't really use Truffle that much but can spot some mistakes in your code:
const signerIdentity = EthCrypto.createIdentity(); creates a new key. signerIdentity.address = accounts[0]; has no effect, addresses are derived from the public key, which is derived from the private key isValidData only accepts one argument
if you need to sign with the key for the address at accounts[0], maybe you could try using web3.eth.sign() to sign instead:
toEthSignedMessageHash specifically creates the hash as used by the eth_sign and personal_sign RPC calls. It prefixes the signed data with "\x19Ethereum Signed Message:\n" + len(message), whereas EthCrypto.sign is signing the data as is. (See the docs.)
You should either use Web3.js or Ethers.js to generate the signature, or you should use a library like eth-sig-util that implement this signing algorithm with the prefix.