FFmpeg 4.0.2 DRM保护-HLS加密aes-128-cbc

http://ffmpeg.org/ffmpeg-all.html#hls-3

21.13 hls

方式一: hls_key_info_file key_info_file

加密

$ catdemo.sh

#!/bin/sh

BASE_URL=$

opensslrand16> file.key

echo$BASE_URL/file.key > file.keyinfo

echofile.key >> file.keyinfo

echo$(openssl rand -hex 16)>> file.keyinfo

exportLD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH

./bin/ffmpeg-flavfi-re-itestsrc-c:v h264-hls_flagsdelete_segments \

-hls_key_info_filefile.keyinfo out.m3u8

$

解密

方式二

-hls_enc enc

Enable (1) or disable (0) the AES128 encryption. When enabled every segment generated is encrypted and the encryption key is saved as playlist name.key.

-hls_enc_key key

Hex-coded 16byte key to encrypt the segments, by default it is randomly generated.

-hls_enc_key_url keyurl

If set, keyurl is prepended instead of baseurl to the key filename in the playlist.

Fmpeg-n4.0.2/libavformat/hlsenc.c

{"hls_enc_key_url","url to access the key to decrypt the segments",

-hls_enc_iv iv

Hex-coded 16byte initialization vector for every segment instead of the autogenerated ones.

Fmpeg-n4.0.2/libavformat/hlsenc.c

{"hls_enc_key_url","url to access the key to decrypt the segments",

#1.没有指定 -hls_enc_key_url 时,在当前目录下产生一个 out.m3u8.key 的文件为 密钥

exportLD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH

./bin/ffmpeg-flavfi-re-itestsrc-c:v h264-hls_flagsdelete_segments \

-hls_enc1-hls_enc_key"123456890abcdef"-hls_enc_iv"1122334455aabbcc"out.m3u8

$catout.m3u8

#EXTM3U

#EXT-X-VERSION:3

#EXT-X-TARGETDURATION:9

#EXT-X-MEDIA-SEQUENCE:0

#EXT-X-KEY:METHOD=AES-128,URI="out.m3u8.key",IV=0x31313232333334343535616162626363

#EXTINF:9.360000,

out0.ts

#EXT-X-ENDLIST

#解密,密钥 out.m3u8.key

strkey=$(hexdump -v -e '16/1 "%02x"' out.m3u8.key)

#iv=$(awk 'NR==3' file.keyinfo )

iv=31313232333334343535616162626363

opensslaes-128-cbc-d-inout27.ts-outout27_decrypto.ts-nosalt-iv$iv-K$strkey

#2. 指定了hls_enc_key_url ,ffmpeg 通过 http 1.1协议 发送16字节的密钥 (Transfer-Encoding: chunked)

$exportLD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH

$./bin/ffmpeg-flavfi-re-itestsrc-c:v h264-hls_flagsdelete_segments-hls_enc1-hls_enc_key"123456890abcdef"-hls_enc_key_url"http://127.0.0.1:8000"-hls_enc_iv"1122334455aabbcc"out.m3u8

[fanshuang@zhifudev01v python]$ pythonpost.py

('127.0.0.1',49950)

POST

/

HTTP/1.1

Transfer-Encoding: chunked

User-Agent: Lavf/58.12.100

Accept: */*

Connection: close

Host:127.0.0.1:8000

Icy-MetaData:1

begin http1.1 chunked ..........

chunk-size hex: 0X10

, need recv16bytes

chunk-data:123456890abcdef

('str_chunk_size_hex:[\r\n] , ValueError:', ValueError("invalid literal for int() with base 16: ''",))

begin http1.1 end ..........

127.0.0.1--[11/Nov/201814:56:03]"POST / HTTP/1.1"200-

$$catpost.py

#coding=utf-8

from BaseHTTPServer import BaseHTTPRequestHandler

import cgi

class PostHandler(BaseHTTPRequestHandler):

def chunked_proc(self):

print'begin http1.1 chunked .......... \n'

str_chunk_size_hex=self.rfile.readline(65537)

len=int(str_chunk_size_hex.upper(),16)

whilelen >:

print"chunk-size hex: 0X"+str_chunk_size_hex+', need recv '+str(len)+' bytes \n'

print"chunk-data:"+self.rfile.readline(len)

str_chunk_size_hex=self.rfile.readline(65537)

try:

len=int(str_chunk_size_hex,16)

except ValueError as e:

len=

print('str_chunk_size_hex:['+str_chunk_size_hex+']'+' , ValueError:',e)

print'begin http1.1 end .......... \n'

def do_POST(self):

print self.client_address

print self.server

print self.command

print self.path

print self.request_version

print self.headers

print self.rfile

ifself.headers['Transfer-Encoding']=='chunked':

self.chunked_proc()

#self.send_header('Transfer-Encoding', 'chunked')

#self.send_header('Connection', 'keepalive')

self.send_response(200)

self.end_headers()

#print self.responses

return

def StartServer():

from BaseHTTPServer import HTTPServer

sever=HTTPServer(("",8000),PostHandler)

sever.serve_forever()

if__name__=='__main__':

StartServer()

$

$ find.-name"*.c"| xargsgrephls_enc_key_url

./libavformat/hlsenc.c: {"hls_enc_key_url","url to access the key to decrypt the segments", OFFSET(key_url), AV_OPT_TYPE_STRING, {.str=NULL},,, E},

$

Fmpeg-n4.0.2/libavformat/hlsenc.c

{"hls_enc_key_url","url to access the key to decrypt the segments",

urltoaccessthekeytodecryptthesegments

staticconstAVOptionoptions[]={

//....

{"hls_enc","enable AES128 encryption support",OFFSET(encrypt),AV_OPT_TYPE_BOOL, {.i64=},,1,E},

{"hls_enc_key","hex-coded 16 byte key to encrypt the segments",OFFSET(key),AV_OPT_TYPE_STRING, .flags=E},

{"hls_enc_key_url","url to access the key to decrypt the segments",OFFSET(key_url),AV_OPT_TYPE_STRING, {.str=NULL},,,E},

{"hls_enc_iv","hex-coded 16 byte initialization vector",OFFSET(iv),AV_OPT_TYPE_STRING, .flags=E},

{NULL},

};

staticintdo_encrypt(AVFormatContext*s,VariantStream*vs){

//.....

av_strlcpy(hls->key_basename,s->url,len);

av_strlcat(hls->key_basename,".key",len);

if(hls->key_url) {

av_strlcpy(hls->key_file,hls->key_url,sizeof(hls->key_file));

av_strlcpy(hls->key_uri,hls->key_url,sizeof(hls->key_uri));

}else{

av_strlcpy(hls->key_file,hls->key_basename,sizeof(hls->key_file));

av_strlcpy(hls->key_uri,hls->key_basename,sizeof(hls->key_uri));

}

//.....

}

  • 发表于:
  • 原文链接:https://kuaibao.qq.com/s/20181112G006NM00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券