2

I am trying to create a C# webservice back end API that handles the code logic found in Step #5 here: https://www.toptal.com/ethereum/one-click-login-flows-a-metamask-tutorial

Their code looks like this:

User.findOne({ where: { publicAddress } })
  // --snip--
  .then(user => {
    const msg = `I am signing my one-time nonce: ${user.nonce}`;

    // We now are in possession of msg, publicAddress and signature. We
    // can perform an elliptic curve signature verification with ecrecover
    const msgBuffer = ethUtil.toBuffer(msg);
    const msgHash = ethUtil.hashPersonalMessage(msgBuffer);
    const signatureBuffer = ethUtil.toBuffer(signature);
    const signatureParams = ethUtil.fromRpcSig(signatureBuffer);
    const publicKey = ethUtil.ecrecover(
      msgHash,
      signatureParams.v,
      signatureParams.r,
      signatureParams.s
    );
    const addressBuffer = ethUtil.publicToAddress(publicKey);
    const address = ethUtil.bufferToHex(addressBuffer);

    // The signature verification is successful if the address found with
    // ecrecover matches the initial publicAddress
    if (address.toLowerCase() === publicAddress.toLowerCase()) {
      return user;
    } else {
      return res
        .status(401)
        .send({ error: 'Signature verification failed' });
    }
  })

My code looks like this, below. But it always returns false. My first guess is that the "message" format is incorrect somehow. I've seen other examples not include the "\x19" portion, but removing it and including it both returns false.

public static bool AccountSignerIsValid(string signature, string publicAddress)
{
    var nonce = "12345678";
    var terms = "Please sign to log in: " + nonce;
    var message = Encoding.UTF8.GetBytes("\x19Ethereum Signed Message:\n" + terms.Length + terms);
    var hash = (new Sha3Keccack()).CalculateHash(message.ToArray());

    var signer = new Nethereum.Signer.MessageSigner();
    var account = signer.EcRecover(hash, signature);

    return (account.ToLower().Equals(publicAddress.ToLower()));
}

What would I need to do to change the C# code to make it return true?

1
//  ("\x19Ethereum")  !=  ("\x19" + "Ethereum")
var message = Encoding.UTF8.GetBytes("\x19" + "Ethereum Signed Message:\n" + terms.Length + terms);
0

For others arriving here, theres a build in function that takes care of encoding, hashing, validating and building the string:

var recoveredAddress = signer.EncodeUTF8AndEcRecover(message, signature);

Just note that the recovered address comes out as mixed case (build in checksum), so do an IgnoreCase comparison or lowercase them both.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.