Private-Key
如何驗證已簽名的消息以及它沒有被重用/篡改?
我已經看過這個問題和其他問題,但沒有人回答我的問題。
如何簽署消息並確保我恢復的公鑰實際上屬於簽署消息的私鑰?
下面的程式碼受到了這個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)} }