MetaMask Signature Issue – Provided Address is Invalid or Capitalization Checksum Test Failed

metamasksignature

Provided address is invalid, the capitalization checksum test failed, or its an indrect IBAN address which can't be converted is not a dupe, this is about signing messages

My code:

const msgParams = [{
        type: 'string', name: 'Message', value: 'Hi, Alice!'  
     },{   type: 'uint32', name: 'A number', value: '1337'
      }];
      let from = Merchant.accounts[0];
      console.log(window.provider);
      let p = window.provider;
      console.log(Object.keys(window.web3));

      window.web3.eth.sign(from, msgParams, function(err, res) {
        console.log(err);
        console.log(res);
      });

(window.provider is the current provider.. window.web3 loses its current provider, see my other question window.web3.currentProvider is null for details)

Running this I get the error in the title

Metamask prompted to sign.. once. Now the prompt won't show. The signing prompt did have the Alice, 1337 data in it.

How do I sign a message with Metamask to get the encrypted string of that signed message?

EDIT: Merchant is my utility class for Metamask. The logged output of Merchant.accounts[0] is

0x2e290a50d3193753f156e5b0b12e4231bd568526

EDIT 2: I have tried this:

web3.eth.getAccounts(function(a,b) {
      Merchant.accounts = b;
      // alert("Saving accounts" + Merchant.accounts);
      console.log("Merchant accounts: " + Merchant.accounts);
      let x = web3.eth.getBalance;
      console.log(x);
    });



 toChecksumAddress (address) {
    address = address.toLowerCase().replace('0x', '')
    var hash = createKeccakHash('keccak256').update(address).digest('hex')
    var ret = '0x'

    for (var i = 0; i < address.length; i++) {
      if (parseInt(hash[i], 16) >= 8) {
        ret += address[i].toUpperCase()
      } else {
        ret += address[i]
      }
    }

    return ret
  }

reloadKeys() {
        const msgParams = [{
        type: 'string', name: 'Message', value: 'Hi, Alice!'  
     },{   type: 'uint32', name: 'A number', value: '1337'
      }];
      // Merchant.accounts[0]
      // let addr = 0x2E290A50d3193753F156e5b0b12e4231Bd568526;
      let from = this.toChecksumAddress(Merchant.accounts[0]);

      // window.web3.utils.toChecksumAddress();
      console.log(typeof(from));
      console.log(from);

      console.log(Object.keys(window.web3));

      window.web3.eth.sign(from, msgParams, function(err, res) {
        console.log(err);
        console.log(res);
      });

I still get this error.

Best Answer

I think there are two issues:

  1. In Web3.js 1.0.0, the order of the parameters is web3.eth.sign(dataToSign, accountToSignWith, callback), but you're passing the account to sign with first.
  2. I don't think there's a way to sign objects like that, though maybe you know something I don't?

Try this to start with:

web3.eth.sign(web3.utils.sha3("test"), '0x2E290A50d3193753F156e5b0b12e4231Bd568526', function (err, result) { console.log(err, result); });

Make sure that works and then move on from there to signing what you want.

EDIT

Per https://github.com/MetaMask/metamask-extension/issues/1530, personal_sign may be a better option:

var fromAddress = '0x2E290A50d3193753F156e5b0b12e4231Bd568526';
web3.currentProvider.sendAsync({
  method: 'personal_sign',
  params: [
    web3.utils.fromAscii('hello world'),
    fromAddress,
  ],
  from: fromAddress,
}, function (err, result) {
  console.log(err, result);
});

EDIT2

Better yet, eth_signTypedData:

web3.currentProvider.sendAsync({
  method: 'eth_signTypedData',
  params: [
    [
      { type: 'string', name: 'Message', value: 'Hi, Alice!' },
      { type: 'uint32', name: 'A number', value: 1337 }
    ],
    fromAddress,
  ],
  from: fromAddress,
}, function (err, result) {
  console.log(err, result);
});
Related Topic