# Channel terenkripsi

Channel yang namanya diawali dengan `private-encrypted-` dienkripsi secara end-to-end. Server Anda menyegel setiap payload sebelum mempublikasikannya, dan klien browser yang disetujui mendekripsinya dengan kunci dari endpoint otorisasi Anda. Realtime edge dan perantara jaringan hanya melihat ciphertext.

Buat dan simpan master key sepanjang 32 byte. Master key tidak pernah muncul dalam permintaan API Realtime, dan prefiks nama channel mengaktifkan fitur ini. Bird tidak dapat memulihkan kunci yang hilang, dan payload yang disegel dengan kunci tersebut tetap tidak dapat dibaca setelah Anda menggantinya.

Channel terenkripsi menggunakan endpoint dan tanda tangan yang sama dengan [channel privat](/docs/guides/realtime/private-channels). Respons otorisasi juga menyertakan kunci dekripsi turunan channel sebagai `shared_secret`. Menolak langganan mencegah klien tersebut menerima kunci.

## Buat master key

Buat 32 byte acak, enkode sebagai base64, dan simpan nilainya seperti app secret:

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

Berikan ke SDK server Anda sebagai bagian dari konfigurasi realtime, di samping app key dan secret.

## Publikasikan event terenkripsi

SDK server mendeteksi prefiks channel, menurunkan kunci dari master key, dan menyegel payload JSON secara lokal. Permintaan publish berisi envelope yang telah disegel.

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

Channel terenkripsi harus menjadi satu-satunya channel dalam satu kali publish. Setiap channel terenkripsi menurunkan kunci yang berbeda, sehingga channel lain tidak dapat mendekripsi payload tersegel yang sama. SDK menolak fan-out ini secara lokal, dan API mengembalikan `E23000` jika menerimanya. Untuk mempublikasikan ke beberapa channel terenkripsi, gunakan batch dengan satu channel per event.

## Kembalikan kunci rahasia bersama dari endpoint auth Anda

Endpoint auth Anda menyetujui langganan terenkripsi sama seperti menyetujui langganan privat. Gunakan helper `authorizeChannel` milik SDK dan respons akan memperoleh `shared_secret` secara otomatis setiap kali nama channel membawa prefiks terenkripsi:

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

SDK menurunkan `shared_secret` terpisah untuk setiap channel. Otorisasi untuk `private-encrypted-orders` oleh karena itu tidak mendekripsi `private-encrypted-invoices`. Secret dikirim dalam respons otorisasi Anda dan tidak disertakan dalam frame langganan yang dikirim ke edge.

## Berlangganan dan dekripsi di browser

Cipher menggunakan entry point `@messagebird/realtime/encrypted` terpisah. Impor dan teruskan sebagai opsi `encryption` klien:

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

Binding menerima plaintext. Berlangganan tanpa opsi `encryption` langsung melempar error, dan respons otorisasi tanpa `shared_secret` menggagalkan langganan.

Saat ini hanya klien browser yang menerima channel terenkripsi. Klien Swift dan Kotlin menolak langganan `private-encrypted-` karena tidak mengimplementasikan dekripsi.

## Rotasi master key

Deploy kunci baru ke semua publisher dan endpoint otorisasi secara bersamaan. Selama rotasi:

1. Publish baru disegel dengan kunci baru.
2. Klien browser yang berlangganan dan tidak dapat mendekripsi suatu event akan melakukan otorisasi ulang sekali dan mengambil `shared_secret` yang baru.
3. Instance yang menggunakan master key berbeda dapat sebentar mempublikasikan event yang tidak dapat didekripsi oleh sebagian klien, jadi koordinasikan peluncuran ke seluruh instance.

Rotasi kunci yang bocor atau hilang. Rotasi melindungi payload di masa depan tetapi tidak dapat menyegel ulang event sebelumnya atau mencabut salinan kunci lama.

## Hal yang tidak dilakukan channel terenkripsi

- **Klien resmi tidak mendukung client event.** Browser `trigger()` melempar error pada channel terenkripsi karena klien tidak menyegel payload klien-ke-klien. Jangan mengirim client event plaintext dari klien kustom.
- **Presence dan enkripsi tidak dapat digabungkan.** Prefiks `presence-encrypted-` tidak didukung. Cache dan enkripsi dapat bekerja bersama: channel `private-encrypted-cache-` menyimpan event yang di-cache dalam keadaan tersegel, meskipun setelah rotasi kunci, salinan cache tetap tersegel dengan kunci lama hingga publish berikutnya menggantinya.
- **Nama channel dan nama event tidak dienkripsi.** Hanya payload yang dienkripsi. Pilih nama channel yang tidak membocorkan apa yang Anda lindungi.
- **Realtime edge tidak dapat memeriksa payload.** Nama channel dan event tetap terlihat, sementara payload tetap terenkripsi.

## Langkah selanjutnya

- [Otorisasi channel](/docs/guides/realtime/authorizing-channels) adalah mekanisme tanda tangan yang menjadi dasar panduan ini.
- [Mempublikasikan event](/docs/guides/realtime/publishing-events) membahas API publish dan batch itu sendiri.
- [Channel cache](/docs/guides/realtime/cache-channels) menjelaskan replay event terakhir yang digabungkan oleh `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)
