# Versleutelde kanalen

Een kanaal waarvan de naam begint met `private-encrypted-` is end-to-end versleuteld. Je server versleutelt elke payload voordat hij deze publiceert, en goedgekeurde browserclients ontsleutelen de payload met een sleutel van je autorisatie-endpoint. De Realtime-edge en netwerktussenstations zien alleen cijfertekst.

Genereer en bewaar een 32-byte mastersleutel. De mastersleutel verschijnt nooit in een Realtime API-request, en het kanaalnaamprefix schakelt de functie in. Bird kan een verloren sleutel niet herstellen, en payloads die met die sleutel versleuteld zijn, blijven onleesbaar nadat je hem vervangt.

Versleutelde kanalen gebruiken hetzelfde endpoint en dezelfde handtekening als [privékanalen](/docs/guides/realtime/private-channels). Het autorisatieantwoord bevat ook de afgeleide ontsleutelingssleutel van het kanaal als `shared_secret`. Door een abonnement te weigeren voorkom je dat die client de sleutel ontvangt.

## Een mastersleutel genereren

Genereer 32 willekeurige bytes, codeer ze als base64 en bewaar de waarde net als het app-secret:

```bash
openssl rand -base64 32
```

Geef hem aan je server-SDK als onderdeel van de realtime-configuratie, naast de app-key en het secret.

## Een versleuteld event publiceren

De server-SDK detecteert het kanaalprefix, leidt de sleutel af van de mastersleutel en versleutelt de JSON-payload lokaal. Het publish-request bevat de versleutelde envelop.

**TypeScript**

```typescript
import { BirdClient } from "@messagebird/sdk";

const bird = new BirdClient({
  apiKey: process.env.BIRD_API_KEY,
  realtime: {
    key: process.env.BIRD_REALTIME_KEY,
    secret: process.env.BIRD_REALTIME_SECRET,
    encryptionMasterKey: process.env.BIRD_REALTIME_MASTER_KEY,
  },
});

await bird.realtime.publish("rap_01krdgeqcxet5s7t44vh8rt9mg", {
  event: "order.updated",
  channels: ["private-encrypted-orders"],
  data: { order_id: "ord_123", status: "shipped" },
});
```

Examples: [TypeScript](/nl-nl/documentatie/guides/realtime/encrypted-channels.ts.md) · [Python](/nl-nl/documentatie/guides/realtime/encrypted-channels.py.md) · [Go](/nl-nl/documentatie/guides/realtime/encrypted-channels.go.md) · [PHP](/nl-nl/documentatie/guides/realtime/encrypted-channels.php.md)

Een versleuteld kanaal moet het enige kanaal in een enkele publish zijn. Elk versleuteld kanaal leidt een andere sleutel af, dus andere kanalen kunnen dezelfde versleutelde payload niet ontsleutelen. De SDK's weigeren deze fan-out lokaal, en de API retourneert `E23000` als hij er een ontvangt. Gebruik een batch met één kanaal per event om naar meerdere versleutelde kanalen te publiceren.

## Het gedeelde geheim retourneren vanuit je auth-endpoint

Je auth-endpoint keurt versleutelde abonnementen op dezelfde manier goed als privéabonnementen. Gebruik de `authorizeChannel`-helper van de SDK en het antwoord krijgt automatisch de `shared_secret` wanneer de kanaalnaam het versleutelde prefix bevat:

**TypeScript**

```typescript
app.post("/bird/auth", async (req, res) => {
  const { connection_id, channel_name } = req.body;

  const user = getUserFromSession(req);
  if (!user || !mayJoin(user, channel_name)) return res.sendStatus(403);

  res.json(
    await bird.realtime.authorizeChannel({
      connectionId: connection_id,
      channelName: channel_name,
    }),
  );
});
```

Examples: [TypeScript](/nl-nl/documentatie/guides/realtime/encrypted-channels.ts.md) · [Python](/nl-nl/documentatie/guides/realtime/encrypted-channels.py.md) · [Go](/nl-nl/documentatie/guides/realtime/encrypted-channels.go.md) · [PHP](/nl-nl/documentatie/guides/realtime/encrypted-channels.php.md)

De SDK leidt een apart `shared_secret` af voor elk kanaal. Autorisatie voor `private-encrypted-orders` ontsleutelt daarom `private-encrypted-invoices` niet. Het geheim reist mee in je autorisatieantwoord en zit niet in het abonnementsframe dat naar de edge wordt gestuurd.

## Abonneren en ontsleutelen in de browser

De cipher gebruikt het aparte `@messagebird/realtime/encrypted`-ingangspunt. Importeer het en geef het mee als de `encryption`-optie van de client:

```typescript
import { BirdRealtime } from "@messagebird/realtime";
import { encryption } from "@messagebird/realtime/encrypted";

const bird = new BirdRealtime({
  appKey: "your-app-key",
  region: "us1",
  authEndpoint: "/bird/auth",
  encryption,
});

const orders = bird.subscribe("private-encrypted-orders");
orders.bind("order.updated", (data) => {
  console.log(data); // decrypted: { order_id: "ord_123", status: "shipped" }
});
```

Bindings ontvangen leesbare tekst. Abonneren zonder de `encryption`-optie gooit direct een fout, en een autorisatieantwoord zonder `shared_secret` laat het abonnement mislukken.

Alleen de browserclient ontvangt momenteel versleutelde kanalen. De Swift- en Kotlin-clients weigeren `private-encrypted-`-abonnementen omdat ze ontsleuteling niet implementeren.

## De mastersleutel roteren

Rol de nieuwe sleutel tegelijk uit naar elke publisher en elk autorisatie-endpoint. Tijdens de rotatie:

1. Nieuwe publishes versleutelen met de nieuwe sleutel.
2. Een geabonneerde browserclient die een event niet kan ontsleutelen, autoriseert eenmalig opnieuw en haalt het nieuwe `shared_secret` op.
3. Instanties met verschillende mastersleutels kunnen kort events publiceren die sommige clients niet kunnen ontsleutelen. Coördineer de uitrol over instanties.

Roteer een gelekte of verloren sleutel. Rotatie beschermt toekomstige payloads, maar kan eerdere events niet opnieuw versleutelen of kopieën van de oude sleutel intrekken.

## Wat versleutelde kanalen niet doen

- **Officiële clients ondersteunen geen client-events.** Browser-`trigger()` gooit een fout op versleutelde kanalen omdat de client client-naar-client-payloads niet versleutelt. Verstuur geen leesbare client-events vanuit een aangepaste client.
- **Presence en versleuteling zijn niet te combineren.** Het `presence-encrypted-`-prefix wordt niet ondersteund. Cache en versleuteling werken wel samen: `private-encrypted-cache-`-kanalen slaan het gecachete event versleuteld op, maar na een sleutelrotatie blijft de gecachete kopie versleuteld met de oude sleutel totdat de volgende publish deze vervangt.
- **Kanaalnamen en eventnamen worden niet versleuteld.** Alleen de payload wordt versleuteld. Kies kanaalnamen die niet onthullen wat je beschermt.
- **De Realtime-edge kan payloads niet inspecteren.** Kanaal- en eventnamen blijven zichtbaar, terwijl de payload versleuteld blijft.

## Volgende stappen

- [Kanalen autoriseren](/docs/guides/realtime/authorizing-channels) beschrijft het handtekeningmechanisme waarop deze gids voortbouwt.
- [Events publiceren](/docs/guides/realtime/publishing-events) behandelt de publish- en batch-API's zelf.
- [Cachekanalen](/docs/guides/realtime/cache-channels) legt de last-event-replay uit waarmee `private-encrypted-cache-` combineert.

## Related resources

- [Realtime](/products/realtime) (product)
- [Build your first integration](/learn/paths/integration) (course)
- [Send your first realtime event](/docs/get-started/send-your-first-realtime-event) (docs)

[Get an implementation brief](/learn/workspace?topic=realtime)
