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

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

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

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

## 技术原理 [#技术原理-3]

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

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

## 前提条件 [#前提条件-3]

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

## 实现方法 [#实现方法-4]

参考如下步骤，为你的 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/cpp-all-platforms/network#api_irtcengine_enableencryption) 设置 `AES_128_GCM2` 或 `AES_256_GCM2` 加密模式，并将密钥和盐传入 SDK。

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

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

    ```cpp
    #include <boost/algorithm/string/trim.hpp>
    #include <boost/archive/iterators/base64_from_binary.hpp>
    #include <boost/archive/iterators/binary_from_base64.hpp>
    #include <boost/archive/iterators/transform_width.hpp>
    #include <boost/range/algorithm/copy.hpp>

    namespace detail {
    using Base64FromBinary = boost::archive::iterators::base64_from_binary<
        boost::archive::iterators::transform_width<const char*, 6, 8>>;

    using BinaryFromBase64 = boost::archive::iterators::transform_width<
        boost::archive::iterators::binary_from_base64<std::string::const_iterator>,
        8, 6>;
    }

    void decodeBase64(const std::string& encoded, std::vector<uint8_t>& out) {
        auto unpadded = encoded;

        const auto num_padded = std::count(begin(encoded), end(encoded), '=');
        std::replace(begin(unpadded), end(unpadded), '=', 'A');  // A_64 == \0

        std::string decoded{
            detail::BinaryFromBase64{begin(unpadded)},
            detail::BinaryFromBase64{begin(unpadded) + unpadded.length()}};

        decoded.erase(end(decoded) - num_padded, end(decoded));
        std::copy(begin(decoded), end(decoded), out.begin());
    }
    // 请在调用 initialize 初始化 rtcEngine 后再调用该方法
    int enableEncryption() {
        std::string secret;
        std::string kdfSaltBase64;
        std::vector<uint8_t> kdfSalt;
        for (int i = 0; i < 32; ++i) {
            kdfSalt.push_back(0);
        }
        if (!getSecretAndSaltFromSever(secret, kdfSaltBase64)) return -1;
        if (rtcEngine && decodeBase64(kdfSaltBase64, kdfSalt)) {
            // 创建一个 EncryptionConfig 实例
            agora::rtc::EncryptionConfig config;
            // 将加密模式设置为 AES_128_GCM2
            config.encryptionMode = AES_128_GCM2;
            // 设置密钥
            config.encryptionKey = secret.c_str();
            // 设置盐
            memcpy(config.encryptionKdfSalt, kdfSalt.data(),
                sizeof(config.encryptionKdfSalt));
            // 开启内置加密
            return rtcEngine->enableEncryption(true, config);
        }
        return -1;
    }
    ```

   上述示例代码中使用到了第三方库 Boost，你可以前往 [boostorg](https://archives.boost.io/release/) 官网下载。

## 参考信息 [#参考信息-3]

### 示例项目 [#示例项目-3]

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

<Cards>
  <Card title={<RepositoryCardTitle provider="gitee">CAgoraMediaEncryptDlg</RepositoryCardTitle>} href="https://gitee.com/agoraio-community/API-Examples/tree/main/windows/APIExample/APIExample/Advanced/MediaEncrypt" />
  <Card title={<RepositoryCardTitle provider="github">CAgoraMediaEncryptDlg</RepositoryCardTitle>} href="https://github.com/Shengwang-Community/API-Examples/tree/main/windows/APIExample/APIExample/Advanced/MediaEncrypt" />
</Cards>

### 注意事项 [#注意事项-3]

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








