修改ffmpeg实现https-flv内容加密

目录

[1 前言](#1 前言)

[2 ffmpeg源码修改](#2 ffmpeg源码修改)

[2.1 增加头文件](#2.1 增加头文件)

[2.2 http上下文增加解密密钥和AVAESCTR结构体](#2.2 http上下文增加解密密钥和AVAESCTR结构体)

[2.3 aes解密上下文初始化](#2.3 aes解密上下文初始化)

[2.4 对http数据部分解密](#2.4 对http数据部分解密)

[2.5 http关闭时清理资源](#2.5 http关闭时清理资源)

[3 ffmpeg使用](#3 ffmpeg使用)


1 前言

当前视频拉流已经通过URL鉴权方式来对访客身份进行识别和过滤,但仍然存在URL泄露的情况,需要通过内容加密来保证直播流只能在特定的播放器进行查看,这样即使URL泄露也没有影响。

参考了阿里云直播加密方案后我们的内容加密架构图如上,其中播放器基于ffmpeg开发,使用的是https-flv协议,其中对称加密使用的是aes加密ctr模式,在之前进行录像加密时需要实现从任意字节任意长度进行加解密,因此之前已经封装了一套基于openssl的加解密函数(使用AES CTR模式实现任意位置数据加解密_openssl aes ctr-CSDN博客),但直播内容加密是从前向后的有序流式传输,不存在seek操作,因此这个场景较为简单。

在修改ffmpeg代码时发现ffmpeg本身就封装了一套aes加解密函数,可以直接拿来使用,在此进行记录。

2 ffmpeg源码修改

2.1 增加头文件

https-flv的数据解密既可以放到协议层,也可以放到解封装层,经过比较还是放到协议层修改比较方便,对应的文件就是http.c。

ffmpeg对aes加解密的头文件是aes_ctr.h,因此需要在http.c文件增加aes_ctr.h头文件包含。

cpp 复制代码
#include "libavutil/aes_ctr.h"

2.2 http上下文增加解密密钥和AVAESCTR结构体

http协议对应的内部上下文为HTTPContext结构体,进行解密操作首先需要在HTTPContext结构体中包含解密密钥和对应解密的AESCTR结构体。

cpp 复制代码
typedef struct HTTPContext {
    ......
    char *key; //解密密钥
    struct AVAESCTR *aes_ctr; //aes解密上下文
} HTTPContext;

另外我们还为http协议增加了配置项用来设置解密密钥

cpp 复制代码
static const AVOption options[] = {
    ......
    {"key", "The key used to crpty http payload", OFFSET(key), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D },
    { NULL }
};

2.3 aes解密上下文初始化

在http_open函数中进行aes解密上下文初始化,在这里我们通过是否设置key来同时兼容需要解密和不需要解密两种场景。

cpp 复制代码
static int http_open(......) {
    ......
    if (s->key) {
        s->aes_ctr = av_aes_ctr_alloc();
        if (!s->aes_ctr) {
            return AVERROR(ENOMEM);
        }
        ret = av_aes_ctr_init(s->aes_ctr, s->key);
        if (ret < 0) {
            return ret;
        }
        av_aes_ctr_set_iv(s->aes_ctr, s->key); /*iv策略需要与服务端一致*/
    }
    if (s->listen) {
    ......
}

2.4 对http数据部分解密

在http_read函数中对收到的数据部分进行解密

cpp 复制代码
static int http_read(......) {
    ......
    if (size > 0 && s->key) {
        av_aes_ctr_crypt(s->aes_ctr, buf, buf, size);
    }
}

2.5 http关闭时清理资源

在http_close时进行相应的资源清理

cpp 复制代码
static int http_close(......) {
    ......
    if (s->aes_ctr) {
        av_aes_ctr_free(s->aes_ctr);
    }
    return ret;
}

3 ffmpeg使用

上面的修改完成后就就可以编译得到可执行程序和库文件,下面演示使用ffmpeg获取内容加密的直播流信息,假设密钥为"0123456789abcdef"

cpp 复制代码
ffmpeg -f flv -key "0123456789abcdef"-i https://192.168.1.100:8080/live/stream.flv
相关推荐
IPdodo_2 小时前
跨境 API 调用不稳定怎么办:出口、超时重试与链路监控的实践
网络·python·网络协议
szephyr9 小时前
HTTPS 证书申请与自动续期:acme.sh + Let‘s Encrypt 完整记录
nginx·https·acme.sh·证书续期
程序员老陆11 小时前
WHIP 与 WHEP:WebRTC 直播的标准化入口与出口
ffmpeg·音视频·webrtc·whip·whep
那年窗外下的雪.16 小时前
AIDC 学习日志|第 27 天|EVPN 多归属收敛时间线与 Leaf2 接管验证
网络协议·学习·http·tcpdump
j7~16 小时前
【Linux】三十八.C++ 手写 HTTP 服务器:裸 socket + fork 多进程,从 HTTP 报文解析到浏览器打开网页
linux·网络·网络协议·学习·http·网络编程
Lsetea17 小时前
部署证书后提示“证书名称与输入不匹配”:Safari 报错的三层排查
nginx·https·safari·ssl证书·openssl
小则又沐风a17 小时前
深入理解TCP协议----滑动窗口,流量控制
linux·网络协议·tcp
captain3761 天前
网络原理(9)-数据链路层
java·网络协议·java-ee
yi碗汤园1 天前
MQTT消息队列遥测传输协议
网络·网络协议·unity
花间相见1 天前
【后端开发|网络编程】—— 五种实时通信方案全解析:短轮询、长轮询、SSE、MQTT、WebSocket
后端·网络协议