# Kanały szyfrowane

Kanał, którego nazwa zaczyna się od `private-encrypted-`, jest szyfrowany end-to-end. Twój serwer szyfruje każdy payload przed opublikowaniem, a zatwierdzone klienty przeglądarkowe odszyfrowują go kluczem z Twojego endpointu autoryzacji. Krawędź Realtime i pośrednicy sieciowi widzą wyłącznie szyfrogram.

Wygeneruj i przechowaj 32-bajtowy klucz główny. Klucz główny nigdy nie pojawia się w żądaniu API Realtime, a prefiks nazwy kanału włącza tę funkcję. Bird nie może odzyskać utraconego klucza, a payloady zaszyfrowane tym kluczem pozostają nieczytelne po jego wymianie.

Kanały szyfrowane korzystają z tego samego endpointu i podpisu co [kanały prywatne](/docs/guides/realtime/private-channels). Odpowiedź autoryzacji zawiera również pochodny klucz deszyfrujący kanału jako `shared_secret`. Odrzucenie subskrypcji uniemożliwia klientowi otrzymanie klucza.

## Generowanie klucza głównego

Wygeneruj 32 losowe bajty, zakoduj je w base64 i przechowaj wartość tak jak sekret aplikacji:

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

Przekaż go do SDK serwera jako część konfiguracji realtime, obok klucza aplikacji i sekretu.

## Publikowanie zaszyfrowanego zdarzenia

SDK serwera wykrywa prefiks kanału, wyprowadza klucz z klucza głównego i szyfruje payload JSON lokalnie. Żądanie publikacji zawiera zaszyfrowaną kopertę.

**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](/pl-pl/dokumentacja/guides/realtime/encrypted-channels.ts.md) · [Python](/pl-pl/dokumentacja/guides/realtime/encrypted-channels.py.md) · [Go](/pl-pl/dokumentacja/guides/realtime/encrypted-channels.go.md) · [PHP](/pl-pl/dokumentacja/guides/realtime/encrypted-channels.php.md)

Zaszyfrowany kanał musi być jedynym kanałem w pojedynczej publikacji. Każdy zaszyfrowany kanał wyprowadza inny klucz, więc pozostałe kanały nie mogłyby odszyfrować tego samego zaszyfrowanego payloadu. SDK-i odrzucają ten fan-out lokalnie, a API zwraca `E23000`, jeśli go otrzyma. Aby opublikować na kilku zaszyfrowanych kanałach, użyj batcha z jednym kanałem na zdarzenie.

## Zwracanie wspólnego sekretu z endpointu autoryzacji

Twój endpoint autoryzacji zatwierdza zaszyfrowane subskrypcje tak samo jak prywatne. Użyj helpera `authorizeChannel` z SDK, a odpowiedź automatycznie otrzyma `shared_secret`, gdy nazwa kanału zawiera prefiks szyfrowania:

**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](/pl-pl/dokumentacja/guides/realtime/encrypted-channels.ts.md) · [Python](/pl-pl/dokumentacja/guides/realtime/encrypted-channels.py.md) · [Go](/pl-pl/dokumentacja/guides/realtime/encrypted-channels.go.md) · [PHP](/pl-pl/dokumentacja/guides/realtime/encrypted-channels.php.md)

SDK wyprowadza osobny `shared_secret` dla każdego kanału. Autoryzacja dla `private-encrypted-orders` nie pozwala więc odszyfrować `private-encrypted-invoices`. Sekret przesyłany jest w odpowiedzi autoryzacji i nie jest dołączany do ramki subskrypcji wysyłanej do krawędzi.

## Subskrypcja i deszyfrowanie w przeglądarce

Szyfr korzysta z osobnego punktu wejścia `@messagebird/realtime/encrypted`. Zaimportuj go i przekaż jako opcję `encryption` klienta:

```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" }
});
```

Bindingi otrzymują tekst jawny. Subskrypcja bez opcji `encryption` natychmiast rzuca wyjątek, a odpowiedź autoryzacji bez `shared_secret` powoduje niepowodzenie subskrypcji.

Obecnie tylko klient przeglądarkowy obsługuje kanały szyfrowane. Klienty Swift i Kotlin odrzucają subskrypcje `private-encrypted-`, ponieważ nie implementują deszyfrowania.

## Rotacja klucza głównego

Wdróż nowy klucz jednocześnie na wszystkich publisherach i endpointach autoryzacji. Podczas rotacji:

1. Nowe publikacje są szyfrowane nowym kluczem.
2. Zasubskrybowany klient przeglądarkowy, który nie może odszyfrować zdarzenia, ponownie się autoryzuje i pobiera nowy `shared_secret`.
3. Instancje korzystające z różnych kluczy głównych mogą chwilowo publikować zdarzenia, których niektóre klienty nie potrafią odszyfrować, więc koordynuj wdrożenie między instancjami.

Dokonaj rotacji klucza w przypadku wycieku lub utraty. Rotacja chroni przyszłe payloady, ale nie może ponownie zaszyfrować wcześniejszych zdarzeń ani unieważnić kopii starego klucza.

## Czego kanały szyfrowane nie robią

- **Oficjalne klienty nie obsługują zdarzeń klienckich.** Przeglądarkowy `trigger()` rzuca wyjątek na kanałach szyfrowanych, ponieważ klient nie szyfruje payloadów klient-klient. Nie wysyłaj jawnych zdarzeń klienckich z niestandardowego klienta.
- **Obecność i szyfrowanie nie mogą być łączone.** Prefiks `presence-encrypted-` nie jest obsługiwany. Cache i szyfrowanie działają razem: kanały `private-encrypted-cache-` przechowują zbuforowane zdarzenie w postaci zaszyfrowanej, choć po rotacji klucza zbuforowana kopia pozostaje zaszyfrowana starym kluczem, dopóki kolejna publikacja jej nie zastąpi.
- **Nazwy kanałów i nazwy zdarzeń nie są szyfrowane.** Szyfrowany jest wyłącznie payload. Dobieraj nazwy kanałów tak, aby nie ujawniały tego, co chronisz.
- **Krawędź Realtime nie może analizować payloadów.** Nazwy kanałów i zdarzeń pozostają widoczne, natomiast payload jest zaszyfrowany.

## Następne kroki

- [Autoryzacja kanałów](/docs/guides/realtime/authorizing-channels) to mechanizm podpisów, na którym opiera się ten przewodnik.
- [Publikowanie zdarzeń](/docs/guides/realtime/publishing-events) opisuje same API publikacji i batchów.
- [Kanały cache](/docs/guides/realtime/cache-channels) wyjaśniają odtwarzanie ostatniego zdarzenia, z którym łączy się `private-encrypted-cache-`.

## 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)
