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

# Sign EVM Messages

> Learn how to sign EIP-191 messages with an EVM wallet using Dynamic's Python SDK

## Overview

This guide shows you how to sign messages with your EVM wallet. Message signing is commonly used for authentication, proof of ownership, and off-chain data verification. The Python SDK signs messages using [EIP-191](https://eips.ethereum.org/EIP-191) personal sign format.

## Prerequisites

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

## Basic Message Signing

```python theme={"system"}
import asyncio
import os
from dynamic_wallet_sdk import DynamicEvmWalletClient

async def main():
    async with DynamicEvmWalletClient(os.environ["DYNAMIC_ENV_ID"]) as client:
        await client.authenticate_api_token(os.environ["DYNAMIC_API_TOKEN"])

        signature = await client.sign_message(
            message="Hello, Dynamic!",
            address="0xYourWalletAddress",
        )
        print(f"Signature: {signature}")

asyncio.run(main())
```

The returned signature is a hex string (`0x...`), 132 characters long (65 bytes: r + s + v).

## Signing with a Password-Protected Wallet

If you created your wallet with a password, pass it when signing:

```python theme={"system"}
signature = await client.sign_message(
    message="Hello, Dynamic!",
    address="0xYourWalletAddress",
    password="your-wallet-password",
)
```

**Password handling:**

* If your wallet was created **without a password**, omit the `password` parameter.
* If your wallet was created **with a password**, you must provide it for all signing operations.

The same `password=` kwarg also enables **auto-recovery** in fresh processes — the SDK transparently rehydrates key shares from Dynamic's encrypted backup before signing. See [Step 3 of Create an EVM Wallet](/python/evm/create-wallet) for details.

## Verifying a Signature

You can verify the signature off-chain using `eth-account`:

```python theme={"system"}
from eth_account import Account
from eth_account.messages import encode_defunct

message = "Hello, Dynamic!"
signature = await client.sign_message(message=message, address=address)

msg = encode_defunct(text=message)
recovered = Account.recover_message(msg, signature=signature)

assert recovered.lower() == address.lower(), "Signature mismatch!"
print("Signature verified")
```

## Common Use Cases

### Authentication Nonce

```python theme={"system"}
import time

nonce = str(int(time.time()))
message = f"Sign this message to authenticate: {nonce}"

signature = await client.sign_message(message=message, address=address)
```

### Proof of Ownership

```python theme={"system"}
message = f"I own wallet {address}"
signature = await client.sign_message(message=message, address=address)
```

## Next Steps

* [Sign typed data (EIP-712)](/python/evm/sign-typed-data)
* [Sign transactions](/python/evm/sign-transactions)
