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

# Key Management

> Key derivation, storage, protection, and recovery

# Key Management

Privacy Boost derives a set of privacy keys from a single seed. These keys give the user a private identity — separate from their public wallet address — that can send, receive, and hold shielded tokens.

## What Gets Derived

<img className="block dark:hidden" src="https://mintcdn.com/sunnysidelabs/npTSPV0krdyxjvTn/images/sdk/key-derivation.svg?fit=max&auto=format&n=npTSPV0krdyxjvTn&q=85&s=e1ad494f5673f523097090d14bcf5b97" alt="Key Derivation Hierarchy" width="600" height="460" data-path="images/sdk/key-derivation.svg" />

<img className="hidden dark:block" src="https://mintcdn.com/sunnysidelabs/npTSPV0krdyxjvTn/images/sdk/key-derivation-dark.svg?fit=max&auto=format&n=npTSPV0krdyxjvTn&q=85&s=3e597e2153be8e3dafa814f45cbfd021" alt="Key Derivation Hierarchy" width="600" height="460" data-path="images/sdk/key-derivation-dark.svg" />

From the seed, the SDK derives three keys that together form the user's private identity:

| Key                | Purpose                                                                                                                                                                            | Scope                                                                                      |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| **Viewing key**    | Encrypts and decrypts transaction metadata. Included in your [privacy address](/technical-explainer/keys-and-encryption#privacy-address) so others can send you private transfers. | Controls **visibility** — who can see your balance and transaction history.                |
| **Nullifying key** | Links your identity to your notes. Used to compute nullifiers when spending.                                                                                                       | Controls **identity** — ties specific notes in the shielded pool to your account.          |
| **Auth key**       | Authorizes transfers and withdrawals inside ZK proofs. Registered on-chain in the AuthRegistry.                                                                                    | Controls **spending** — required to move funds. Can be rotated or revoked via your wallet. |

These keys are designed with **separation of concerns**: the viewing key handles privacy, the nullifying key handles identity, and the auth key handles fund custody. This means a single key being exposed doesn't give full access — for example, leaking the viewing key reveals your balance but doesn't allow anyone to spend your funds. For the full security model and threat analysis, see [Keys & Encryption](/technical-explainer/keys-and-encryption).

Your **Master Public Key (MPK)** and **privacy address** are derived from these keys. The MPK is your public identity in Privacy Boost — safe to share. The privacy address is what you give to others so they can send you private transfers.

## Key Sources

The `keySource` parameter controls where the seed comes from.

| Key Source      | Best for                 | What the user needs to back up                  |
| --------------- | ------------------------ | ----------------------------------------------- |
| `walletDerived` | Most apps                | Nothing — same wallet always produces same keys |
| `mnemonic`      | Cross-wallet portability | The 12-word phrase                              |
| `rawSeed`       | Testing and development  | The hex seed                                    |

### walletDerived (recommended)

The SDK asks the wallet to sign a deterministic message and uses the signature as the seed. The same wallet always produces the same signature, so the same privacy keys are derived every time. This is the simplest option because the wallet itself is the backup — there's nothing extra for the user to write down.

### mnemonic

The SDK derives keys from a BIP-39 mnemonic phrase. This is useful when you want keys to be portable across different wallets, but the user must securely store the phrase.

### rawSeed

A raw 32-byte hex seed. Intended for testing.

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Wallet-derived (recommended)
  await sdk.auth.authenticate(adapter, { keySource: { type: 'walletDerived' } });

  // From mnemonic
  await sdk.auth.authenticate(adapter, { keySource: { type: 'mnemonic', phrase: 'your twelve word phrase ...' } });
  ```

  ```swift iOS theme={null}
  // Wallet-derived
  try await sdk.authenticate(wallet: wallet, keySource: .walletDerived())

  // From mnemonic
  try await sdk.authenticate(wallet: wallet, keySource: .mnemonic(phrase: "your twelve word phrase ..."))
  ```

  ```kotlin Android theme={null}
  // Wallet-derived
  sdk.authenticate(wallet, keySource = KeySource.WalletDerived())

  // From mnemonic
  sdk.authenticate(wallet, keySource = KeySource.Mnemonic(phrase = "your twelve word phrase ..."))
  ```
</CodeGroup>

## Persistence & Protection

Without persistence, the SDK re-derives keys every time the user opens your app (requiring wallet signature popups). With persistence enabled, keys are encrypted and stored locally so returning users can log in silently.

Persistence has two parts: **where** keys are stored and **how** they're protected.

### Storage

| Storage        | Platform     | Notes                                                |
| -------------- | ------------ | ---------------------------------------------------- |
| `localStorage` | Web          | Simple, cleared when users clear site data           |
| `indexedDB`    | Web          | More robust, survives some clear-data actions        |
| `osKeychain`   | iOS, Android | Platform-native secure storage (Keychain / Keystore) |

### Protection (Unlock Method)

You can require the user to unlock stored keys before they're used:

| Unlock Method | How it works                                            |
| ------------- | ------------------------------------------------------- |
| `none`        | Keys are encrypted but accessible without user input    |
| `pin`         | User enters a numeric PIN each time                     |
| `password`    | User enters a password each time                        |
| `biometric`   | Face ID, Touch ID, or fingerprint prompt (iOS, Android) |
| `passkey`     | WebAuthn passkey (experimental)                         |

When `pin` or `password` is used, `authenticate()` returns a `credentialRequired` result so your app can show the appropriate input. See [Authentication — PIN / Password Unlock](/sdk/concepts/authentication#pin--password-unlock).

When `biometric` is used, the platform prompt appears automatically.

### Configuration

<CodeGroup>
  ```typescript TypeScript theme={null}
  const sdk = await PrivacyBoost.create({
    // ... required fields
    persistence: {
      storage: 'localStorage',  // 'localStorage' | 'indexedDB'
      unlock: 'pin',            // 'none' | 'pin' | 'password'
    },
  });
  ```

  ```swift iOS theme={null}
  let config = PrivacyBoostConfig(
      // ... required fields
      persistenceStorage: .osKeychain,
      persistenceUnlock: .biometric
  )
  ```

  ```kotlin Android theme={null}
  val config = PrivacyBoostConfig(
      // ... required fields
      persistenceStorage = StorageBackend.OsKeychain,
      persistenceUnlock = UnlockMethod.Biometric
  )
  ```
</CodeGroup>

### How Persistence Interacts with Key Source

| Returning user?              | What happens                                         |
| ---------------------------- | ---------------------------------------------------- |
| First visit (no stored keys) | SDK uses `keySource` to derive keys, then saves them |
| Returning (keys stored)      | SDK loads keys from storage; `keySource` is ignored  |

This means a user only needs to provide their mnemonic once. After that, keys are loaded from storage.

## Session Export & Import

If you don't want to use persistence, you can manually save and restore sessions on native platforms:

<CodeGroup>
  ```swift iOS theme={null}
  if let session = sdk.exportSession() {
      saveToKeychain(session) // You handle secure storage
  }

  if let session = loadFromKeychain() {
      try sdk.importSession(session)
  }
  ```

  ```kotlin Android theme={null}
  sdk.exportSession()?.let { saveToSecureStorage(it) }

  loadFromSecureStorage()?.let { sdk.importSession(it) }
  ```
</CodeGroup>

<Warning>
  Exported sessions contain private keys. Always store them in the platform's secure storage (Keychain, Keystore, or encrypted storage).
</Warning>

## Recovery

Keys are derived deterministically, so recovery is straightforward as long as the original key source is available.

| Key Source      | How to recover                                                    |
| --------------- | ----------------------------------------------------------------- |
| `walletDerived` | Log in with the same wallet — same keys are derived automatically |
| `mnemonic`      | Provide the same 12-word phrase                                   |
| `rawSeed`       | Provide the same hex seed                                         |

**Funds are never lost.** Deposits live on-chain in the shielded pool. Once keys are re-derived, the SDK automatically finds and restores your balance.

### Common Recovery Scenarios

**Cleared app data or reinstalled the app?**
Re-authenticate with the same key source. A new vault is created automatically.

**Forgot vault PIN/password?**
Clear app storage, then re-authenticate with the original key source. The old vault is discarded and a new one is created. No funds are lost.

**Lost device?**
Your funds are safe — session data is encrypted on-device. Set up a new device and authenticate with the same wallet or mnemonic.

**Switching to a new device?**
Either re-authenticate with the same key source, or on native platforms use `exportSession()` / `importSession()` to transfer the session directly.

<Warning>
  If you used `mnemonic` and lose the phrase without having an exported session, your keys cannot be recovered. Back up the phrase securely.
</Warning>

## Next Steps

* [Error Handling](/sdk/concepts/error-handling) — Handle SDK errors with structured error codes
* [Keys & Encryption](/technical-explainer/keys-and-encryption) — Deep dive into the key hierarchy, privacy addresses, and 3-way ECDH encryption

Platform-specific session and storage guides:

<CardGroup cols={2}>
  <Card title="iOS: Session Storage" href="/sdk/ios/guides/session-storage">
    Secure Keychain storage and biometric unlock
  </Card>

  <Card title="Android: Session Storage" href="/sdk/android/guides/session-storage">
    Android Keystore storage and biometric unlock
  </Card>

  <Card title="React Native: Session Storage" href="/sdk/react-native/guides/session-storage">
    AsyncStorage and Keychain persistence
  </Card>
</CardGroup>
