# Keep the secret with the client.

> Run key generation, encrypted evaluation, and decryption as separate commands with explicit file boundaries.

- Canonical page: https://www.poulpy.dev/docs/client-evaluator/
- Poulpy version: 0.9.0
- Source revision: [`7dd13e6aa9808982f5355fb6acb70ca434de4e35`](https://github.com/poulpy-fhe/poulpy/tree/7dd13e6aa9808982f5355fb6acb70ca434de4e35)
- Documentation reviewed: 2026-10-08
- Audience: For application developers

## Build the example

Use the project from [Standalone application](https://www.poulpy.dev/docs/application/), then run:

```sh
cargo build --locked --release --bin client_evaluator
```

The [complete source](https://www.poulpy.dev/examples/poulpy-app/src/bin/client_evaluator.rs) evaluates the same `(a + b) × b` calculation. This is a local-file teaching protocol with small, unrated parameters, not a network service.

## 1. Client creates the request

From the example directory:

```sh
cargo run --locked --release --bin client_evaluator -- setup client-private request
```

The command creates fresh directories and refuses to overwrite existing files. It samples a fresh secret seed and separate encryption randomness, then creates two ciphertexts and a relinearization key.

| Location | Contents | Who receives it? |
| --- | --- | --- |
| `client-private/secret.seed` | Seed used to reconstruct the client's secret key | Client only |
| `request/a.ct`, `request/b.ct` | Serialized ciphertexts with their noise metadata, and CKKS metadata | Evaluator |
| `request/evaluation.key` | Unprepared multiplication/relinearization key | Evaluator |

The seed is secret-key material. On Unix the example creates a private directory with mode 0700 and files with mode 0600; on other systems use an appropriately protected client directory. For an actual transfer, give the evaluator access to the request directory only.

## 2. Evaluator returns an encrypted result

```sh
cargo run --locked --release --bin client_evaluator -- evaluate request response.ct
```

This command reads only the request files. It restores and prepares the evaluation key, evaluates the circuit, and writes the resulting ciphertext. It neither opens the client directory nor reconstructs a secret key.

```text
evaluated (a + b) * b without a secret key
evaluation only: ... ms; scratch ... bytes; response ... bytes
```

The timing includes addition and multiplication after setup. It excludes parsing, key preparation, allocation, and output serialization. It is a single-run diagnostic at learning parameters, not a comparative performance result. See [Measure a workload](https://www.poulpy.dev/docs/measurement/).

## 3. Client decrypts and checks

```sh
cargo run --locked --release --bin client_evaluator -- decrypt client-private response.ct
```

```text
ok: client verified 512 slots; max error ...
```

The client reconstructs its key and checks real and imaginary errors below `1e-9`. The tutorial knows the generated test inputs, so it can compare with a cleartext reference. This test is not a general proof of correct server execution.

## Serialization boundary

The application uses Poulpy's `WriterTo` and `ReaderFrom` for host-readable GLWE and evaluation-key layouts. Its small `PWP1` envelope records the effective ciphertext width and CKKS scale; slot kind, sparsity, dimensions, and parameter set are fixed by the example.

Each serialized layout starts with a short noise-metadata prefix, whose length depends on whether an encryption recorded its noise. Before restoring a layout, the reader bounds the file size and compares the serialized shape header against the expected allocation. It rejects mismatched widths, scales, lengths, and trailing bytes. The exact wire-format header sizes are tied to the pinned revision. Backend-prepared keys are recreated on the evaluator rather than transmitted.

These checks do not authenticate ciphertext contents or make arbitrary malicious ciphertexts safe. A deployment needs its own authenticated protocol, key/version identifiers, input validation, and restricted decryption policy. Review [Security and responsibilities](https://www.poulpy.dev/docs/security/) before adapting this example.
