Private-Key

如何驗證已簽名的消息以及它沒有被重用/篡改?

  • August 27, 2021

我已經看過這個問題和其他問題,但沒有人回答我的問題。

如何簽署消息並確保我恢復的公鑰實際上屬於簽署消息的私鑰?

下面的程式碼受到了這個github 執行緒的啟發。

// function in the front-end.
async signMessage(){
   const message = `Hello World`;
   const messageHash = await ethers.utils.hashMessage(message)
   const signedMessage = await this.signer.signMessage(ethers.utils.arrayify(messageHash));
   //...........
   //Send messageHash and signedMessage to the server backend
}

後端程式碼:

// function in the back-end.
async verifyMessage(messageHash, signedMessage){
   const pubkey = ethers.utils.recoverPublicKey(
       ethers.utils.arrayify(
           ethers.utils.hashMessage(ethers.utils.arrayify(messageHash))
       ),
       signedMessage
   )
   const address = ethers.utils.computeAddress(pubkey) 
}

上面程式碼的第一個問題是某人(例如惡意方)可以一次又一次地使用簽名(不辭職),而後端將無法知道這一點。

第二個問題,您可以送出與已簽名的消息不同的消息,並且後端將無法知道。事實上,一個有效的乙太坊地址仍然會被恢復。

如何解決?

1st簽署消息。該消息必須具有簽名者地址。我們將解析此消息並獲取簽名者地址,並將其與我們從解碼簽名消息中獲得的地址進行比較。如果它們匹配,則消息是真實的並且沒有被篡改。

第二。在消息中,我們還需要包含一個我們將保存在數據庫中的隨機數,使用它來確保消息不會被重用。

前端程式碼:

// Front end code
async signMessageAnsSendToServer() {
   const nonce = new Date().getTime()
   const message = `
       Message:

           Wallet address:
               ${this.connectedAddress}

           Nonce:
               ${nonce}
`
   this.web3 = new ethers.providers.Web3Provider(this.provider)// create web3 instance
   this.signer = this.web3.getSigner();
   const signedMessage = await this.signer.signMessage(message);
   // send signed message to server

}

後端程式碼:

// Backend code
async function getSignerAddressAndNonce(message, signedMessage){
   const signerAddress = ethers.utils.verifyMessage(message, signedMessage);

   const addressFromMessage = message.replace(/\n|\r/g, "").split("Wallet address:").pop().split("Nonce:")[0].trim();

   const nonce = message.split("Nonce:").pop().trim();
 
   if(signerAddressA !== signerAddressB){
       // this means that the message was not signed
   }

   return {address: signerAddressA, nonce: Number(nonce)}
}

引用自:https://ethereum.stackexchange.com/questions/107100