# Secure channel encryption (/en/realtime-media/iot/build/authenticate-and-secure-channels/media-stream-encryption)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

Media stream encryption prevents potential eavesdroppers from accessing sensitive and private information shared in a channel. IoT SDK provides built-in encryption methods that you can use to guarantee data confidentiality during transmission.

This page shows you how to integrate media stream encryption into your app using IoT SDK.

## Understand the tech

To ensure secure communication, your app uses an SSL [key](https://en.wikipedia.org/wiki/Key_authentication) and, for some encryption modes, a [salt](https://en.wikipedia.org/wiki/Salt_%28cryptography%29) to encrypt and decrypt data in the channel. Agora SDRTN® uses your key and salt to encrypt a stream and sends it to remote users. When a remote user receives an encrypted media stream, their app decrypts it using the same key and salt.

The following figure shows the call flow for media stream encryption:

![Encrypt media stream](https://assets-docs.agora.io/images/common/media-stream-encryption.png)

All users in a channel must use the same encryption mode, key, and salt. You set this configuration before you join a channel.

<CalloutContainer type="info">
  <CalloutDescription>
    Mismatched encryption configurations between users cause undefined behavior, such as a black screen or lost audio, instead of an explicit error. Best practice is to have your authentication system generate a new key and salt regularly.
  </CalloutDescription>
</CalloutContainer>

IoT SDK supports the following encryption modes:

* `AES_128_XTS`
* `AES_128_ECB`
* `AES_256_XTS`
* `SM4_128_ECB`
* `AES_128_GCM`
* `AES_256_GCM`
* `AES_128_GCM2` (recommended)
* `AES_256_GCM2` (recommended)

`AES_128_GCM2` and `AES_256_GCM2` use a more secure key derivation function and support a salt. For the other modes, you only need to set the encryption mode and key.

## Prerequisites

To follow this procedure you must have:

* Implemented the basic IoT SDK functionality. See [Build from scratch](../../build-from-scratch.mdx).

* [OpenSSL](https://www.openssl.org/) v3.0.0 or above.

## Generate a key and salt

Generate a 16-byte encryption key:

```bash
openssl rand -hex 16
```

If you use `AES_128_GCM2` or `AES_256_GCM2`, also generate a Base64-encoded, 32-byte salt:

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

## Enable encryption

Set the `crypto_opt` fields of `rtc_channel_options_t` before you call `agora_rtc_join_channel`:

```cpp
rtc_channel_options_t channel_options = { 0 };

// Enable encryption
channel_options.crypto_opt.enable = true;
// Set the encryption mode
channel_options.crypto_opt.mode = AES_128_GCM2;
// Set the key
sprintf(channel_options.crypto_opt.key, "%s", key_str);

// Set the salt (AES_128_GCM2 and AES_256_GCM2 only)
uint8_t *salt_bytes = NULL;
uint32_t salt_bytes_len = 0;
salt_bytes = util_base64_decode(salt_base64_str, strlen(salt_base64_str), &salt_bytes_len);
memcpy(channel_options.crypto_opt.salt, salt_bytes, salt_bytes_len);
free(salt_bytes);

// Join the channel
agora_rtc_join_channel(conn_id, channel_name, uid, token, &channel_options);
```

`key_str` and `salt_base64_str` are the key and salt you generated in [Generate a key and salt](#generate-a-key-and-salt). If your encryption mode doesn't use a salt, omit the salt-related lines.

## Reference

* [agora\_rtc\_join\_channel](https://api-ref.agora.io/en/iot-sdk/linux/1.x/agora__rtc__api_8h.html#a6c29ff27f04623526a164cf6e5dcd738)
