trustwallet / trust-wallet-ios

:iphone: Trust - Ethereum Wallet and Web3 DApp Browser for iOS
https://trustwallet.com
GNU General Public License v3.0
1.52k stars 718 forks source link

eth_sign sometimes produces invalid signature. #947

Open leroldary opened 5 years ago

leroldary commented 5 years ago

Using eth_sign and then verifying the signature (recovering the address) the recovered address in sometimes wrong.

E.g. Signing the data 0x68bfc34d28afcb7ae03691816548965dffba6c427c79d15fe6ef548384395fb0 with the address 0xe3aAd2d4f9545D3cE53Bb5cd9Ca929a9f7995837 the result of TrustWallet is 0xa20bdcf11c4c689edba3af62c531240c09d365233cc7e8934ad9c8ea7085b37a1f781f59e558e8dc8f46cf56964f373deaf70b61bd2b896b87a49c8b293cc3311b

Now if we recover the address we get 0x4d8d9d89b133024249651d9161F52a8c0D9d4e7e

yoheinishikubo commented 5 years ago

I got wrong signed hashes every time with the function web3.personal.sign.

With the following minimum PoC code, the generated result is wrong. Of course, this code works perfectly with other environments like MetaMask and the Android version of Trust.

<html>
  <head>
    <script>
    const sign = ()=>{
        const message = 'Hello world!';
        const signer = web3.eth.accounts[0];
        web3.personal.sign(message, signer, (err, signature) => {
            if (!err){
                document.querySelector(".signer").innerText = signer;
                document.querySelector(".message").innerText = message;
                document.querySelector(".signature").innerText = signature;
            }
            });
    }

    </script>
  </head>
  <body onload="sign()">
    <div>Signer: <span class="signer"></span></div>
    <div>Message: <span class="message"></span></div>
    <div>Signature: <span class="signature"></span></div>
  </body>
</html>

The code above can be tested on the following URL.

https://gist.githack.com/yoheinishikubo/65e51a60fad63fefcc2af7e8d7fe5508/raw/d1dc153c76a6cbce676e339c3df0a00d3eb24955/index.html

It makes me confused that the service like OpenSea using this API works fine with Trust. Is there another way to make a message personal-signed?

yoheinishikubo commented 5 years ago

I found that the first parameter of web3.personal.sign is needed to be converted to hex manually with the method like web3.fromUtf8 or web3.utils.utf8ToHex. I can get the correct result with iOS version of Trust.

The original code working with MetaMask and Android version of Trust mislead me.