how to verify the signature of a message in phantom solana?

6.1k views Asked by At

I am trying to authenticate phantom wallet by signing it with a message I used below code to sign the message and it returns me a signature how can I verify that signature in the backend.

    const encodedMessage = new TextEncoder().encode("Message to sign");
    const signedMessage = await window.solana.request({
      method: "signMessage",
      params: {
        message: encodedMessage,
        display: "utf8", //hex,utf8
      },
    });

Here signed Message responds with this answer with publickey and a signature

{
    "publicKey": "Gy4xSKsLHXScRMVZgKt5f6BvDawp1JW8PrenA3GbakCK",
    "signature": "5BoNFSoV9WEafBnXon2ujPzH5zgjwZkXHL9vkHuUHEnc1AqLSN38LEx5XtAz68JFEt9RhvuhmPL3GkMPdMcQPuzN"
}
2

There are 2 answers

0
Jon C On

If you want to verify a signature, you'll also need the signed data, and use the underlying verifier as:

nacl.sign.detached.verify(signData, signature, publicKey.toBuffer())

In general, you may want to directly verify a signed transaction rather than asking a user to sign another message by using the verifySignatures method on Transaction: https://github.com/solana-labs/solana/blob/d4e7ebf4f8821dfa59a1f278898cf9a7ad70ebd9/web3.js/src/transaction.ts#L673

1
Sceat On
  • generate a unique message on the backend and save it in your database
  • request it from the frontend
  • sign a message through the provider
  • send that result to the backend
  • retrieve the message from the database
  • verify it against the received signature

Frontend

import bs58 from 'bs58'

const message_from_backend = 'hello world'
const { signature, publicKey } = window
  .solana
  .signMessage(
    new TextEncoder().encode(message_from_backend),
    'utf8'
  )

fetch('/backend', {
  method: 'POST',
  body: JSON.stringify({
    public_key: publicKey.toBase58(),
    signature: bs58.encode(signature)
  })
})

Backend

import nacl from 'tweetnacl'
import bs58 from 'bs58'

const message = 'hello world'
const { public_key, signature } = received_from_frontend
const verified = nacl
  .sign
  .detached
  .verify(
    new TextEncoder().encode(message),
    bs58.decode(signature),
    bs58.decode(public_key)
  )