概述
视频加密是对视频内容保护的一种手段。对视频中的内容进行加密,可有效防止视频泄露和盗链问题。目前,视频加密广泛用于在线教育及财经等领域。阿里云视频点播目前支持的加密方式有 "阿里云私有加密"和"HLS 标准加密"。
其中私有加密是点播服务完全托管的,用户无需自己搭建解密接口,实际播放的时候必须使用阿里云播放器通过VideoId+播放凭证的方式去播放。HLS标准加密依赖于KMS密钥管理服务,需要用户自己搭建解密接口服务,支持直接使用URL方式播放,并且可以使用第三方播放器来完成播放。
目前视频点播官网帮助中心有提供HLS标准加密的开发文档,具体可以点击这里阅读。本文在此开发文档的基础上,补充说明一些开发者经常遇到的问题,以便更快速的定位解决问题。
SubmitTranscodeJobs提交转码作业错误
1. KeyNotFound
出现这种错误提示一般都是使用的加密Service Key 和视频不在同一个区域,例如:华东2的视频,必须使用华东2的KMS生成秘钥。
2. NoSuchResource
出现这种错误通常代表用户的某种的资源缺失,可以结合Error Message进行排查。
(1)can not find cross service token
表示用户没有通过RAM授权点播操作用户的KMS导致,需要用户使用RAM服务给视频点播授权访问业务方秘钥管理服务(KMS)的权限,请参考HLS标准加密开发文档的第二步,点击 RAM授权 给视频点播授权,如下图所示:
特别注意,授权的AliyunVODDefaultRole角色是一个系统角色,该角色默认就授权了AliyunVODRolePolicy这个系统策略,视频点播服务会默认使用此角色来访问账号下其他云产品中的资源,请勿去修改或者删除此角色下的策略。如果误操作修改了错误的策略,可以考虑删除次角色以后,点击上面描述的链接重新去授权下这个系统角色。
(2)can not find customer encrypt master key
表示在用户对应区域的KMS中没有拿到响应的加密Service key,请确保已经开通Service key,并且到KMS控制台对应区域拿到对应的Service key信息(描述信息是acs/vod)。
(3)can not find customer encrypt info
表示用户传递的密文秘钥(也就是Ciphertext值)不是使用KMS生成,或者秘钥生成和视频存储不在同一个区域,需要用户在视频相应区域生成加密秘钥。
(4)can not find customer plaintext
表示用户生成的秘钥解密不到明文秘钥,需要用户使用GenerateDataKey生成加密秘钥。
(5)The specified resource Template does not exist
表示视频对应区域的转码模板数据不存在,需要检查SubmitTranscodeJobs接口传入的TemplateGroupId参数是否正确。
转码后的视频文件未加密
生成的文件未加密,一般都是由于转码模板在设置的时候没有选择HLS加密选项(标准加密、私有加密必须要勾选),请在点播控制台设置转码模板处,高级参数里开启"视频加密"选项,并选择加密方式为"私有加密",参考下图
注意:无论是"阿里云私有加密"还是"HLS标准加密",都必须开启视频加密,并选择加密方式为私有加密。
加密转码失败
视频标准加密失败,一般都是由于用户在调用GenerateDataKey生成的秘钥是非AES_128位的,或者秘钥使用自定义字符串生成。这里在调用KMS的GenerateDataKey接口时,传递的KeySpec参数必须是AES_128。
解密失败无法播放
通常HLS标准加密成功,说明秘钥应该是没问题的,那么解密失败通常是由于解密接口服务本身就异常或者解密接口返回的内容不对导致。
1. DecryptKeyUri传递的地址无法访问
SubmitTranscodeJobs接口文档里EncryptConfig参数里的DecryptKeyUri的示例是
http://decrypt.demo.com?CipherText=ZjJmZGViNzUtZWY1Mi00Y2RlLTk3MTMt
这里要特别注意,这个decrypt.demo.com只是一个示例的值,实际是必须替换成用户搭建的解密接口服务器的域名,并且需要公网可达,总之必须保证播放器能成功请求到这个地址,并且能正常请求到解密接口逻辑里。
2. 浏览器Block
浏览器要求在HTTPS的页面里加载的资源必须也是HTTPS的,如果传递的DecryptKeyUri是HTTP的,但是播放页面却是HTTPS的,会导致Web端的播放器因为浏览器安全原因导致无法正常请求解密接口服务器地址,导致无法正常解密,这种情况需要设置DecryptKeyUri为HTTPS的地址(需要对解密服务器域名配置HTTPS证书)。如下图,可以在浏览器开发者工具的Console里看到Mixed Content的错误,就是这个原因造成的
另外,Console下如果有No 'Access-Control-Allow-Origin'的错误,则说明是跨域问题导致的,需要对解密服务器域名配置跨域,返回Access-Control-Allow-Origin这个Http头。
3. 解密接口返回的明文密钥不对
很多用户可能会把Decrypt接口返回的json串直接返回给播放器,或者把接口返回的Plaintext直接返回给播放器,这是不对的。解密服务只需要把KMS的Decrypt接口返回的Plaintext 做base64 decode以后返回给播放器就行了,最终返回给播放器的是二进制数据。如下图所示,在Network下看解密接口的Response信息,应该是一个乱码的内容,因为二进制数据浏览器无法正常解码
下图展示了一个正常的过程,我们可以从m3u8文件里拿到解密接口地址,然后请求解密接口地址拿到这个接口返回的密钥,正常情况这个返回的密钥是Plaintext做base64 decode以后的值,是二进制数据,可以用二进制解析工具查看,并且该文件是16字节的。
MtsHlsUriToken参数重写失效
如果需要对播放用户进行自定义鉴权,则需要通过MtsHlsUriToken参数来传递令牌,解密接口服务对令牌进行鉴权。可以到点播控制台域名管理界面开启,参考HLS标准加密改写。
如果域名开启了URL鉴权,则MtsHlsUriToken参数重写功能不生效,目前MtsHlsUriToken参数重写和鉴权功能是互斥的。
解密示例代码
关于HLS标准加密安全播放的实现。案例描述了解密的实现逻辑,并提供了Java的示例。本文以下再提供一份PHP的示例供参考
<?php
/*
视频解密接口
*/
include_once 'aliyun-php-sdk-core/Config.php';
use Kms\Request\V20160120 as Kms;
// 使用账号AK初始化VOD客户端
$iClientProfile = DefaultProfile::getProfile("cn-shanghai", "<AccessKeyId>", "<AccessKeySecret>");
function Decrypt($client,$CiphertextBlob) {
try {
//将前台加密视频传来的Ciphertext进行解密
$request = new kms\DecryptRequest();
$request->setCiphertextBlob($CiphertextBlob);
$response = $client->getAcsResponse($request);
return base64_decode($response->Plaintext);
} catch (Exception $e) {
print $e->getMessage()."\n";
return null;
}
}
try {
$CiphertextBlob=$_GET['CipherText'];
if($CiphertextBlob!="")
{
$client = new DefaultAcsClient($iClientProfile);
$result = Decrypt($client,$CiphertextBlob);
echo $result;
}else{
print '视频解密ID未传输,请刷新页面重试';
}
} catch (Exception $e) {
print $e->getMessage()."\n";
}