跳到主要内容

自定义加密

在音视频通话场景中,您可以对媒体流进行自定义加密,以保障数据安全。

加密方式

自定义加密由开发者自行实现加解密逻辑,融云服务仅转发数据,不参与解密。该方式适用于对安全性有特殊要求的业务。

自定义加密限制

启用自定义加密后,将无法使用以下 RTC 服务端能力:云端录制云端截图内容审核云播放器

提示
  • 自定义加密要求发送端与接收端采用完全一致的加解密算法,否则会导致无法正常通话。
  • 由于数据量大且实时性要求高,建议在 C++ 层实现自定义加密算法以保证性能。
  • 任意加密方案都会对客户端、服务器造成额外的资源消耗,在低性能设备上可能影响体验。

实现步骤

步骤 1:发起呼叫时开启自定义加密

Java
// 开启加密
boolean isEncrypted = true;
RCCallPlusEncryption encryption = new RCCallPlusEncryption(isEncrypted);
RCCallPlusOption option = RCCallPlusOption.Builder.create()
.setCallPlusEncryption(encryption)
// 其他配置...
.build();

List<String> userIds = new ArrayList<>();
userIds.add(remoteUserId);
// 发起呼叫
RCCallPlusClient.getInstance().startCall(userIds, RCCallPlusType.PRIVATE, RCCallPlusMediaType.VIDEO, option);

步骤 2:配置 NDK 环境

如果您的 Android App 项目尚未使用 C++,请参考知识库文档配置 NDK 编译。

步骤 3:加载自定义加密 SO 库

Java
// SO 库名称需根据项目自定义
System.loadLibrary("custom_frame_crypto");

步骤 4:实现加解密逻辑

在 C++ 层实现 CustomAudioFrameEncryptorCustomAudioFrameDecryptor 以完成音频加解密:

  • 音频加密示例:
cpp
/**
* 自定义加密方法
* @param payload_data 加密前数据的起始地址
* @param payload_size 加密前数据的大小
* @param encrypted_frame 加密后的数据起始地址,融云SDK已申请内存,开发者无需重新申请
* @param bytes_written 加密后数据的大小
* @param mediastream_id 当前音频或视频流的唯一标识
* @param mediatype 媒体类型,0 为 "audio",1 为 "video"
* @return 0:成功;非 0:失败
*/
int CustomAudioFrameEncryptor::Encrypt(const uint8_t *payload_data, size_t payload_size,
uint8_t *encrypted_frame, size_t *bytes_written,
std::string mediastream_id, int mediatype) {
// 在此实现自定义音频加密算法;示例:按位取反
uint8_t fake_key_ = 0xff;
for (size_t i = 0; i < payload_size; i++) {
encrypted_frame[i] = payload_data[i] ^ fake_key_;
}
*bytes_written = payload_size;
return 0;
}

/**
* 计算加密后数据的长度
* @param frame_size 明文大小
* @param mediastream_id 当前音频或视频流的唯一标识
* @param mediatype 媒体类型,0 为 "audio",1 为 "video"
* @return 密文长度
*/
size_t CustomAudioFrameEncryptor::GetMaxCiphertextByteSize(size_t frame_size, std::string mediastream_id,
int mediatype) {
// 加密之后数据帧大小
return frame_size;
}
  • 音频解密示例:
cpp
/**
* 开发者定义解密方法
* @param encrypted_frame 解密前数据的起始地址
* @param encrypted_frame_size 解密前数据的大小
* @param frame 解密后的数据起始地址,融云SDK已申请内存,开发者无需重新申请
* @param bytes_written 解密后数据的大小
* @param mediastream_id 当前音频或视频流的唯一标识
* @param mediatype 媒体类型,0 为 "audio",1 为 "video"
* @return 0:成功;非 0:失败
*/
int CustomAudioFrameDecryptor::Decrypt(const uint8_t *encrypted_frame, size_t encrypted_frame_size,
uint8_t *frame, size_t *bytes_written,
std::string mediastream_id, int mediatype) {
// 在此处实现自己的解密算法,示例为按位取反
uint8_t fake_key_ = 0xff;
for (size_t i = 0; i < encrypted_frame_size; i++) {
frame[i] = encrypted_frame[i] ^ fake_key_;
}
*bytes_written = encrypted_frame_size;
return 0;
}

/**
* 计算解密后数据的长度
* @param frame_size 密文大小
* @param mediastream_id 当前音频或视频流的唯一标识
* @param mediatype 媒体类型,0 为 "audio",1 为 "video"
* @return 明文长度
*/
size_t CustomAudioFrameDecryptor::GetMaxPlaintextByteSize(size_t frame_size, std::string mediastream_id,
int mediatype) {
// 解密之后帧大小
return frame_size;
}
提示

视频加解密方式类似,需要在 C++ 层实现 CustomVideoFrameEncryptor 和 CustomVideoFrameDecryptor 类即可。