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

# Keys and Authentication in the Walley Python SDK

> How the SDK loads your Ed25519 key (key file, mnemonic, PEM, raw bytes), derives the party id, signs messages, and authenticates API reads.

A Walley party is controlled by a single Ed25519 key. This page covers how the SDK loads it, how the party id relates to it, and how authentication works under the hood.

## Loading the key

The recommended way is a **key file** — key material stays out of source code:

```python theme={null}
Walley(key_file="~/.config/walley/alice.key")   # or set WALLEY_KEY_FILE
```

The file's format is detected automatically: a PKCS#8 PEM, a 24-word BIP-39 recovery phrase, or a hex/base64 raw key. Inline forms are also supported:

```python theme={null}
Walley(mnemonic="brief lyrics ...")          # 24-word recovery phrase
Walley(private_key=b"\x9d\x61...")           # raw 32 bytes
Walley(private_key="9d61b19d...")            # hex
Walley(private_key="nWGxne/9WmC6...")        # base64
Walley(private_key="-----BEGIN PRIVATE KEY-----\n...")  # PKCS#8 PEM
```

<Note>
  The recovery phrase **is** the key: its 256 bits of entropy are used directly as the Ed25519 private key — no derivation path, no passphrase — exactly as the Walley app encodes it at registration. See [Recovery Phrase](/concepts/recovery-phrase).
</Note>

## Keys, fingerprints, and party ids

The `Signer` class converts between representations:

```python theme={null}
from walley import Signer

s = Signer.from_file("~/.config/walley/alice.key")
s.mnemonic                    # back to the 24 words — the offline backup
s.fingerprint                 # "1220..." — SHA-256 fingerprint of the public key
s.party_id("walley-alice")    # "walley-alice::1220..."
```

A Canton party id is `<hint>::<fingerprint>`, so the key and the party are cryptographically bound. Identify the party either way:

```python theme={null}
Walley(key_file=..., party_hint="walley-alice")      # id derived from the key
Walley(key_file=..., party_id="walley-alice::1220...")  # verified against the key
```

A `party_id` whose namespace doesn't match the key's fingerprint is rejected up front.

## Signing arbitrary messages

`w.sign(...)` produces a signature bundle any verifier can check against the party id — useful for login proofs and off-ledger attestations:

```python theme={null}
signed = w.sign("login:my-dapp:2026-07-03")
signed.signature      # base64 Ed25519 signature (64 bytes)
signed.signed_by      # key fingerprint == party id namespace
signed.public_key     # base64 DER SPKI public key

w.signer.sign(b"raw bytes")   # just the raw 64-byte signature
```

This is the headless equivalent of the dApp SDK's [`signMessage`](/build/provider-api).

## Configuration reference

| Constructor arg    | Env var              | Default                  |
| ------------------ | -------------------- | ------------------------ |
| `key_file`         | `WALLEY_KEY_FILE`    | —                        |
| `mnemonic`         | `WALLEY_MNEMONIC`    | —                        |
| `private_key`      | `WALLEY_PRIVATE_KEY` | —                        |
| `party_id`         | `WALLEY_PARTY_ID`    | —                        |
| `party_hint`       | `WALLEY_PARTY_HINT`  | —                        |
| `api_base`         | `WALLEY_API_URL`     | `https://api.walley.cc`  |
| `audience`         | —                    | `https://walley.cc/dapp` |
| `auto_settle_fees` | —                    | `True`                   |

`audience` must match the target deployment's auth configuration, you can override it together with `api_base` when pointing at a non-production environment.
