I'm trying to validate signed data with ecrecover. The message is signed like this on the FE:

return this.web3.eth.personal.sign( `${nonce}`, publicAddress ).then( ( signature ) => {
            return signature;
        } )

After the signature is seemingly well generate it is sent to the BE along with the public address for verification.

const user = await User.findOne( { publicAddress: req.body.publicAddress } );
const msg = `${user.nonce}`;

const msgBuffer = ethUtil.toBuffer( msg );
const msgHash = ethUtil.hashPersonalMessage( msgBuffer );
const signatureBuffer = ethUtil.toBuffer( req.body.signature );
const signatureParams = ethUtil.fromRpcSig( signatureBuffer );
const publicKey = ethUtil.ecrecover(
const addressBuffer = ethUtil.publicToAddress( publicKey );
const address = ethUtil.bufferToHex( addressBuffer );

if ( address.toLowerCase() === req.body.publicAddress.toLowerCase() ) {
    res.status( 200 ).send( { message: 'Signature ok' } );
} else {
    res.status(401).send( { error: 'Signature verification failed' } );

However I always get back a completely different public address then the original. I read somewhere that I might need to append a prefix along with the message length, but that didn't help either.


  • Or at least can anyone tell me why the web3.eth.personal.sign method requires password parameter while it didn't before? – Jhonny Mar 1 '19 at 13:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.