# 媒体流加密 (/zh-CN/realtime-media/rtc/build/advanced-channel/channel-encryption/android)

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

媒体流加密是指通过由 App 开发者控制的唯一的密钥和[盐](https://en.wikipedia.org/wiki/Salt_(cryptography))为 App 中的音视频流加密。声网提供媒体流加密功能以确保传输过程中数据的保密性，建议你根据实际的业务场景合理应用。

本文介绍如何在你的 App 中添加声网内置媒体流加密。

## 技术原理 [#技术原理]

下图描述了启用媒体流加密后的数据传输流程。声网推荐使用 `AES_128_GCM2` 或 `AES_256_GCM2` 加密模式，并设置密钥和盐。

![加密传输流程](https://web-cdn.agora.io/docs-portal/img/rtc/encryption.png)

## 前提条件 [#前提条件]

在进行操作之前，请确保你已经在项目中实现了基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。

## 实现方法 [#实现方法]

参考如下步骤，为你的 App 添加内置媒体流加密功能：

1. 在你的服务端生成一个密钥和盐。

   - 在你的服务端，参考以下命令，通过 OpenSSL 随机生成一个 16 字节的随机值，并以 16 进制 (hex) 字符串形式输出，作为密钥使用：

      ```shell
      # 随机生成一个密钥
      openssl rand -hex 16
      # 示例输出
      9f3c7a1e5b8d4c2a6e0f91b7d4a2c8e5
      ```

   - 在你的服务端，参考以下命令，通过 OpenSSL 随机生成 Base64 编码、32 字节的盐：

      ```shell
      # 随机生成一个 Base64 编码、32 字节的盐
      openssl rand -base64 32
      # 示例输出
      X5w9T+50kzxVOnkJKiY/lUk82/bES2kATOt3vBuGEDw=
      ```

2. 实现客户端逻辑：

   1. 从服务端获取 `String` 型的密钥和 Base64 编码的盐。

   2. 将盐从 Base64 转换成 `uint8_t`。

   3. 加入频道前，调用 [`enableEncryption`](/zh-CN/api-reference/rtc/android/network#api_irtcengine_enableencryption) 设置 `AES_128_GCM2` 或 `AES_256_GCM2` 加密模式，并将密钥和盐传入 SDK。

:::warning[注意]
- 同一频道内所有用户必须使用相同的加密模式、密钥和盐。否则，可能会出现黑屏或音频丢失等未定义行为。
- 为确保安全性，声网建议在每次启用媒体流加密前使用新的密钥和盐。
:::

   以下示例代码展示了该逻辑的实现过程：

   ```java
   import java.util.Base64;
   import io.agora.rtc2.RtcEngine;
   import io.agora.rtc2.internal.EncryptionConfig;

   class Example
   {
       public bool enableEncryption(RtcEngine engine) {
           if(engine == null)
               return false;
           // 从服务端获取 Base64 编码的盐
           String encryptionKdfSaltBase64 = Server.getEncryptionKdfSaltBase64();
           // 从服务端获取 String 型的密钥
           String encryptionSecret = Server.getEncryptionSecret();
           if(encryptionKdfSaltBase64 == null || encryptionSecret == null)
               return false;

           // 将 Base64 编码的盐转换成 uint8_t
           byte[] encryptionKdfSalt = Base64.getDecoder().decode(encryptionKdfSaltBase64);
           // 创建一个 EncryptionConfig 实例
           EncryptionConfig config = new EncryptionConfig();
           // 将加密模式设置为 AES_128_GCM2
           config.encryptionMode = EncryptionConfig.EncryptionMode.AES_128_GCM2;
           config.encryptionKey = encryptionSecret;
           System.arraycopy(encryptionKdfSalt, 0, config.encryptionKdfSalt, 0, config.encryptionKdfSalt.length);
           int result = engine.enableEncryption(true, config);
           return (result == 0);
       }
   }
   ```

## 参考信息 [#参考信息]

### 示例项目 [#示例项目]

声网提供了开源的媒体流加密示例项目供你参考，你可以前往下载或查看其中的源代码。

<Cards>
  <Card title={<RepositoryCardTitle provider="gitee">ChannelEncryption</RepositoryCardTitle>} href="https://gitee.com/agoraio-community/API-Examples/blob/main/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/ChannelEncryption.java" />
  <Card title={<RepositoryCardTitle provider="github">ChannelEncryption</RepositoryCardTitle>} href="https://github.com/Shengwang-Community/API-Examples/blob/main/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/ChannelEncryption.java" />
</Cards>

### 注意事项 [#注意事项]

如需与 Web 平台的音视频 SDK 互通，你还需要将本文提到的 `String` 型密钥从 Hex 编码格式转换成 ASCII 编码格式。
















