Cannot verify signature in php

I can verify signature when using metamask(standlone) .
The issue is that signature(from moralis user authData) cannot be verified if we use authenticate() method;

const user = await authenticate({ signingMessage: "Messagge" });

if ( user ) {
    // verifySignature is mapped to PHP endpoint for verification
    await verifySignature(
        user.attributes.authData.moralisEth.data,
        user.attributes.ethAddress,
        user.attributes.authData.moralisEth.signature
    );
}

PHP Side

     try {
                $messageLength = strlen($message);
                $hash = Keccak::hash("\x19Ethereum Signed Message:\n{$messageLength}{$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;
                }

                $publicKey = (new EC('secp256k1'))->recoverPubKey($hash, $sign, $recId);

                $derivedAddress = self::pubKeyToAddress($publicKey);
                //echo "\n public key : ";print_r( $publicKey);
                echo "\n param address : ". strtolower($address);
                echo "\n derived address : ". $derivedAddress;

                return strtolower($derivedAddress) === strtolower($address);
       }  catch (Exception $e) {
              print_r($e->getMessage() );
      }
const {web3} = useMoralis();
let signer = web3.getSigner();
let signature = await signer.signMessage('Some data')

signature from this code snippet can be verified by PHP API.

it should work without issues, same code to make the signature is used in the sdk

@cryptokid

onst {web3} = useMoralis();
let signer = web3.getSigner();
let signature = await signer.signMessage('message\n\nId: 242422424:335434')

This code is not working when I changed

await signer.signMessage('Some data')

to

await signer.signMessage('message\n\nId: 242422424:335434')

then it has to be something with the php part, that is only a string that is passed as parameter, maybe it interprets the characters in some way in php, like that \n

1 Like

@cryptokid I got it. Do let me try on PHP side.

@cryptokid Without touching PHP side,

The signature I generated on this site(https://codesandbox.io/s/react-eth-metamask-signatures-forked-dnn8dg?file=/src/VerifyMessage.js:241-318)

can be verified by PHP even though signing message is message\n\nId: 242422424:335434.

what is the difference then? shouldn’t be the same signature in both cases if the message is the same?

The difference is that

const {web3} = useMoralis();
let signer = web3.getSigner();
let signature = await signer.signMessage('message\n\nId: 242422424:335434')

The signature generated from above snippet cannot be verified.
And
The signature generated from “https://codesandbox.io/s/react-eth-metamask-signatures-forked-dnn8dg?file=/src/VerifyMessage.js:241-318”;
can be verified.

I have no idea why the first one is not working.

maybe it a difference how those \n\n characters are interpreted, maybe sometimes are interpreted as 2 characters, sometimes as 4 characters

1 Like

@cryptokid Thanks for your help.It is caused by our PHP script. Managed to solve by improving PHP code.

1 Like