Skip to main content

Keys & Wallets

Keys and wallets are the identity and access layer of Cardano. A seed phrase generates a tree of key pairs, public keys are hashed into the address credentials that lock UTXOs, and wallet software manages it all so users can send, receive, and stake. Whoever holds the private key controls the funds, there is no password reset.

If you have used SSH, the model will feel familiar: you already generate an ed25519 key pair, keep the private key local, share the public key, and prove possession by signing. Cardano keys work the same way, except you authenticate to the whole network and can move value, so losing the key costs more than losing server access. A CIP-30 wallet connector, meanwhile, is like "Sign in with Google" (OAuth): the dApp receives the signatures it asks for but never sees your raw private key.

What is a key pair?

A key pair is a private key (32 bytes of entropy) and its public key (derived via Ed25519, the same algorithm as SSH ed25519 keys).

private_key = random_256_bits()
public_key = ed25519_derive(private_key)

private -> public: easy
public -> private: infeasible
sign(msg, private) -> 64-byte signature
verify(msg, sig, public) -> true/false
  • The private key is your identity. Whoever holds it can spend the funds.
  • The public key is your verifiable identity. Share it freely; others verify your signatures and derive your address from it.

Why not use raw key pairs?

One key per address creates real problems: transactions become trivially linkable, managing hundreds of unrelated keys is error-prone, backups are impractical, and a compromised key cannot be rotated. The fix is Hierarchical Deterministic (HD) wallets.

Seed phrases (BIP-39)

A mnemonic seed phrase is a human-readable encoding of random entropy as words from a standard 2048-word list (Cardano wallets use 15 or 24 words). This single phrase deterministically regenerates your entire key tree, so it is the only backup you need.

24 words = 256 bits of entropy = 2^256 possible phrases (~10^77).
Brute-forcing one is not impractical; it is physically impossible.

The phrase is stretched into a 512-bit root key via PBKDF2. An optional passphrase (a "25th word") produces a completely different wallet from the same words.

HD derivation (BIP-32 / CIP-1852)

An HD wallet derives an unlimited number of keys from the root key along a tree, so the mnemonic alone recreates every key the wallet ever used.

m / purpose' / coin_type' / account' / role / index

For Cardano: m / 1852' / 1815' / 0' / 0 / 0
1852' = Shelley-era purpose (CIP-1852)
1815' = ADA coin type
0' = account
role = 0 external (payment), 1 internal (change), 2 staking
index = address index

(1815 and 1852 are Ada Lovelace's birth and death years.) New addresses are generated by incrementing the index; no need to revisit the seed. Non-hardened levels even allow watch-only wallets that track balances without the ability to sign.

Payment keys vs staking keys

Cardano deliberately separates the two:

Payment key (m/1852'/1815'/acct'/0/index): controls spending. Many per account.
Staking key (m/1852'/1815'/acct'/2/0): controls delegation + reward withdrawal. One per account.

This means you can delegate stake without giving anyone the ability to spend your funds, and all addresses in an account contribute to one delegation.

What is a wallet, really?

A wallet is software that stores your keys, scans the chain for UTXOs at your addresses, computes your balance, and builds and signs transactions. Your funds live on-chain as UTXOs; they are not "inside" the app.

Wallet typeExamplesTrade-off
Full-nodeDaedalusMaximum trustlessness; downloads the whole chain
LightBrowser and mobile walletsFast; relies on a backend for chain data (signing stays local)
HardwareLedger, TrezorKeys never leave a secure device; strongest theft protection
Browser extension(implements CIP-30)The standard way dApps connect to users

How dApps connect: CIP-30

CIP-30 is the dApp connector standard. The wallet exposes an API; it signs only what the user approves and never exposes private keys, much like "Sign in with Google" hands an app a token, not your password.

const wallet = await window.cardano.eternl.enable()
const utxos = await wallet.getUtxos()
const signed = await wallet.signTx(unsignedTx) // user approves in the wallet

Wallets can also sign arbitrary messages (CIP-8 / COSE) to prove address ownership without submitting a transaction, the basis for wallet login. For implementations, see Wallet authentication.

Working with wallets in code

For a browser dApp, you don't manage keys at all: you connect the user's CIP-30 wallet (above), covered in Connect a wallet. For backend services, scripts, and tests, you create a wallet from a mnemonic, a private key, or just an address (read-only). The SDK handles the BIP-32/CIP-1852 derivation described above.

In Evolution, a wallet is one capability of a client. Add it with .withSeed(), .withPrivateKey(), or .withAddress() (a wallet on its own can sign and derive addresses; add a provider to also query and submit):

import { preprod, Client } from "@evolution-sdk/evolution"

// From a 24-word mnemonic (dev, testing, multi-account via accountIndex)
const seedClient = Client.make(preprod)
.withSeed({ mnemonic: process.env.WALLET_MNEMONIC!, accountIndex: 0 })

// From an extended private key (backend automation; load from a vault)
const keyClient = Client.make(preprod)
.withPrivateKey({ paymentKey: process.env.PAYMENT_SIGNING_KEY! })

// Read-only, observe an address, no signing (backend tx-building, monitoring)
const watchClient = Client.make(preprod)
.withAddress({ address: "addr1..." })

const address = await seedClient.address()

Generate a fresh mnemonic with PrivateKey.generateMnemonic(). Switch networks by changing the network parameter (preprodmainnet); use a different mnemonic per environment.

The four wallet types map to four security models: pick the weakest that fits the job:

TypeHas keysCan signWhere keys liveUse for
Seed phraseYes (local)YesMemory / .envDevelopment, testing
Private keyYes (local)YesSecret vaultBackend automation
CIP-30 (browser)No (external)Via userUser's deviceFrontend dApps
Read-onlyNoneNoAddress onlyBackend tx-building, monitoring
Backend key handling

Never bundle a mnemonic or private key into frontend code, and never commit one. On a backend, load keys from a secret manager (AWS Secrets Manager, Azure Key Vault, HashiCorp Vault), use a read-only wallet wherever you only need to build transactions, and keep separate keys per environment. Production key handling is covered in going to production.

Security: it all reduces to key management

  • Seed phrase: never store digitally (no photos, cloud, or text files); write on durable material; consider the optional passphrase.
  • Key isolation: hardware wallets keep keys in a secure element; extensions encrypt with a spending password.
  • Address hygiene: let the wallet generate fresh addresses; reuse links your history.
  • Verify on-device: confirm transaction details on the hardware wallet screen, not just the app.

Key takeaways

  • A 24-word BIP-39 seed phrase is the root of your whole identity; HD derivation (BIP-32 / CIP-1852) grows the key tree from it.
  • Cardano separates payment keys (spending) from staking keys (delegation), so you can delegate without exposing spending control.
  • A wallet is software that manages keys and builds transactions; funds live on-chain as UTXOs.
  • CIP-30 lets dApps request signatures without ever seeing private keys; security reduces to protecting the seed phrase and isolating keys.

Next steps

  • Addresses: how these keys become the credentials that lock funds
  • Transactions: how wallets build, sign, and submit