Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

流媒体加密 #10

Open
gwuhaolin opened this issue Aug 1, 2017 · 17 comments
Open

流媒体加密 #10

gwuhaolin opened this issue Aug 1, 2017 · 17 comments

Comments

@gwuhaolin
Copy link
Owner

gwuhaolin commented Aug 1, 2017

本文只讨论应用于浏览器环境的流媒体协议的加密

为什么要加密视频

付费观看视频的模式是很多平台的核心业务,如果视频被录制并非法传播,付费业务将受到严重威胁。因此对视频服务进行加密的技术变得尤为重要。

本文所指的视频加密是为了让要保护的视频不能轻易被下载,即使下载到了也是加密后的内容,其它人解开加密后的内容需要付出非常大的代价。

无法做到严格的让要保护的视频不被录制,原因在于你需要在客户端播放出视频的原内容,解密的流程在客户端的话不法分子就能模拟整个流程,最保守也能用屏幕录制软件录制到视频的原内容(可以通过加水印的方法缓解下)。我们的目标是让他获取原内容的代价更大。

常见视频加密技术

视频加密技术分为两种:

  1. 防盗链:通过验证的用户才能访问到没有加密的视频内容,这种方案存在视频很容易就被下载的风险,严格来说这不属于加密。这种方式其实是资源访问授权,它实现起来简单。
  2. 加密视频本身:通过对称加密算法加密视频内容本身,用户获得加密后的视频内容,通过验证的用户可以获取解密视频的密钥,在客户端解密后播放。这种方式实现起来流程复杂会带来更多的计算量。

一般结合这两种技术一起用,第1种技术很成熟也有很多教程就不再复述,本文主要介绍第2种加密技术。

流媒体加密技术原理

看视频分为两种,看点播和看录播。
要看点播可以通过下载完整个视频后再看,或者通过流媒体边下边看。
看直播只能通过流媒体看最新的画面。

加密整个视频的技术很简单,把视频看成一个文件采用加密文件的技术,这种技术太多就不介绍了。
加密流媒体的技术很少,也很难找到学习资料,本文主要介绍流媒体加密技术。

常见的应用与浏览器播放的流媒体传输协议有:

  • HLS:Apple 推出的基于 HTTP 协议的 MP4 分片传输协议,可用于点播和直播场景。每下载一个分片都需要发生一次 HTTP 请求,所以严格来说 HLS 不能称为流媒体传输协议。
  • HTTP-FLV:基于 HTTP 长连接的 FLV 分块 tag 传输协议,可用于点播和直播场景。
  • RTMP:基于 TCP 的 FLV 分块 message 传输协议,用于 Flash 客户端。

流媒体加密原理

可以看出一个规律这些流媒体传输协议都必须把视频流拆分成连续的小块之后再被传送,只不过分块的大小和视频容器的格式不一样而已。

流媒体加密技术的核心就在于对这每一小块视频分别使用对称加密算法,在服务端加密客户端解密,通过权限验证的用户才能拿到解密一小块视频的密钥。

为什么不用 HTTPS 加密

可能有人会问为什么不用 HTTPS 加密?原因是 HTTPS 在网络传输层进行非对称加密,目的是为了防止中间人窃听劫持,任何人都可以和我们的服务器建立 HTTPS 链接获取到原数据。而视频加密的目的不是为了防止有中间人窃听我们的视频数据,而是要让视频数据本身被加密。

为什么选择对称加密

现代成熟的加密技术分为对称加密算法和公钥密码算法(非对称加密)。之所以选择对称加密是因为流媒体要求很强的实时性,数据量又很大。公钥密码算法的计算都比较复杂,效率较低,适合对少量数据进行加密。对称加密效率相对较高,所以流媒体加密首选对称加密。例如在 SSH 登入的时候会先通过公钥密码算法传输一个密钥,再用这个密钥用作对称加密算法的密钥,在数据传输过程中使用对称加密算法来提示数据传输效率。

HLS 加密

HLS 是目前最成熟的支持流媒体加密的能应用在浏览器里的流媒体传输协议,HLS 原生支持加密,下面来详细介绍它。

在介绍如何加密 HLS 先了解下 HLS 相比于其它流媒体传输协议的优缺点。
优点在于:

  • 建立在 HTTP 之上,使用简单,接入代价小。
  • 分片技术有利于 CDN 加速技术的实施。
  • 部分浏览器原生支持,支持点播和录播。

缺点在于:

  • 用作直播时延迟太大。
  • 移动端支持还好,PC端只有 Safari 原生支持。

HLS 加密原理

HLS 由两部分构成,一个是 .m3u8 文件,一个是 .ts 视频文件(TS 是视频文件格式的一种)。整个过程是,浏览器会首先去请求 .m3u8 的索引文件,然后解析 m3u8,找出对应的 .ts 文件链接,并开始下载。
hls

m3u8 文件是一个文本文件,在开启 HLS 加密时,内容大致如下:

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:26
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.do?k=1"
#EXTINF:9.901,
http://media.example.com/segment26.ts
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.do?k=2"
#EXTINF:9.501,
http://media.example.com/segment28.ts

这个文件描述了每个 TS 分片的 URL ,但这些分片都是加密后的内容,要还原出原内容需要从

#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.do?k=1"

中解析出获取解密密钥的URL https://priv.example.com/key.do 和对称加密算法 AES-128
获取到密钥后再在客户端解密出原内容。
可以看出启用 HLS 加密后会多出更多的事情:

  • 针对每个 TS 需要去请求获取密钥。
  • 需要多提供一个给客户端获取密钥的鉴权服务。
  • 针对每个 TS 需要去执行对称加密的解密计算。

这会带来更多的网络请求和计算量,可能会对延迟和性能造成一定的不良影响。

HLS 加密实战

支持 HLS 的客户端都原生支持加密,所以要开启 HLS 加密你只需要修改你的服务端:

  • 修改 HLS 视频服务,对 TS 加密,往 m3u8 中加入 EXT-X-KEY 字段。
  • 提供给客户端获取密钥的鉴权服务,即上面的 https://priv.example.com/key.do?k=1 所指向的服务。

目前大多数云服务都支持 HLS 加密服务,如果你想直接搭建 HLS 加密服务可以使用 nginx-rtmp-module

HLS 兼容方案

目前 HLS 存在兼容性问题:

  • 针对桌面端低版本浏览器例如 IE,可以使用 Flash 技术来播放 HLS ,详细使用见开源项目 flashls
  • 针对非Safari高版本浏览器例如 Chrome ,可以使用 Media Source Extensions API 去实现播放 HLS,详细使用见开源项目 hls.js
  • 针对即不原生支持 HLS又不支持 Media Source Extensions 也不支持 Flash 的浏览器,常见于部分低版本移动端浏览器,我也找不到什么好办法。

flashls 和 hls.js 都支持 HLS 加密技术。

破解 HLS 加密

有加密就有破解,在明白 HLS 加密原理后,你想过如何去破解它吗?先定义下破解成功是指:获取到视频加密前的完整原文件。我想到的方法是:

  1. 先付费买一个可正常观看受保护视频的账号。
  2. 用抓包工具抓下所有网络请求(可以筛选下限制到只保存 HLS 和 获取key 的请求,防止保存太多垃圾数据)。
  3. 第2步保存下来了加密后的 TS 分片和加密分片所需要的密钥。
  4. 写一个脚本以 m3u8 为索引一一解密出加密后的 TS 分片的原文件,再把 TS 拼接成完整的视频原文件。

似乎破解的难度也不会很复杂。

总结

目前流媒体加密技术还不成熟,除了 HLS 协议提供了方便成熟的方案外,其它协议的加密技术还不成熟。

RTMP 协议提供了一个变种版 RTMPE 可以加密流媒体,原理和 HLS 加密类似,但是我还找不到合适的服务端去支持 RTMPE 协议。

阅读原文

@orangemi
Copy link

orangemi commented Aug 2, 2017

点赞了,我之前对HLS稍有研究,也没有找到相应成熟的解决方案,但我想方向应该是:

  1. 使用https对流的传输进行加密
  2. 在对流的请求加以验证,可以用nginx的x-accel方式,现在应该有很多资源是用这样方式加权验证的。

对于rtmp,网上有一些rtmps协议的内容,但我个人更倾向使用hls协议

@tixo
Copy link

tixo commented Aug 3, 2017

写的真不错。 有一点没搞懂

目的是为了防止中间人窃听劫持,任何人都可以和我们的服务器建立 HTTPS 链接获取到原数据

如您所说,为什么不进行鉴权,以避免“任何人”都能获取你的视频。 反而要大费周张在视频数据本身上加密?

@gwuhaolin
Copy link
Owner Author

gwuhaolin commented Aug 3, 2017

@orangemi @tixo HTTPS 是一套公开的公钥加密机制,HTTPS 是为了保证传输过程中的数据安全。

鉴权是为了控制用户能防止资源的权限。

加密视频数据本身是为了增加获取到视频原数据的难度

一般我们需要采用 HTTPS+鉴权+加密视频本身 这三种方法一起上来给破解者带来最大的阻力。

@longyiyiyu
Copy link

好文,赞!@tixo 原文有说,加密视频本身是防止正常用户下载视频然后传播

@jhaoheng
Copy link

您好,看了您的文章,有疑惑的地方在
既然有解密,肯定有加密
那该如何针对 ts 档案,加密?

streaming -> �取得 ts file -> 加密 ts file -> 储存 ts file

@Tinywan
Copy link

Tinywan commented May 28, 2018

HLS 加密

直播

  • 使用https对流的传输进行加密
  • 对流的请求地址进行鉴权:控制用户访问资源的权限
  • 对获取解密密钥请求加以验证
  • 防盗链,播放连接地址是明文的,别人拿到播放地址也播放不了视频

点播

  • 加密视频源本身:增加获取到视频原数据的难度
  • 使用https传输:保证传输过程中的数据安全
  • 对获取解密密钥请求加以验证:如:是否为白名单域名
  • 防盗链,播放连接地址是明文的,别人拿到播放地址也播放不了视频

@RockyQu
Copy link

RockyQu commented Oct 16, 2018

加密是否必须要用服务器支持?

@echokk11
Copy link

echokk11 commented Jan 2, 2019

如果使用ffmpeg加密的话,就是命令行指令.

# 生成加密key
openssl rand  16 > enc.key

# 生成IV
openssl rand -hex 16

# 新建enc.keyinfo,内容如下
http://localhost/video/enc.key
enc.key
191029d9c2d4e9051a8a5deb2f7f5c04

# 以加密hls.mkv为例
ffmpeg -i hls.mkv \
-codec:v libx264 \
-codec:a mp3 \
-map 0 \
-s 640x360 \
-hls_time 10 \
-hls_list_size 0 \
-hls_allow_cache 1 \
-hls_base_url http://localhost/videos/ \
-hls_segment_filename out%03d.ts \
-hls_key_info_file enc.keyinfo \
playlist.m3u8

部分参数解析

  • hls_key_info_file指定keyinfo
  • hls_base_url生成ts文件的前缀
  • hls_segment_filename输出文件的格式

@y888
Copy link

y888 commented Jan 21, 2019

所以myfreecams.com 的直播一直是那种加密?
去年在m.myfreecams还能找到.m3u8 文件,现在变成一段段.m4s,现在已经不会了 。

@oliyg
Copy link

oliyg commented Jan 25, 2019

HLS 容易实现加密 还是因为它本质上是个伪流协议

@michaelzs1994
Copy link

求解密方法

1 similar comment
@whapply
Copy link

whapply commented Oct 10, 2019

求解密方法

@TongDaDa
Copy link

YouTube 的视频流就是加密的

@michaelzs1994
Copy link

YouTube 的视频流就是加密的

没有吧,不是youtube-dl直接下吗

@sansui-orz
Copy link

解密完全不需要key,由于目前hls解密通常都是通过应用自身去解的,这也就意味着解密后的数据会直接暴露在代码逻辑里。直接抓取解密后的视频数据,回传自己的服务器,再在服务器进行合并操作,就是一个可播放的完整视频了,至少在web是这样,客户端想来也只是难度加大了而已。

@MacrazdHao
Copy link

bilibili的加密方式是怎么样的?我看他们的video的视频源就是一串简单的域名+一串加密过的字符

@matisse510
Copy link

matisse510 commented Jul 28, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests