如何在Node.js后端通过Aptos Typescript SDK验证签名
在Node.js后端验证Petra钱包的Aptos签名
我正在使用Petra钱包与Aptos Typescript SDK开发dApp,已在前端完成签名操作,但不清楚如何在Node.js后端验证签名。我尝试在官方文档及Github上查找方法,但未能找到。
环境信息:
前端依赖:
"@aptos-labs/ts-sdk": "^1.2.0", "@aptos-labs/wallet-adapter-react": "^2.1.2"
后端依赖:
"@aptos-labs/ts-sdk": "^1.2.0"
解决方案
步骤1:前端传递签名核心数据到后端
前端完成签名后,需要将原始待签名消息、钱包返回的签名值、用户Aptos地址(可选:直接传公钥以节省后端查询开销)这三类数据传给后端。
前端签名示例:
import { useWallet } from "@aptos-labs/wallet-adapter-react"; const { signMessage, account } = useWallet(); // 定义待签名消息(建议用结构化文本/JSON字符串,确保唯一性) const rawMessage = `确认登录我的dApp,时间戳:${Date.now()}`; const messageBytes = new TextEncoder().encode(rawMessage); // 调用Petra钱包签名 const signResult = await signMessage({ message: messageBytes, nonce: crypto.randomUUID(), // 加入随机串防止重放攻击 address: account.address, }); // 向后端发送验证请求 await fetch("/api/verify-aptos-signature", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ rawMessage, signature: signResult.signature, userAddress: account.address, userPublicKey: account.publicKey // 可选:直接传公钥,避免后端查节点 }), });
步骤2:Node.js后端验证签名
使用@aptos-labs/ts-sdk提供的Ed25519PublicKey和verifySignature工具完成验证,核心逻辑是用用户公钥校验签名与原始消息的匹配性。
后端验证示例:
import { Ed25519PublicKey, verifySignature, Hex, Aptos } from "@aptos-labs/ts-sdk"; // 初始化Aptos客户端(用于查询账户公钥,如果前端没传的话) const aptosClient = new Aptos({ network: "testnet" }); // 按需切换主网/测试网 export async function POST(request: Request) { const { rawMessage, signature, userAddress, userPublicKey } = await request.json(); try { // 获取用户公钥:优先用前端传递的,否则从Aptos节点查询 const publicKeyHex = userPublicKey || (await aptosClient.getAccountInfo({ accountAddress: userAddress })).public_key; if (!publicKeyHex) throw new Error("无法获取用户公钥"); // 转换公钥为SDK可处理的实例 const publicKey = new Ed25519PublicKey(Hex.fromHexString(publicKeyHex)); // 重新编码原始消息为字节数组(必须和前端编码方式一致) const messageBytes = new TextEncoder().encode(rawMessage); // 执行签名验证 const isValid = verifySignature({ publicKey, message: messageBytes, signature: Hex.fromHexString(signature), }); return Response.json({ success: isValid, message: isValid ? "签名验证通过" : "签名不匹配" }, { status: isValid ? 200 : 403 }); } catch (error) { console.error("签名验证失败:", error); return Response.json({ success: false, message: "验证过程出错" }, { status: 500 }); } }
关键注意事项
- 消息一致性:前后端必须使用完全相同的原始消息编码,比如前端用
TextEncoder,后端也得用一样的方式,否则验证必失败。 - 重放攻击防护:签名时加入随机nonce或时间戳,后端需记录已使用的nonce,避免同一签名被重复利用。
- 性能优化:让前端直接传递公钥,省去后端查询Aptos节点的耗时。
内容的提问来源于stack exchange,提问作者Liki Crus
相关产品推荐
相关产品推荐

