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

# TypeScript / WASM quickstart

> Use the Everabyte Crypto SDK from browser TypeScript to encrypt file content and names locally before relaying ciphertext through your own backend.

This page demonstrates **browser-side cryptography** with the prebuilt WASM binding. It does not call the Everabyte REST API from the browser. Everabyte API-key headers are not allowed by the API's CORS policy, and a secret API key embedded in browser code would be exposed to every user. Use your own authenticated backend to relay ciphertext and envelope data to Everabyte; that backend must never receive the UMK, DEK, or recovery phrase. See [Requests and CORS](https://docs.everabyte.com/authentication/requests-and-cors.md) and the [Node.js quickstart](https://docs.everabyte.com/sdk/quickstart-nodejs.md) for a server-side API example.

## 1. Install the browser binding

The WASM binding is in the public [everabyte/crypto-sdk](https://github.com/everabyte/crypto-sdk) repository: `bindings/wasm/pkg` is the browser/bundler build; `bindings/wasm/pkg-node` is for Node.js.

```bash theme={null}
npm install everabyte/crypto-sdk#path:bindings/wasm/pkg
```

```ts theme={null}
import init, {
  generate_umk,
  umk_public_keys,
  wrap_dek_to_umk,
  unwrap_dek_from_umk,
  evb1_seal_all,
  evb1_open_all,
  generate_random_12,
  generate_random_32,
  wrap_umk_with_mnemonic,
  derive_wire_alias,
  encrypt_file_name,
  decrypt_file_name,
} from "evb-e2ee-wasm";

await init(); // load the WASM module using your bundler's wasm-bindgen setup
```

## 2. Create and enroll an account key

Generate the UMK in the browser. Register only its public keys and recovery-wrapped copy through your authenticated application backend. Obtain the step-up token using the account's supported step-up flow; do not put the Everabyte secret API key in this browser code.

```ts theme={null}
const umk = generate_umk(); // 96 bytes: X25519 secret (32) || ML-KEM seed (64)
const publics = JSON.parse(umk_public_keys(umk.subarray(0, 32), umk.subarray(32)));
const mnemonic = await promptUserForFreshRecoveryPhrase();
const stepUpToken = await obtainStepUpTokenFromYourApplication();
const wrappedBlob = wrap_umk_with_mnemonic(
  umk.subarray(0, 32), umk.subarray(32), mnemonic,
);

await fetch("/api/everabyte/e2ee/keys/register", {
  method: "POST",
  credentials: "same-origin",
  headers: { "Content-Type": "application/json", "X-CSRF-Token": csrfToken },
  body: JSON.stringify({
    publicKeyX25519: publics.publicKeyX25519,
    publicKeyMlkem: publics.publicKeyMlkem,
    wraps: [{ wrapKind: "mnemonic", wrappedBlob }],
    stepUpToken,
  }),
});
```

`/api/everabyte/...` is an example route in **your application**, not an Everabyte endpoint. Implement authorization, CSRF protection, request validation and API-key storage on that backend. The backend forwards the registration request to `POST /e2ee/keys/register` without ever seeing the unwrapped UMK or recovery phrase. Show the recovery phrase once and store it outside Everabyte. If every enrolled device and the phrase are lost, the files cannot be recovered by support.

## 3. Encrypt a browser-selected file

The whole-buffer WASM helpers take the complete file and return the complete encrypted payload. For large files, account for that memory use; this binding does not expose the Rust streaming API.

```ts theme={null}
async function encryptSelectedFile(file: File) {
  const plaintext = new Uint8Array(await file.arrayBuffer());
  const dek = generate_random_32();
  const payload = evb1_seal_all(dek, generate_random_12(), plaintext);

  const wireName = derive_wire_alias(
    umk.subarray(0, 32), umk.subarray(32), file.name,
  );
  const encryptedName = encrypt_file_name(dek, file.name, generate_random_12());
  const envelope = JSON.parse(wrap_dek_to_umk(
    dek,
    Uint8Array.from(atob(publics.publicKeyX25519), c => c.charCodeAt(0)),
    Uint8Array.from(atob(publics.publicKeyMlkem), c => c.charCodeAt(0)),
  ));

  return { payload, wireName, encryptedName, envelope };
}
```

Send only `payload`, `wireName`, `encryptedName`, and the envelope to your backend (for example, as a multipart file plus a JSON metadata part). Never send `dek`, `umk`, or `mnemonic`. The backend uploads the ciphertext to `POST /files/upload/{bucketId}` and attaches the envelope using `POST /e2ee/files/by-path/envelope`. It must check both responses and retain the resulting file identifier. The encrypted display name is optional for backward compatibility in the API, but include it for new files when the original name must be restored. On an attach timeout, reconcile before cleanup. After a confirmed failure, resolve the uploaded row by bucket and opaque wire name, confirm it has no envelope, and hard-delete it through the file API as required by the E2EE upload contract. Handle retention blocks explicitly.

## 4. Download and decrypt locally

Have your backend authorize the request and return the stored ciphertext plus the caller's envelope. The browser then unwraps the DEK locally and opens the payload:

```ts theme={null}
const dek = unwrap_dek_from_umk(
  JSON.stringify(envelope), umk.subarray(0, 32), umk.subarray(32),
);
const plaintext = evb1_open_all(dek, ciphertext);
const originalName = decrypt_file_name(dek, envelope.encryptedName);
```

The response data from your backend must contain ciphertext and envelope only. Do not return secret API credentials to the browser.

## Next steps

* [Node.js quickstart](https://docs.everabyte.com/sdk/quickstart-nodejs.md) for a server-side integration that calls the REST API directly.
* [SDK API reference](https://docs.everabyte.com/sdk/api-reference.md) for every binding export.
* [Wire protocol reference](https://docs.everabyte.com/sdk/protocol-reference.md) for format and interoperability details.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.