在实时音视频互动过程中,开发者需要对媒体流加密,从而保障用户的数据安全。Agora 提供内置加密方案和自定义加密方案,区别如下:
你可以根据需要选择合适的加密方案。
下图描述了启用媒体流加密后的数据传输流程:
Agora 在 GitHub 上提供以下实现了媒体流加密功能的开源示例项目:
你可以下载体验并参考源代码。
在启用媒体流加密前,请确保已在你的项目中实现基本的实时音视频功能。
1. 获取加密库(仅 iOS)
自 3.2.0 版本起,Agora iOS SDK 中的 AgoraRtcCryptoLoader.framework
加密库合并入 AgoraRtcKit.framework
。如果你使用 3.2.0 及以上版本的 SDK,获取 AgoraRtcKit.framework
后即可使用内置的加密方案。
如果你使用 3.2.0 以下版本的 SDK,除获取 AgoraRtcKit.framework
外,还需参考以下步骤获取 AgoraRtcCryptoLoader.framework
加密库并导入类:
选择以下一种方法集成加密库:
a. 开始前确保你已安装 Cocoapods。参考 Getting Started with CocoaPods 安装说明。
b. 在 Terminal 里进入项目根目录,并运行 pod init
命令。项目文件夹下会生成一个 Podfile
文本文件。
c. 打开 Podfile
文件,修改文件为如下内容。注意将 Your App
替换为你的 Target 名称,并将 version
替换为你需集成的 SDK 版本。
# platform :ios, '9.0' use_frameworks!
target 'Your App' do
pod 'AgoraRtcEngine_iOS_Crypto', 'version'
end
d. 在 Terminal 内运行 pod install
命令安装 Agora SDK。成功安装后,Terminal 中会显示 Pod installation complete!
,此时项目文件夹下会生成一个 xcworkspace
文件。
e. 打开新生成的 xcworkspace
文件。
a. 将 SDK 包中的 AgoraRtcCryptoLoader.framework
复制到项目文件夹下。
b. 打开 Xcode(以 Xcode 11.0 为例),进入 TARGETS > Project Name > General > Frameworks, Libraries, and Embedded Content 菜单,点击 +,再点击 Add Other… 添加 AgoraRtcCryptoLoader.framework
,并确保添加的动态库 Embed 属性设置为 Embed & Sign。
在项目中导入 AgoraRtcCryptoLoader
类:
// Swift
import AgoraRtcCryptoLoader
// Objective-C
#import <AgoraRtcCryptoLoader/AgoraRtcCryptoLoader.h>
2. 开启内置加密
在加入频道前,调用 enableEncryption
方法开启内置加密,并设置加密模式和密钥。
Agora 支持 4 种加密模式:
AgoraEncryptionModeAES128XTS
: 128 位 AES 加密,XTS 模式。AgoraEncryptionModeAES128ECB
: 128 位 AES 加密,ECB 模式。AgoraEncryptionModeAES256XTS
: 256 位 AES 加密,XTS 模式。AgoraEncryptionModeSM4128ECB
: 128 位国密 SM4 加密,ECB 模式。// Swift
// 创建一个 AgoraEncryptionConfig 实例
let config = AgoraEncryptionConfig()
// 设置加密模式为国密 SM4 加密模式
config.encryptionMode = AgoraEncryptionMode.SM4128ECB
// 设置加密密钥
config.encryptionKey = "xxxxxxxxxxxxxxxx"
// 启用内置加密
agoraKit.enableEncryption(true, config)
// Objective-C
// 创建一个 AgoraEncryptionConfig 实例
AgoraEncryptionConfig *config = [[AgoraEncryptionConfig alloc] init];
// 设置加密模式为国密 SM4 加密模式,并设置加密密钥
config.encryptionMode = AgoraEncryptionModeSM4128ECB;
config.encryptionKey = @"xxxxxxxxxxxxxxxx";
// 启用内置加密
[agoraKit enableEncryption: YES encryptionConfig:config];
Agora 提供 C++ 的 registerPacketObserver
方法及 IPacketObserver
类,帮助你实现自定义加密功能。
.mm
文件中实现。.mm
文件的开头需要引入 C++ 头文件: #include <AgoraRtcKit/IAgoraRtcEngine.h>
。参考步骤如下:
在 .mm
文件中通过 IPacketObserver
类实现你自定义的数据加密算法。
class AgoraPacketObserver : public agora::IPacketObserver
{
public:
AgoraPacketObserver()
{
m_txAudioBuffer.resize(2048);
m_rxAudioBuffer.resize(2048);
m_txVideoBuffer.resize(2048);
m_rxVideoBuffer.resize(2048);
}
virtual bool onSendAudioPacket(Packet& packet) {
int i;
// 加密数据包
const unsigned char* p = packet.buffer;
const unsigned char* pe = packet.buffer+packet.size;
for (i = 0; p < pe && i < m_txAudioBuffer.size(); ++p, ++i)
{
m_txAudioBuffer[i] = *p ^ 0x55;
}
// 将加密后数据的缓存地址和缓存大小发回 SDK
packet.buffer = &m_txAudioBuffer[0];
packet.size = i;
return true;
}
virtual bool onSendVideoPacket(Packet& packet) {
int i;
// 加密数据包
const unsigned char* p = packet.buffer;
const unsigned char* pe = packet.buffer+packet.size;
for (i = 0; p < pe && i < m_txVideoBuffer.size(); ++p, ++i)
{
m_txVideoBuffer[i] = *p ^ 0x55;
}
// 将加密后数据的缓存地址和缓存大小发回 SDK
packet.buffer = &m_txVideoBuffer[0];
packet.size = i;
return true;
}
virtual bool onReceiveAudioPacket(Packet& packet) {
int i = 0;
// 解密数据包
const unsigned char* p = packet.buffer;
const unsigned char* pe = packet.buffer+packet.size;
for (i = 0; p < pe && i < m_rxAudioBuffer.size(); ++p, ++i)
{
m_rxAudioBuffer[i] = *p ^ 0x55;
}
// 将解密后数据的缓存地址和缓存大小发回 SDK
packet.buffer = &m_rxAudioBuffer[0];
packet.size = i;
return true;
}
virtual bool onReceiveVideoPacket(Packet& packet) {
int i = 0;
// 解密数据包
const unsigned char* p = packet.buffer;
const unsigned char* pe = packet.buffer+packet.size;
for (i = 0; p < pe && i < m_rxVideoBuffer.size(); ++p, ++i)
{
m_rxVideoBuffer[i] = *p ^ 0x55;
}
// 将解密后数据的缓存地址和缓存大小发回 SDK
packet.buffer = &m_rxVideoBuffer[0];
packet.size = i;
return true;
}
private:
// 发送音频数据 buffer
std::vector<unsigned char> m_txAudioBuffer;
// 发送视频数据 buffer
std::vector<unsigned char> m_txVideoBuffer;
// 接收音频数据 buffer
std::vector<unsigned char> m_rxAudioBuffer;
// 接收视频数据 buffer
std::vector<unsigned char> m_rxVideoBuffer;
};
在加入频道前,注册数据包观测器,在语音或视频数据包传输时接收事件。
// Swift
AgoraCustomEncryption.registerPacketProcessing(agoraKit)
在 .mm
文件中调用 registerPacketObserver
实现注册数据包观测器。
+ (void)registerPacketProcessing:(AgoraRtcEngineKit *)rtcEngineKit {
if (!rtcEngineKit) {
return;
}
// 获取 Native SDK 的 C++ 句柄
agora::rtc::IRtcEngine* rtc_engine = (agora::rtc::IRtcEngine*)rtcEngineKit.getNativeHandle;
// 注册数据包观测器
rtc_engine->registerPacketObserver(&s_packetObserver);
}
离开频道后,取消注册数据包观测器。
// Swift
AgoraCustomEncryption.deregisterPacketProcessing(agoraKit)
在 .mm
文件中调用 registerPacketObserver(NULL)
实现取消注册数据包观测器。
+ (void)deregisterPacketProcessing:(AgoraRtcEngineKit *)rtcEngineKit {
if (!rtcEngineKit) {
return;
}
// 获取 Native SDK 的 C++ 句柄
agora::rtc::IRtcEngine* rtc_engine = (agora::rtc::IRtcEngine*)rtcEngineKit.getNativeHandle;
// 取消注册数据包观测器
rtc_engine->registerPacketObserver(NULL);
}