# spark\_signMessage

The `spark_signMessage` method lets your app request a **secure, hashed message signature** from the user’s Spark wallet.\
This method provides a safe way to verify ownership of a Spark address, authenticate a user, or prove intent **without exposing the wallet to raw arbitrary message signing attacks.**

## :closed\_lock\_with\_key: How It Works

To ensure signing security and prevent vulnerabilities with arbitrary data, Xverse implements a **hash-before-sign** scheme.\
When your app sends a message to be signed:

1. The raw message string is **UTF-8 decoded** into bytes.
2. The wallet computes the SHA-256 hash of the message bytes
3. The wallet signs the resulting hash with the user’s Spark identity key
4. The wallet returns **the message signature** to your app in base64 format

This prevents signature malleability and enforces minimum payload size, while aligning with the cryptographic standards used by **Spark** and **Flashnet**.

## Parameters

<table><thead><tr><th width="221">Request parameters</th><th>Description</th></tr></thead><tbody><tr><td><code>message</code></td><td>a string representing the UTF-8 message to sign</td></tr></tbody></table>

## Example

```ts
import { request } from "sats-connect";

const message = `Xverse / Spark — Sign-in Request
App: flashdex.example
Action: auth
Nonce: 6b6a7b2a-4e1b-4c2c-9f46-1f2b3d0a9e23
Issued At: 2025-10-22T09:31:12Z
Expires At: 2025-10-22T09:36:12Z
Chain: spark
Note: This does not move funds.`;

const res = await request("spark_signMessage", { message });
```

## What `spark_signMessage` does

When called, this method:

1. Prompts the user to review the message to sign with their Xverse wallet:

* **Title:** `Sign Message with Spark Wallet`
* **Message Preview:** The human-readable message (UTF-8 text)
* The user can confirm or cancel the signing request

2. Signs the message upon user approval, following the [signing procedure](#how-it-works)
3. Returns **the message signature** to your app in base64 format

### Response

#### ✅ Success

```ts
{
  signature: "3045022100..." // Spark signature of the message in base64 format
}
```

#### :x: Error

```ts
{
  errorCode: "SIGN-MESSAGE-001",
  message: "User rejected message signing" | "Invalid message format",
  requestId: "01HJZKFABCDEFGHJKLMNPQRSTVW"
}
```

### 🔍 Verifying the Signature on Your Backend

To verify the signature:

```ts
import { secp256k1 } from '@noble/curves/secp256k1.js';
import { base64, hex } from '@scure/base';

// convert UTF-8 string to bytes
const decodedMessage = new TextEncoder().encode(message);

// decode base64 encoded signature
const decodedSignature = base64.decode(response.result.signature);

// decode hex encoded public key (provided by wallet)
const decodedPublicKey = hex.decode(sparkPublicKey);

const isValid = secp256k1.verify(decodedSignature, decodedMessage, decodedPublicKey);
```

This ensures end-to-end consistency: the signature always corresponds to the deterministic SHA-256 hash of the message.

## ⚠️ Security Notes

* The wallet **never signs raw messages directly** — only hashed digests.
* The app must display or record the human-readable message alongside the signature for auditability.
* Avoid embedding sensitive data directly in the message body; instead, use authentication challenges or session tokens.
* SHA-256 is fixed as the canonical hash digest for this method to stay consistent with Spark’s on-chain cryptography.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.xverse.app/sats-connect/spark-methods/spark_signmessage.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
