如何在外部采用AES-128对HLS的TS流进行加密?
下面介绍了如何在Wowza Stream Engine 4外部采用AES-128对HLS流媒体中的TS流进行加密(包括直播业务和VOD点播业务)。
关于Http Live Streaming的详细技术规范,请参考互联网工程小组的
draft-pantos-http-live-streaming-05 specification。
在外部采用AES-128加密的意思是:播放器测获取用于解密的密码时的URL是由wowza media server之外的WEB服务提供的。另外,还有一个采用Wowza Media Server内部机制的方式,在这个方式下,所有的TS流和用于解密的密钥都由Wowza Media Server负责提供给客户端的播放器。
要了解更多关于如何在内部采用AES-128对HLS的TS流进行加密,请阅读
如何在Wowza内部采用AES-128对HLS的TS流进行加密。
- 按照Wowza Streaming Engine 4快速上手中的介绍,配置一个Wowza Media Server的应用。此外还必须有一个可以访问的web服务器。
-
配置一个AES-128密钥用于对ts流进行加密。你可以采用在Wowza Media Server的[install-dir]/bin文件夹找到genkey工具:
- 打开命令行窗口并切换到[install-dir]/bin目录下
- 输入下面的命令:
Windows:
genkey.bat iphone [stream-name] [key-url]
Linux:
./genkey.sh iphone [stream-name] [key-url]
其中[stream-name] 是将要被加密的流的StreamName,[key-url]是播放器获取解密密钥的URL。
这个命令将生成一个名为[stream-name].key的文件。 下面是一个命令行的例子:
genkey.bat iphone myStream https://mycompany.com/myStream.php
这个命令会输出如下信息:
key: B9A954F22ACD093BDEB80622EC7155BB
url: https://mycompany.com/myStream.php
Key file generated: myStream.key
Copy file to: [install-dir]/keys
- 将这个命令所生成的文件拷贝到[install-dir]/keys文件夹下。在下面,你会看到如何为每一个应用建立一个keys文件夹。
-
重新启动Wowza Stream Engine 4,然后向服务器推送(或者是拉)一个实时流。当直播流进入服务器, 你会看到下面的log信息:
Encrypt iPhone stream: key: *[last-8-characters-of-key]
Encrypt iPhone stream: url: [key-url]
这说明这个流正在被正确的加密。
关于[key-url]
这个
[key-url]是播放器获取解密密码时用的URL。你也可以在这个环节来控制哪些用户可以观看你的HLS流。如果这个URL请求返回
403状态码,那么播放器就无法获得密钥进而无法解密和播放。如果返回了密钥,这个流就可以被解密。
我们建议这个采用Https协议来对URL进行保护,这样这个密钥就不会以明文的形式被泄漏到Internet上。密钥信息必须是16个8进制的,并且要在http的header信息中设定内容格式为二进制数据流:
Content-Type: binary/octet-stream
Pragma: no-cache
下面的例子展现如何使用常见的WEB应用程序向播放器提供获取密钥的过程,包括
ASP.NET,
JSP以及
PHP。在这些例子中,密钥为
DE51A7254739C0EDF1DCE13BBB308FF0。请用上面生成的密钥替换这个值:
ASP.NET 的例子
<%@ Page Language="C#" %>
<%
Boolean isValid = true;
if (!isValid)
{
Response.Status = "403 Forbidden";
}
else
{
Response.AddHeader("Content-Type", "binary/octet-stream");
Response.AddHeader("Pragma", "nocache");
String keyStr = "DE51A7254739C0EDF1DCE13BBB308FF0";
int len = keyStr.Length/2;
byte[] keyBuffer = new byte[len];
for (int i=0;i<len;i++)
keyBuffer[i] = Convert.ToByte(keyStr.Substring(i*2, 2), 16);
Response.BinaryWrite(keyBuffer);
Response.Flush();
Response.End();
}
%>
JSP 的例子
<%@ page import="java.util.*,java.io.*" %>
<%
boolean isValid = true;
if (!isValid)
{
response.setStatus( 403 );
}
else
{
response.setHeader("Content-Type", "binary/octet-stream");
response.setHeader("Pragma", "no-cache");
String keyStr = "DE51A7254739C0EDF1DCE13BBB308FF0";
int len = keyStr.length()/2;
byte[] keyBuffer = new byte[len];
for (int i=0;i<len;i++)
keyBuffer[i] = (byte)Integer.parseInt(keyStr.substring(i*2, (i*2)+2), 16);
OutputStream outs = response.getOutputStream();
outs.write(keyBuffer);
outs.flush();
}
%>
PHP 的例子
<?php
function hex2bin($h)
{
if (!is_string($h))
return null;
$r = '';
for ($a=0;$a<strlen($h);$a+=2)
{
$r .= chr(hexdec($h{$a}.$h{($a+1)}));
}
return $r;
}
$isValid = true;
if (! $isValid)
{
header('HTTP/1.0 403 Forbidden');
}
else
{
header('Content-Type: binary/octet-stream');
header('Pragma: no-cache');
echo hex2bin('DE51A7254739C0EDF1DCE13BBB308FF0');
exit(); // this is needed to ensure cr/lf is not added to output
}
?>
上面每一个例子都包含了一个Boolean类型的变量
isValid, 默认值是
true。你可以修改这个例子,用于对用户进行验证。如果非法的用户访问了这个WEB资源,你可以将
isValid设置为
false来阻止用户得到密钥。
这些例子代码是可以自由修改和分发的,没有任何限制。
[install-dir]
Windows (default): %PROGRAMFILES%\Wowza Media Systems\Wowza Media Server [version]
Mac OS X: /Library/WowzaMediaServer
Linux: /usr/local/WowzaMediaServer
注意: 默认情况下,所有的应用都被配置为使用
keys 文件夹,但这样会引起stream name冲突,要为每一个应用配置一个
keys文件夹,请用文本编辑器打开
[install-dir]/conf/[application]/Application.xml文件,并修改
Streams/KeyDir 属性的值。如果你将它设置为空字符串(长度为0), 它将默认使用:
[install-dir]/applications/[application]/keys/[appInstance]
注意: 在Wowza Media Server 2 (preview 7) 及以后版本,在playlist.m3u8的URL后面可以添加任意的查询参数,并且一个wowza session ID 将会作为参数传递进入获取密钥的URL。
例如,你可以使用下面的URL请求播放一个HLS流:
http://[wowza-ip-address]:1935/live/myStream/playlist.m3u8?userid=12345
同时假定获取密钥的URL定义如下:
https://mycompany.com/myStream.php?keyinfo=securekey
那么,请求密钥的URL将将包括下面的查询参数:
https://mycompany.com/myStream.php?keyinfo=securekey&userid=12345&wowzasessionid=345234