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

# Sign EVM Messages

> Sign messages with EIP-191 using Dynamic's Rust SDK for EVM chains

## Overview

`DynamicEvmWalletClient::sign_message` signs a UTF-8 message using EIP-191 (`personal_sign`) and returns a `0x`-prefixed `r || s || v` signature (65 bytes / 130 hex chars). Message signing is commonly used for authentication, nonce verification, and data integrity checks.

## Prerequisites

* [Created an EVM wallet](/rust/evm/create-wallet)

## Basic Message Signing

The Rust SDK is stateless — every sign call requires `WalletProperties` and `external_server_key_shares`. Load both from where you persisted them at wallet creation time.

```rust theme={"system"}
use dynamic_waas_sdk::{ServerKeyShare, WalletProperties};
use dynamic_waas_sdk_evm::DynamicEvmWalletClient;

let evm = DynamicEvmWalletClient::new(&client);

// Load the metadata + shares you persisted at creation time.
let wallet_properties: WalletProperties = serde_json::from_str(
    &redis.get(format!("wallet:{}", account_address)).await?,
)?;
let external_server_key_shares: Vec<ServerKeyShare> = serde_json::from_slice(
    &vault.read(format!("wallet:{}/shares", account_address)).await?,
)?;

let signature = evm
    .sign_message(
        &wallet_properties,
        &external_server_key_shares,
        "Hello, World!",
    )
    .await?;

println!("Signature: {signature}");
```

`signature` is a `0x`-prefixed hex string — pass it directly to any EIP-191 verifier (`alloy`, `ethers`, viem, etc).

## Verifying the signer locally

Because the signature is standard EIP-191, you can recover the signer with any EVM library. With `alloy`:

```rust theme={"system"}
use alloy_primitives::{Address, Signature};

let prefixed = format!(
    "\x19Ethereum Signed Message:\n{}{}",
    "Hello, World!".len(),
    "Hello, World!",
);
let digest = alloy_primitives::keccak256(prefixed.as_bytes());
let sig: Signature = signature.parse()?;
let recovered: Address = sig.recover_address_from_prehash(&digest)?;

assert_eq!(
    recovered.to_checksum(None),
    wallet_properties.account_address,
);
```

## Common Use Cases

### Authentication

```rust theme={"system"}
let nonce = chrono::Utc::now().timestamp_millis().to_string();
let message = format!("Sign this message to authenticate: {nonce}");
let signature = evm
    .sign_message(&wallet_properties, &external_server_key_shares, &message)
    .await?;
```

### Data Integrity

```rust theme={"system"}
let payload = serde_json::json!({ "user_id": 123, "action": "transfer", "amount": "100" });
let message = serde_json::to_string(&payload)?;
let signature = evm
    .sign_message(&wallet_properties, &external_server_key_shares, &message)
    .await?;
```

## Next Steps

* [Export the EVM private key](/rust/evm/export-private-key)
* [Use delegated access](/rust/evm/delegated-access)
