> ## 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. The SDK returns the signature as raw bytes (`Uint8Array`), so encode it as base58 with `bs58` (`npm install bs58`) before sending it to your backend:

**React**

```tsx theme={null}
import { useSolana } from "@phantom/react-sdk";
import bs58 from "bs58";

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

  const signAndVerify = async () => {
    const message = "Hello, please sign this message";
    
    const address = solana.publicKey;
    if (!address) throw new Error("Wallet not connected");

    // 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,
        message,
        signature: bs58.encode(signature),
      }),
    });

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

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

**Browser SDK**

```typescript theme={null}
import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
import bs58 from "bs58";

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";
  
  const address = sdk.solana.publicKey;
  if (!address) throw new Error("Wallet not connected");

  // Sign the message using the SDK
  const { signature } = await sdk.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, message, signature: bs58.encode(signature) }),
  });

  const { verified } = await response.json();
  return verified;
}
```

**React Native**

```tsx theme={null}
import { useSolana } from "@phantom/react-native-sdk";
import bs58 from "bs58";
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 address = solana.publicKey;
      if (!address) throw new Error("Wallet not connected");
      const { signature } = await solana.signMessage(message);

      const response = await fetch("/api/verify", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          address,
          message,
          signature: bs58.encode(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,
  },
});
```

## 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 });
  }
}
```
