媒体流加密是指通过由 app 开发者控制的唯一的密钥和盐为 app 中的音视频流加密。虽然并不是所有应用场景下都需要对媒体流进行加密,但声网提供媒体流加密功能以确保传输过程中数据的保密性。
本文介绍如何在你的 app 中添加声网内置媒体流加密。
下图描述了启用媒体流加密后的数据传输流程。声网推荐使用 AES_128_GCM2
或 AES_256_GCM2
加密模式,并设置密钥和盐。
在进行操作之前,请确保你已经在项目中实现了基本的实时音视频功能。详见实现视频通话或实现视频直播。
参考如下步骤,为你的 app 添加内置媒体流加密功能:
在你的服务端生成一个密钥和盐;
在你的服务端,参考以下命令,通过 OpenSSL 随机生成 String 型、32 字节的密钥:
// 随机生成一个 String 型、32 字节的密钥
openssl rand -hex 32
dba643c8ba6b6dc738df43d9fd624293b4b12d87a60f518253bd10ba98c48453
在你的服务端,参考以下命令,通过 OpenSSL 随机生成 Base64 编码、32 字节的盐:
// 随机生成一个 Base64 编码、32 字节的盐
openssl rand -base64 32
X5w9T+50kzxVOnkJKiY/lUk82/bES2kATOt3vBuGEDw=
实现客户端逻辑:
从服务端获取 String 型的密钥和 Base64 编码的盐。
将盐从 Base64 转换成 uint8_t。
加入频道前,调用 enableEncryption 设置 AES_128_GCM2
或 AES_256_GCM2
加密模式,并将密钥和盐传入 SDK。
以下示例代码展示了该逻辑的实现过程:
#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 官网下载。
本节提供了在实现流媒体加密功能时可能需要的参考信息。
声网在 GitHub 上提供一个开源的内置媒体流加密示例项目。你可以前往下载,或查看其中的源代码。
如需与 Web 平台的音视频 SDK 互通,你还需要将本文提到的 String 型密钥从 Hex 编码格式转换成 ASCII 编码格式。