You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React向Node.js传递以太坊签名遇BigInt序列化问题求解

解决BigInt序列化与签名验证的问题

问题根源

你遇到的两个错误本质都是JSON不原生支持BigInt类型:

  • 直接发送signMessage对象时,JSON.stringify无法处理r、s的BigInt值,抛出序列化错误
  • 把整个signMessage转成字符串(比如String(signMessage))会得到"[object Object]",服务端用BigInt()转换这个字符串自然报错

正确处理方案

1. 客户端:结构化序列化签名数据

不要把整个对象转成字符串,而是保留JSON结构,仅将BigInt字段转为字符串后再序列化:

// 客户端代码(假设用ethers.js生成签名)
const signMessage = await signer.signMessage(transactionMessage);

// 转换BigInt字段为字符串,保留对象结构
const serializableSignature = {
  r: signMessage.r.toString(),
  s: signMessage.s.toString(),
  recovery: signMessage.recovery // recovery是普通数字,直接保留
};

// 发送POST请求
await fetch('/send', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(serializableSignature)
});

如果不想手动逐个字段处理,也可以用JSON.stringify的replacer函数自动处理所有BigInt:

const serializedSignature = JSON.stringify(signMessage, (key, value) => {
  return typeof value === 'bigint' ? value.toString() : value;
});

2. 服务端:还原BigInt并验证签名

接收JSON数据后,将对应的字符串字段转回BigInt,再进行验证:

// 服务端Express示例代码
const ethers = require('ethers');
const express = require('express');
const app = express();
app.use(express.json()); // 解析JSON请求体

app.post('/send', async (req, res) => {
  const { r, s, recovery } = req.body;
  
  try {
    // 把字符串转回BigInt
    const signature = {
      r: BigInt(r),
      s: BigInt(s),
      recovery: Number(recovery)
    };

    // 执行签名验证(替换为你的验证逻辑)
    const verifiedAddress = await ethers.verifyMessage(yourOriginalMessage, signature);
    
    res.status(200).json({ success: true, verifiedAddress });
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
});

关键注意事项

  • 始终保留JSON的结构化传输,不要直接把对象转成非结构化字符串
  • 验证时要确保服务端使用的原始消息和客户端签名的消息完全一致,否则验证会失败

内容的提问来源于stack exchange,提问作者Matias Salimbene

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:19:52