Open moda20 opened 2 years ago
I am trying to verify the signature of a hashed message, and the method used in the description doesn't return the right address :
function verifySignature($message, $signature, $address) { $msglen = strlen($message); $hash = Keccak::hash("\x19Ethereum Signed Message:\n{$msglen}{$message}", 256); $sign = ["r" => substr($signature, 2, 64), "s" => substr($signature, 66, 64)]; $recid = ord(hex2bin(substr($signature, 130, 2))) - 27; if ($recid != ($recid & 1)) return false; $ec = new EC('secp256k1'); $pubkey = $ec->recoverPubKey($hash, $sign, $recid); return $address == $this->pubKeyToAddress($pubkey); } $address = "0xd927a97442c8bce9f18e84de11cac6e54a890ff8"; $message = "0xa880c297e04a9a4e1b8856dd4b48c1f6c0b0b82b1da2907b3d16f6ab1357c8b9"; // signature returned by eth.sign(address, message) $signature = "0xcd33577b169a3f2a5c835b3ca7dab1d41fa32db4b791c6856319756e7fecc3cb13676706408b019b6dcc3fe28a72f8435390bb0a1572ba241cfd09ae917784511c"; if ($this->verifySignature($message, $signature, $address)) { Log::error("SUCCSS"); } else { Log::error("FAIL"); }
the address returned by verifySignature (that we try to compare to the original address) is
0xad21644cb255d77dbf4b1ab716cca9797ce3e5bb
which is different than the original address.The problem here is that when not signing the hashed message but the original message it works correctly.
the original message is : "It'sMe MArio". (without the quotes) and the hashing is done by sha3 :
web3.utils.sha3(message)
Quick fix is in js code and not in php end if finally got it working here is my script:
//Load account from metamask
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
console.log(accounts[0]);
//prepare message to sign
const msgtext = "Hello World";
const hashedMessage = Web3.utils.fromUtf8(msgtext);
console.log(hashedMessage);
//get user to sign the message
const signature = await window.web3.eth.sign(hashedMessage, accounts[0]);
Explaination: Thing is you have to take a string data and covert it to hex which returns a bytes32 hexcode and then ask user to sign it.
Explaination: Thing is you have to take a string data and covert it to hex which returns a bytes32 hexcode and then ask user to sign it.
I'm getting the same issue as soon as the provider is not MetaMask (e.g. WalletConnect)
With
let publicAddress = address;
let paToLower = publicAddress.toLowerCase();
const signature = await web3ModalProv.eth.sign(web3ModalProv.utils.fromUtf8(message), paToLower);
or without
let message = response.data;
let publicAddress = address;
handleSignMessage(message, publicAddress).then(handleAuthenticate);
function handleSignMessage(rawMessage, publicAddress) {
let message = web3ModalProv.utils.utf8ToHex(rawMessage);
return new Promise((resolve, reject) =>
web3ModalProv.eth.personal.sign(
message,
publicAddress,
(err, signature) => {
if (err || typeof signature === 'undefined') {
userLoginData.state = "loggedOut";
showMsg(userLoginData.state);
}
return resolve({ publicAddress, signature });
}
)
)
}
In all cases the PHP code returns false if it is not a MetaMask address at if ($recid != ($recid & 1))
If I use the same code with MetaMask, it works.
I'm using a fork of this https://github.com/giekaton/php-metamask-user-login to establish a login with WalletConnect
I managed to fix the issue which was actually on the back-end (verifySignature).
Include php-ecrecover in your project
This needs the following version of CryptoCurrencyPHP (I did not tested the HEAD one)
Simply replace function verifySignature()
by:
function verifySignature($message, $signature, $address)
{
return $address == personal_ecRecover($message, $signature);
}
The personal_ecRecover
function is based on gmp and looks more efficient than the current public key recovery method which seems to have been developed only for MetaMask.
You might need to allow gmp extension in php.ini if not done
I am trying to verify the signature of a hashed message, and the method used in the description doesn't return the right address :
the address returned by verifySignature (that we try to compare to the original address) is
0xad21644cb255d77dbf4b1ab716cca9797ce3e5bb
which is different than the original address.The problem here is that when not signing the hashed message but the original message it works correctly.
the original message is : "It'sMe MArio". (without the quotes) and the hashing is done by sha3 :
web3.utils.sha3(message)