Skip to content

Instantly share code, notes, and snippets.

@swkim109
Last active December 5, 2022 09:26
Show Gist options
  • Save swkim109/75bc431ddced2bc7b9c44e02ee526873 to your computer and use it in GitHub Desktop.
Save swkim109/75bc431ddced2bc7b9c44e02ee526873 to your computer and use it in GitHub Desktop.
Sign message
const Web3 = require('web3');
const HDWalletProvider = require("@truffle/hdwallet-provider");
const fs = require('fs');
const key = fs.readFileSync("private.key").toString().trim();
const privateKeys = [key];
//const mnemonic = "crash ... twice";
// 지갑을 쓰는 것과 동일
const provider = new HDWalletProvider({
//mnemonic: mnemonic,
privateKeys,
providerOrUrl: "http://127.0.0.1:8545",
addressIndex: 0
});
const web3 = new Web3(provider);
//const message = "Terms of service";
const message = "Hello, World!";
const messageHash = web3.utils.soliditySha3("\x19Ethereum Signed Message:\n" + message.length + message);
//const messageHash = web3.utils.sha3("\x19Ethereum Signed Message:\n" + message.length + message); // soliditySha3 와의 차이점?
console.log(messageHash);
// 마지막 바이트가 1b(27) 또는 1c(28)이 된다. 그러나 트랜잭션의 경우는 EIP-155 이후부터 25(37) 또는 26(38),
// 최근에는 원래 값 0(r이 짝수) 또는 1(r이 홀수)
// 아래 세가지 서명은 당연히 모두 동일하다.
// 메시지를 해쉬하지 않고 그냥 전달한다.
const sig = web3.eth.accounts.sign(message, key);
//console.log(sig);
console.log(sig.signature);
web3.eth.personal.sign(message, "0xAFc4F9F3bA806dd2F8e47A524fFDa2418bBFc08a").then(sig => console.log(sig));
web3.eth.sign(message, "0xAFc4F9F3bA806dd2F8e47A524fFDa2418bBFc08a").then(sig => console.log(sig));
// 서명 데이터는 r,s,v를 문자열로 이은 것이므로 다시 분리할 수 있다.
// const signature = sig.signature.substring(2);
// const r = "0x" + signature.substring(0, 64);
// const s = "0x" + signature.substring(64, 128);
// const v = parseInt(signature.substring(128, 130), 16);
// console.log(r,s,v);
web3.eth.personal.ecRecover(message, sig.signature).then(account => console.log(account));
const account = web3.eth.accounts.recover(message, sig.signature, false);
console.log(account);
provider.engine.stop();
@swkim109
Copy link
Author

swkim109 commented Jan 29, 2022

web3.js에서는 prefix를 자동으로 추가하여 서명 데이터를 만듭니다. 그래서 특별히 메시지를 파라미터로 전달할 때도 원본 메시지를 그대로 전달합니다(해시 하지 않고).

하지만 솔리디티의 ecrecover를 사용할 때 메시지를 전달할 때는 prefix가 있는 메시지를 해시해서 전달해야 합니다.

//SPDX-License-Identifier:MIT
pragma solidity ^0.8.0;

import "./ECDSA.sol";

contract MyContract {

    using ECDSA for bytes32;

    function verifyMessage(bytes32 messageHash, bytes memory signature) public pure returns (address) {
        return messageHash.recover(signature);
    }

}

@swkim109
Copy link
Author

swkim109 commented Jul 23, 2022

const privateKey = "...";
const provider = new ethers.providers.JsonRpcProvider("...");

const message = "Hello, Ethereum";
const messageHash = ethers.utils.hashMessage(message);
console.log(messageHash);
const wallet = new ethers.Wallet(privateKey, provider);

wallet.signMessage(message).then(signature => {
    
    const r = signature.slice(0, 66)
    const s = '0x' + signature.slice(66, 130)
    const v = '0x' + signature.slice(130, 132)    
    
    console.log(r,s,v);
    
}); 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment