FreshTV 这个 M3U8 最大的坑爹之处在于它的 key 是一个私有协议。
例子:
#EXT-X-KEY:METHOD=AES-128,URI="abemafresh://abemafresh/206437t2806498f02ad88f4aecd7aa2083a6374edef/2928e09b0fa322020bbe5d854eb92984",IV=0xd3d54ce117415b571eb96ac49ed11e9d
好,这个abemafresh://
是什么坑爹玩意呢。
翻了下代码发现原来是劫持了 XMLHTTPRequest 来支持这么个玩意的加载。
好我们来仔细研究一下。
首先这个s就是来判定要加载的url是不是以abemafresh://
开头,这神奇的写法我也是醉了。String.prototype.startsWith()
了解一下?
如果是的话就按/
来分割。
得到 i = ["abemafresh:", "", "abemafresh", "206437t2806498f02ad88f4aecd7aa2083a6374edef", "2928e09b0fa322020bbe5d854eb92984"]
然后 c 和 l 就分别是 "206437t2806498f02ad88f4aecd7aa2083a6374edef"
和 "2928e09b0fa322020bbe5d854eb92984"
u 是 c 和 l 连接起来。
然后调用了一个a(c, l, s)
a()
函数的内部,首先是调用了个 d.create()
,其实这个函数是 cryptojs.lib.WordArray()
把一组固定的数创建成一个 WordArray
随后使用 HmacSHA256 做个运算。随后使用 AES 进行解密,前面 SHA256 得到的结果就是密钥。也就是说那个abemafresh的url 前半部分是密钥后半部分是密文。
总之经过还原后的代码是这样的
const cryptojs = require('crypto-js'); const abemafresh = [1413502068, 2104980084, 1144534056, 1967279194, 2051549272, 860632952, 1464353903, 1212380503]; const url = "abemafresh://abemafresh/206437t2806498f02ad88f4aecd7aa2083a6374edef/2928e09b0fa322020bbe5d854eb92984"; const part1 = url.split('/')[3]; const part2 = url.split('/')[4]; const hash = cryptojs.HmacSHA256(part1, cryptojs.lib.WordArray.create(abemafresh)); const decryptResult = cryptojs.AES.decrypt(cryptojs.lib.CipherParams.create({ ciphertext: cryptojs.enc.Hex.parse(part2) }), hash, { mode: cryptojs.mode.ECB, padding: cryptojs.pad.NoPadding }).toString(); for (var t = new Uint8Array(16), r = 0; 16 > r; r++) t[r] = parseInt(decryptResult.substr(2 * r, 2), 16); const result = []; for (const i of t) { result.push(i.toString(16).length === 1 ? ('0' + i.toString(16)) : i.toString(16)); } console.log('key = ', result.join(''));
Hi,
Thanks for this, it is very helpful!
However, I am having difficulty incorporating the outputted key into the original HLS file. FFmpeg unfortunately continues to run into “Invalid data found when processing input” errors.
Any help would be much appreciated. Thanks!
You may refer to this: https://egg.5ch.net/test/read.cgi/streaming/1524231434/272
Use a hex to file converter to make a key file. Then points the key of m3u8 to this key file.