Web3js

簽署 Metamask 消息並使用 ethereumjs-utils 7.0.10 進行驗證

  • March 14, 2022

我試圖在後端使用 ethereumjs-util 確認簽名的 Metamask 消息,但沒有成功。

Metamask 出現在使用者面前,他們可以對消息進行簽名 - 但是在後端驗證消息時,我收到錯誤消息。

Number can only safely store up to 53 bits
at assert (project\node_modules\ethereumjs-util\node_modules\bn.js\lib\bn.js:6:21)
   at BN.toNumber (project\node_modules\ethereumjs-util\node_modules\bn.js\lib\bn.js:547:7)
   at Object.exports.bufferToInt (project\node_modules\ethereumjs-util\dist\bytes.js:148:55)
   at Object.exports.fromRpcSig (project\node_modules\ethereumjs-util\dist\signature.js:76:21)
   at project\Routes\dashboard.js:21:32 ## will mark this in backend

簽名是一個 132 字元的十六進制,以 0x 開頭

後端程式碼- 帶有 Express 的節點

var ethUtil = require('ethereumjs-util');

var sig = req.query.sig;
console.log(sig + " length: " + sig.length);

var message = 'data';
const messageBuffer = Buffer.from(message);
const messageHash = ethUtil.hashPersonalMessage(messageBuffer);
const signatureBuffer = Buffer.from(sig);
const sigDecoded = ethUtil.fromRpcSig(signatureBuffer); ### this line is where it throws the Number can only safely store up to 53 bits error

// Recover Address
var recoveredPub = ethUtil.ecrecover(messageHash, sigDecoded.v, sigDecoded.r, sigDecoded.s)
var recoveredAddress = ethUtil.pubToAddress(recoveredPub).toString("hex")

後端包.json

"ethereumjs-util": "^7.0.10",
"web3": "^1.3.6"

前端程式碼

import('eth-sig-util');
import('axios');
import(web3);
     
window.ethereum.sendAsync({ id: 1, method: 'personal_sign', params: [ web3.utils.fromUtf8("data"), window.ethereum.selectedAddress] },
   function(err, result) {
       console.log(result);
       let sig = result.result;
       axios.get("http://myhost:8000/authenticate/" , { params: { sig }});
   }
)

前端包.json

"axios": "^0.21.1",
"vue": "^3.0.0",
"web3": "^1.3.6"

我已經按照我可以在網上找到的所有範例進行操作,包括使用 Metamask 簽署消息並使用 ethereumjs-utils 進行驗證,但是在工作時間之後,我一無所獲。

最終排序

前端應該是這樣的:

var message = 'data';
const messageBuffer = Buffer.from(message);
const messageHash = ethUtil.hashPersonalMessage(messageBuffer);
const sigDecoded = ethUtil.fromRpcSig(sig);

我最近在節點 js 中管理了這個(實際上是在一個 n8n 自定義函式中)

const { verifyMessage } = require('@ethersproject/wallet') // https://docs.ethers.io/v5/single-page/#/v5/api/utils/signing-key/-%23-utils-verifyMessage

const recoveredAddress = verifyMessage(signedMessage, signature).toLowerCase()
const isSignerMatching = !!(recoveredAddress === expectedAddress.toLowerCase())

實際上找出如何正確導入它是最複雜的!

因為 ethers.utils 沒有承諾的功能!

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