媒体流加密
- Windows
更新时间不可用
了解实时互动 RTC 在不同平台上的媒体流加密方式,包括接入流程、关键配置和平台差异。
媒体流加密是指通过由 App 开发者控制的唯一的密钥和盐为 App 中的音视频流加密。声网提供媒体流加密功能以确保传输过程中数据的保密性,建议你根据实际的业务场景合理应用。
本文介绍如何在你的 App 中添加声网内置媒体流加密。
技术原理
下图描述了启用媒体流加密后的数据传输流程。声网推荐使用 AES_128_GCM2 或 AES_256_GCM2 加密模式,并设置密钥和盐。
前提条件
在进行操作之前,请确保你已经在项目中实现了基本的实时音视频功能。详见实现音视频互动。
实现方法
参考如下步骤,为你的 App 添加内置媒体流加密功能:
-
在你的服务端生成一个密钥和盐。
-
在你的服务端,参考以下命令,通过 OpenSSL 随机生成一个 16 字节的随机值,并以 16 进制(hex)字符串形式输出,作为密钥使用:
Shell # 随机生成一个密钥 openssl rand -hex 16 # 示例输出 9f3c7a1e5b8d4c2a6e0f91b7d4a2c8e5 -
在你的服务端,参考以下命令,通过 OpenSSL 随机生成 Base64 编码、32 字节的盐:
Shell # 随机生成一个 Base64 编码、32 字节的盐 openssl rand -base64 32 # 示例输出 X5w9T+50kzxVOnkJKiY/lUk82/bES2kATOt3vBuGEDw=
-
-
实现客户端逻辑:
-
从服务端获取
String型的密钥和 Base64 编码的盐。 -
将盐从 Base64 转换成
uint8_t。 -
加入频道前,调用
enableEncryption设置AES_128_GCM2或AES_256_GCM2加密模式,并将密钥和盐传入 SDK。
注意
- 同一频道内所有用户必须使用相同的加密模式、密钥和盐。否则,可能会出现黑屏或音频丢失等未定义行为。
- 为确保安全性,声网建议在每次启用媒体流加密前使用新的密钥和盐。
以下示例代码展示了该逻辑的实现过程:
C++ #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 官网下载。
-
参考信息
示例项目
声网提供了开源的媒体流加密示例项目供你参考,你可以前往下载或查看其中的源代码。
注意事项
如需与 Web 平台的音视频 SDK 互通,你还需要将本文提到的 String 型密钥从 Hex 编码格式转换成 ASCII 编码格式。