> For the complete documentation index, see [llms.txt](https://docs.coti.io/coti-documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.coti.io/coti-documentation/privacy-on-demand/account-onboarding-aes-key.md).

# Account onboarding (AES key)

Every PoD user needs an **account AES key** to decrypt `ct*` values returned from private operations. The key is a 16-byte AES secret represented as **32 hexadecimal characters without a `0x` prefix**.

This page describes a practical onboarding flow. Low-level crypto helpers live in [`@coti-io/coti-sdk-typescript`](/coti-documentation/privacy-on-demand/coti-typescript-sdk-for-pod.md); decryption in app code typically goes through [`CotiPodCrypto`](/coti-documentation/privacy-on-demand/typescript-pod-sdk.md).

## Trust model

* AES key recovery happens on a **trusted client** (browser, mobile app, or user-controlled wallet extension).
* A backend may broker encrypted key shares but must **never** see the plaintext AES key.
* Do not pass the recovered key in URLs, query parameters, or server logs.

## Typical flow

1. Client generates an RSA key pair.
2. Client sends the RSA **public** key to your onboarding service.
3. Service returns two encrypted key shares.
4. Client decrypts and combines shares into the account AES key.
5. Client stores the key in secure local storage.

## Example implementation

```typescript
import { generateRSAKeyPair, recoverUserKey } from "@coti-io/coti-sdk-typescript";

type KeySharesResponse = {
  encryptedKeyShare0: string;
  encryptedKeyShare1: string;
};

async function onboardAccount(
  requestShares: (publicKey: Uint8Array) => Promise<KeySharesResponse>
): Promise<string> {
  const { publicKey, privateKey } = generateRSAKeyPair();
  const { encryptedKeyShare0, encryptedKeyShare1 } = await requestShares(publicKey);

  const accountAesKey = recoverUserKey(privateKey, encryptedKeyShare0, encryptedKeyShare1);

  if (!/^[0-9a-fA-F]{32}$/.test(accountAesKey)) {
    throw new Error("invalid AES key format");
  }

  return accountAesKey;
}
```

## Storage recommendations

| Environment          | Recommendation                                                               |
| -------------------- | ---------------------------------------------------------------------------- |
| Web dApp             | Encrypted-at-rest in browser storage with strict origin and session controls |
| Mobile               | OS keychain or secure enclave                                                |
| Server-rendered apps | Avoid persisting the AES key on the server                                   |

## Operational guardrails

* Never log key shares or the recovered key.
* Enforce TLS and authenticated onboarding endpoints.
* Define account recovery and key-rotation policy before production launch.
* Pair onboarding with [async UX guidance](/coti-documentation/privacy-on-demand/async-private-operations.md): users cannot decrypt results until onboarding completes.

## See also

* [COTI TypeScript SDK for PoD](/coti-documentation/privacy-on-demand/coti-typescript-sdk-for-pod.md) — `generateRSAKeyPair`, `recoverUserKey`, decrypt helpers
* [TypeScript PoD SDK](/coti-documentation/privacy-on-demand/typescript-pod-sdk.md) — `CotiPodCrypto.decrypt`
* [Tutorial: private Adder on Sepolia](/coti-documentation/privacy-on-demand/tutorial-private-adder-sepolia.md) — end-to-end walkthrough that assumes a key is available


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.coti.io/coti-documentation/privacy-on-demand/account-onboarding-aes-key.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
