rustmetamask

How to verify the signature made by metamask for ethereum?


I want to sign a simple message on the frontend with metamask and verify it on the backend in order to sign user in.

So on the frontend I do:

const accounts = await web3.eth.getAccounts();
let sign = await web3.eth.personal.sign(`some message here`, accounts[0], '');

What is the best way to verify the signature on the backend written in Rust? And what crates are the best for such task? I would be really grateful for any real code since Im a total newbie in Rust.

Thank you 🙏


Solution

  • this works for me:

        use web3::signing::{keccak256, recover};
    
        pub fn eth_message(message: String) -> [u8; 32] {
            keccak256(
                format!(
                    "{}{}{}",
                    "\x19Ethereum Signed Message:\n",
                    message.len(),
                    message
                )
                .as_bytes(),
            )
        }
    
        #[test]
        fn test_recover() {
            let account = "0x63f9a92d8d61b48a9fff8d58080425a3012d05c8".to_string();
            let message = "0x63f9a92d8d61b48a9fff8d58080425a3012d05c8igwyk4r1o7o".to_string();
            let message = eth_message(message);
            let signature = hex::decode("382a3e04daf88f322730f6a2972475fc5646ea8c4a7f3b5e83a90b10ba08a7364cd2f55348f2b6d210fbed7fc485abf19ecb2f3967e410d6349dd7dd1d4487751b").unwrap();
            println!("{} {:?} {:?}", account, message, signature);
            let recovery_id = signature[64] as i32 - 27;
            let pubkey = recover(&message, &signature[..64], recovery_id);
            assert!(pubkey.is_ok());
            let pubkey = pubkey.unwrap();
            let pubkey = format!("{:02X?}", pubkey);
            assert_eq!(account, pubkey)
        }
    

    It's very important to salt the original message with

    format!("{}{}{}","\x19Ethereum Signed Message:\n",message.len(),message) and hash it.