3

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.

4 Answers4

3

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);
});
user19510
  • 27,999
  • 2
  • 30
  • 48
  • Hey, I'm able to sign a message when I switch the 2nd param to be one of my addresses! So I will mark this as correct for now. However, if I change the first parameter to a regular string eg. "test", when I click sign Metamask stays stuck spinning (odd). My intention behind this process is to sign a message proving that the message signer is the address they claim they are –  Jan 19 '18 at 02:33
  • I believe the data to be signed has to be 32 bytes. When I try with a shorter string and inspect the MetaMask popup, I see an error logged to the console: "message length is invalid". See https://github.com/MetaMask/metamask-extension/issues/1530. – user19510 Jan 19 '18 at 02:36
  • Thanks, I don't get an error just a pinwheel in metamask –  Jan 19 '18 at 02:38
  • If you right click on the MetaMask popup and click "inspect" and then view the console, you should see an error there that, when expanded, has the message I mentioned. – user19510 Jan 19 '18 at 02:41
  • Also, please see my edit. Based on that GitHub issue, you may prefer to use personal_sign. The UI is much better. – user19510 Jan 19 '18 at 02:44
  • Right clicking won't work -- no menu on Metamask. On Mac, maybe that's why. (I just checked the regular console from developer tools) –  Jan 19 '18 at 02:44
  • Strange. I'm also on a Mac. In any case, I think we know the issue. – user19510 Jan 19 '18 at 02:45
  • 1
    And see my second edit for using signTypedData, which seems to be what you were after. – user19510 Jan 19 '18 at 02:49
  • Cool, so I can signTypedData to verify a message, then recover with sigUtil.recoverTypedSignature({ data: msgParams, sig: result.result }) –  Jan 19 '18 at 02:52
1

Signing requires a checksummed address which can be generated using the web3 function toChecksumAddress. So your code needs to be adjusted as follows:

let from = web3.toChecksumAddress(Merchant.accounts[0]);

The checksum is calculated by capitalising certain hexadecimal letters according to the algorithm designed by Vitalk in EIP-55

o0ragman0o
  • 4,320
  • 18
  • 35
  • Hello. web3.toChecksumADdress is not defined. `web3.eth.iban.checksum

    var i = new web3.eth.iban("XE81ETHXREGGAVOFYORK");` is from the documentation ... I don't see a clear way to use it

    –  Jan 18 '18 at 20:01
  • You might be using a beta version of web3 1.0.0. If so, web3.utils.toChecksumAddress instead. – user19510 Jan 18 '18 at 21:22
  • Hi @smarx , I am using beta and I tried web3.utils.toChecksumAddress. I get the same error. –  Jan 19 '18 at 01:14
  • @smarx looks like there is a way to sign objects. https://medium.com/metamask/the-new-secure-way-to-sign-data-in-your-browser-6af9dd2a1527 , https://github.com/danfinlay/js-eth-personal-sign-examples << seems to work on the signing part, need to test verification –  Jan 19 '18 at 02:36
0

had a similar problem, try copying the address directly from bscscan and passing it as a string e.g '0xE60000' no need for conversion again.

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center. – Community Dec 13 '21 at 22:05
0

The Remix transaction result address, that I copy to use as contract, in fact, are not valid anymore to web3 as contract hash (I don't know why). I went to etherscan.io and see all transactions from my address, click on the last "contract creation" that give me a different address than remix output.

I used that address and that error ends.


1 - Remix output hash from contract: 0x866e8ea2987873e4a0b985a5f408181c2b476cc9cf74f41dbb1e5e2231633821
2 - Etherscan transaction detail
3 - Contract address: 0x525d67ef6a08ad80c0956ca04af7eb2cd02a8bf0