如何验证sol-wallet-adapter生成的签名实现Solana钱包登录?
Solana钱包签名验证解决方案
核心错误原因
你调用Node原生crypto.verify失败的核心原因是:Solana钱包返回的公地址是base58编码的ed25519原始公钥字节,不是PEM格式的公钥,你直接套PEM头传入crypto.verify完全不匹配,自然验证失败。
最简实现方案
直接使用Solana生态通用的依赖组合实现,就是你预期的开箱即用逻辑:
第一步:安装依赖
npm install @solana/web3.js tweetnacl
第二步:后端验证代码
import { PublicKey } from '@solana/web3.js'; import nacl from 'tweetnacl'; // 16进制转Uint8Array工具函数,你之前的实现可直接复用 const fromHexString = (hexString) => new Uint8Array(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))); // 封装好的验证方法,参数完全匹配你的预期 const verifySolanaSignature = (message, publicAddress, hexSignature) => { // 将base58编码的公地址转成原始公钥字节 const publicKey = new PublicKey(publicAddress); // 解码16进制签名 const signature = fromHexString(hexSignature); // 待验证消息转Uint8Array const messageUint8 = new TextEncoder().encode(message); // 直接调用ed25519签名验证 return nacl.sign.detached.verify(messageUint8, signature, publicKey.toBytes()); } // 调用示例 const verified = verifySolanaSignature('message to verify', user.publicAddress, args.signature); console.log("isVerified: ", verified);
可选优化点
如果前端不想自行转换16进制,也可以直接将签名转成base58字符串传输,后端仅需把解码函数换成bs58.decode()即可,验证逻辑完全一致。
注意事项
- 前后端待验证的消息必须完全一致,不能有任何字符、编码、空格、换行的差异
- sol-wallet-adapter的
sign方法默认返回的就是符合验证要求的原始签名字节,不需要额外处理
内容的提问来源于stack exchange,提问作者harkl
相关产品推荐
相关产品推荐

