> ## Documentation Index
> Fetch the complete documentation index at: https://docs.phantom.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Verify a signature

> Verify Solana message signatures on your backend to confirm wallet ownership after signing.

After a user signs a message using the Phantom Connect SDK, verify the signature on your backend to prove they own the wallet.

## Get a signature (frontend)

First, have the user sign a message using the SDK:

<Tabs>
  <Tab title="React">
    ```tsx theme={null}
    import { useSolana } from "@phantom/react-sdk";

    function SignForVerification() {
      const { solana } = useSolana();

      const signAndVerify = async () => {
        const message = "Hello, please sign this message";
        
        // Sign the message using the SDK
        const { signature } = await solana.signMessage(message);

        // Send to your backend for verification
        const response = await fetch("/api/verify", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            address: await solana.getPublicKey(),
            message,
            signature,
          }),
        });

        const { verified } = await response.json();
        console.log("Signature verified:", verified);
      };

      return <button onClick={signAndVerify}>Sign and Verify</button>;
    }
    ```
  </Tab>

  <Tab title="Browser SDK">
    ```typescript theme={null}
    import { BrowserSDK, AddressType } from "@phantom/browser-sdk";

    const sdk = new BrowserSDK({
      providers: ["google", "apple", "injected"],
      appId: "your-app-id",
      addressTypes: [AddressType.solana],
    });

    async function signAndVerify() {
      const message = "Hello, please sign this message";
      
      // Sign the message using the SDK
      const { signature } = await sdk.solana.signMessage(message);
      const address = await sdk.solana.getPublicKey();

      // Send to your backend for verification
      const response = await fetch("/api/verify", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ address, message, signature }),
      });

      const { verified } = await response.json();
      return verified;
    }
    ```
  </Tab>

  <Tab title="React Native">
    ```tsx theme={null}
    import { useSolana } from "@phantom/react-native-sdk";
    import { View, Button, Alert, StyleSheet } from "react-native";

    function SignForVerification() {
      const { solana } = useSolana();

      const signAndVerify = async () => {
        try {
          const message = "Hello, please sign this message";
          
          const { signature } = await solana.signMessage(message);
          const address = await solana.getPublicKey();

          const response = await fetch("/api/verify", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
              address,
              message,
              signature,
            }),
          });

          const { verified } = await response.json();
          
          if (verified) {
            Alert.alert("Success", "Signature verified!");
          } else {
            Alert.alert("Error", "Signature verification failed");
          }
        } catch (error) {
          Alert.alert("Error", error.message);
        }
      };

      return (
        <View style={styles.container}>
          <Button title="Sign and Verify" onPress={signAndVerify} />
        </View>
      );
    }

    const styles = StyleSheet.create({
      container: {
        padding: 20,
      },
    });
    ```
  </Tab>
</Tabs>

## Verify a signature (backend)

### Install dependencies

```bash theme={null}
npm install @solana/web3.js tweetnacl bs58
```

### Verify a Solana signature

```typescript theme={null}
import { PublicKey } from "@solana/web3.js";
import nacl from "tweetnacl";
import bs58 from "bs58";

function verifySignature(
  walletAddress: string,
  message: string,
  signature: string
): boolean {
  try {
    const publicKey = new PublicKey(walletAddress);
    const messageBytes = new TextEncoder().encode(message);
    const signatureBytes = bs58.decode(signature);

    return nacl.sign.detached.verify(
      messageBytes,
      signatureBytes,
      publicKey.toBytes()
    );
  } catch {
    return false;
  }
}

// Usage
const isValid = verifySignature(
  "7fUAJdStEuGbc3sM84cKRL6yYaaSstyLSU4ve5oovLS7",
  "Hello, please sign this message",
  "5eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9..."
);

console.log("Signature valid:", isValid);
```

## API route example (Next.js)

```typescript theme={null}
// app/api/verify/route.ts
import { PublicKey } from "@solana/web3.js";
import nacl from "tweetnacl";
import bs58 from "bs58";
import { NextResponse } from "next/server";

export async function POST(request: Request) {
  const { address, message, signature } = await request.json();

  try {
    const publicKey = new PublicKey(address);
    const messageBytes = new TextEncoder().encode(message);
    const signatureBytes = bs58.decode(signature);

    const isValid = nacl.sign.detached.verify(
      messageBytes,
      signatureBytes,
      publicKey.toBytes()
    );

    if (!isValid) {
      return NextResponse.json({ error: "Invalid signature" }, { status: 401 });
    }

    return NextResponse.json({ verified: true, address });
  } catch (error) {
    return NextResponse.json({ error: "Verification failed" }, { status: 400 });
  }
}
```
