多协议、性能稳定、丰富API的流媒体服务器软件
如何在外部采用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流进行加密

  1. 按照Wowza Streaming Engine 4快速上手中的介绍,配置一个Wowza Media Server的应用。此外还必须有一个可以访问的web服务器。

  2. 配置一个AES-128密钥用于对ts流进行加密。你可以采用在Wowza Media Server的[install-dir]/bin文件夹找到genkey工具:

    1. 打开命令行窗口并切换到[install-dir]/bin目录下

    2. 输入下面的命令:

      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
    3. 将这个命令所生成的文件拷贝到[install-dir]/keys文件夹下。在下面,你会看到如何为每一个应用建立一个keys文件夹。


  3. 重新启动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