Sign inGet started

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. 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:
Przykład kodu
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ę.
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" },
});
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:
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,
    }),
  );
});
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:
Przykład kodu
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

Powiązane zasoby

Kontynuuj z dokumentacją, przewodnikami i przykładami dotyczącymi tego tematu. Zasoby są w języku angielskim.

Wypróbuj ćwiczenie i uzyskaj brief wdrożeniowy