无法验证由 sol-wallet-adapter 签名的消息

Posted

技术标签:

【中文标题】无法验证由 sol-wallet-adapter 签名的消息【英文标题】:Unable to verify message signed by sol-wallet-adapter 【发布时间】:2021-09-18 11:47:39 【问题描述】:

拥有created a signed message 我不确定如何使用生成的签名来使用公钥验证消息。

我的用例是,我想使用 Solana 钱包登录 API 服务器,其模式如下:

    GET message: String (from API server) sign message with privateKey POST signature (to API server) verify signature with stored publicKey

我尝试使用 nodeJS crypto.verify 来解码 API 端的签名消息,但我对缓冲区和椭圆曲线的深入研究有点超出了我的深度:

// Front-end code
const toHexString = (buffer: Buffer) =>
  buffer.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");

const data = new TextEncoder().encode('message to verify');
const signed = await wallet.sign(data, "hex");
await setLogin( // sends API post call to backend
  variables: 
    publicAddress: walletPublicKey,
    signature: toHexString(signed.signature),
  ,
);

// Current WIP for backend code
const ALGORITHM = "ed25519";
const fromHexString = (hexString) =>
  new Uint8Array(hexString.match(/.1,2/g).map((byte) => parseInt(byte, 16)));
const signature = fromHexString(args.signature);
const nonceUint8 = new TextEncoder().encode('message to verify');
const verified = crypto.verify(
  ALGORITHM,
  nonceUint8,
  `-----BEGIN PUBLIC KEY-----\n$user.publicAddress\n-----END PUBLIC KEY-----`,
  signature
);
console.log("isVerified: ", verified);

我很确定我的做法是错误的,我肯定缺少一个明显的方法。

随着空间的成熟,我预计验证函数或库会消耗const signed = await wallet.sign(data, "hex"); 的输出

类似:

import  VerifyMessage  from '@solana/web3.js';

const verified = VerifyMessage(message, publicKey, signature, 'hex');

但经过 3 天的努力,我开始达到自己的极限,我的大脑正在衰竭。任何帮助或方向在哪里看起来非常感谢????

【问题讨论】:

您是否尝试使用 Solana 的 web3 API 代替? 另外,您是否尝试使用签名示例provided here 进行验证? const data = new TextEncoder().encode('message to verify'); const signed = await wallet.sign(data, "hex"); ... signature: toHexString(signed.signature), 您在这里使用的是十六进制,但血清示例显示 UTF8 还有验证方法有问题。 const verified = crypto.verify( ALGORITHM, nonceUint8, `-----BEGIN PUBLIC KEY-----\n$user.publicAddress\n-----END PUBLIC KEY-----`, signature ); 公共地址和公共密钥不一样。假设 user.publicAddress 是正确的,它的格式是否正确,例如base64? 查看 ETH web3 文档可能是描述此处尝试实现的目标的最佳方式。 sign 函数的等价物就是我在这里看到的 web3js.readthedocs.io/en/v1.2.9/…。区别在于签名和恢复消息不会引发链上交易。你可以在这里web3js.readthedocs.io/en/v1.2.11/…看到对应的ecRecover函数。您还会注意到这些函数与signTransactionsendTransaction 不同。 【参考方案1】:

我建议留在 solana-labs trail 并使用 tweetnacl

spl-token-wallet (sollet.io) 使用 nacl.sign.detached(message, this.account.secretKey)

https://github.com/project-serum/spl-token-wallet/blob/9c9f1d48a589218ffe0f54b7d2f3fb29d84f7b78/src/utils/walletProvider/localStorage.js#L65-L67

在另一端,验证完成 nacl.sign.detached.verify

在@solana/web3.js https://github.com/solana-labs/solana/blob/master/web3.js/src/transaction.ts#L560

在您的后端使用nacl.sign.detached.verify,您应该会很好。我还建议避免任何数据格式操作,我不确定您要做什么,但如果您确实验证每个步骤是否正确。

【讨论】:

【参考方案2】:

通过出色的 Project Serum discord 开发人员的意见解决。高级解决方案是使用在 sol-wallet-adapter repo 中也使用的库,即 tweetnaclbs58

const signatureUint8 = base58.decode(args.signature);
const nonceUint8 = new TextEncoder().encode(user?.nonce);
const pubKeyUint8 = base58.decode(user?.publicAddress);

nacl.sign.detached.verify(nonceUint8, signatureUint8, pubKeyUint8)
// true

【讨论】:

太棒了!确保在此处接受正确答案,以便其他人知道 =)

以上是关于无法验证由 sol-wallet-adapter 签名的消息的主要内容,如果未能解决你的问题,请参考以下文章

分块上传验证:“无法上传文件。”

四位由数字和字母组成的验证码的代码

iOS由开发者验证应用商店购买ID

Yii2,自定义验证:clientValidateAttribute() 无法正常工作

Zend Guard Loader 无法验证应用程序许可证

在 windbg 中,啥会导致消息“警告:无法验证 mydll.dll 的时间戳”?