通常会看到表单提交带有文件的时候,一般content-type长这样:
multipart/form-data; boundary=----WebKitFormBoundaryV1xLBsu5DDg4628C
那么boundary对应值的后半部分是怎么来的呢,搜了一下chromium的代码,找到了答案。
下面是用python对应写的,主要是python的requests模块boundary的样子不一样,强迫症~

from random import randint
kAlphaNumericEncodingMap = [0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42]
random_chars = "".join([chr(kAlphaNumericEncodingMap[randint(0,63)]) for _ in range(16)])
boundary = "----WebKitFormBoundary" + random_chars
print(boundary)

好像很久没有公开文章了...其实还是有写几篇,今天看到别人的博客,突然觉得还是得发点什么证明这个博客没有被废弃!

本文中心:爱奇艺authkey算法

  • 下了断点调试,很快就知道这个参数计算的方法了,然后下面是代码
  • 传入有两个参数,一个是13位时间戳,一个是tvid
  • 实际参与计算还有一个authkey(""),这是个固定值
  • 用法是node authkey.js tm tvid
  • 然而...它其实就是对字符串进行了md5计算
  • 所以最简单的代码就是md5("d41d8cd98f00b204e9800998ecf8427e"+tm+tvid)
function a(e, t) {
    e[t >> 5] |= 128 << t % 32,
    e[14 + (t + 64 >>> 9 << 4)] = t;
    for (var i = 1732584193, a = -271733879, n = -1732584194, u = 271733878, c = 0; c < e.length; c += 16) {
        var f = i
          , p = a
          , h = n
          , _ = u;
        i = r(i, a, n, u, e[c + 0], 7, -680876936),
        u = r(u, i, a, n, e[c + 1], 12, -389564586),
        n = r(n, u, i, a, e[c + 2], 17, 606105819),
        a = r(a, n, u, i, e[c + 3], 22, -1044525330),
        i = r(i, a, n, u, e[c + 4], 7, -176418897),
        u = r(u, i, a, n, e[c + 5], 12, 1200080426),
        n = r(n, u, i, a, e[c + 6], 17, -1473231341),
        a = r(a, n, u, i, e[c + 7], 22, -45705983),
        i = r(i, a, n, u, e[c + 8], 7, 1770035416),
        u = r(u, i, a, n, e[c + 9], 12, -1958414417),
        n = r(n, u, i, a, e[c + 10], 17, -42063),
        a = r(a, n, u, i, e[c + 11], 22, -1990404162),
        i = r(i, a, n, u, e[c + 12], 7, 1804603682),
        u = r(u, i, a, n, e[c + 13], 12, -40341101),
        n = r(n, u, i, a, e[c + 14], 17, -1502002290),
        a = r(a, n, u, i, e[c + 15], 22, 1236535329),
        i = o(i, a, n, u, e[c + 1], 5, -165796510),
        u = o(u, i, a, n, e[c + 6], 9, -1069501632),
        n = o(n, u, i, a, e[c + 11], 14, 643717713),
        a = o(a, n, u, i, e[c + 0], 20, -373897302),
        i = o(i, a, n, u, e[c + 5], 5, -701558691),
        u = o(u, i, a, n, e[c + 10], 9, 38016083),
        n = o(n, u, i, a, e[c + 15], 14, -660478335),
        a = o(a, n, u, i, e[c + 4], 20, -405537848),
        i = o(i, a, n, u, e[c + 9], 5, 568446438),
        u = o(u, i, a, n, e[c + 14], 9, -1019803690),
        n = o(n, u, i, a, e[c + 3], 14, -187363961),
        a = o(a, n, u, i, e[c + 8], 20, 1163531501),
        i = o(i, a, n, u, e[c + 13], 5, -1444681467),
        u = o(u, i, a, n, e[c + 2], 9, -51403784),
        n = o(n, u, i, a, e[c + 7], 14, 1735328473),
        a = o(a, n, u, i, e[c + 12], 20, -1926607734),
        i = s(i, a, n, u, e[c + 5], 4, -378558),
        u = s(u, i, a, n, e[c + 8], 11, -2022574463),
        n = s(n, u, i, a, e[c + 11], 16, 1839030562),
        a = s(a, n, u, i, e[c + 14], 23, -35309556),
        i = s(i, a, n, u, e[c + 1], 4, -1530992060),
        u = s(u, i, a, n, e[c + 4], 11, 1272893353),
        n = s(n, u, i, a, e[c + 7], 16, -155497632),
        a = s(a, n, u, i, e[c + 10], 23, -1094730640),
        i = s(i, a, n, u, e[c + 13], 4, 681279174),
        u = s(u, i, a, n, e[c + 0], 11, -358537222),
        n = s(n, u, i, a, e[c + 3], 16, -722521979),
        a = s(a, n, u, i, e[c + 6], 23, 76029189),
        i = s(i, a, n, u, e[c + 9], 4, -640364487),
        u = s(u, i, a, n, e[c + 12], 11, -421815835),
        n = s(n, u, i, a, e[c + 15], 16, 530742520),
        a = s(a, n, u, i, e[c + 2], 23, -995338651),
        i = d(i, a, n, u, e[c + 0], 6, -198630844),
        u = d(u, i, a, n, e[c + 7], 10, 1126891415),
        n = d(n, u, i, a, e[c + 14], 15, -1416354905),
        a = d(a, n, u, i, e[c + 5], 21, -57434055),
        i = d(i, a, n, u, e[c + 12], 6, 1700485571),
        u = d(u, i, a, n, e[c + 3], 10, -1894986606),
        n = d(n, u, i, a, e[c + 10], 15, -1051523),
        a = d(a, n, u, i, e[c + 1], 21, -2054922799),
        i = d(i, a, n, u, e[c + 8], 6, 1873313359),
        u = d(u, i, a, n, e[c + 15], 10, -30611744),
        n = d(n, u, i, a, e[c + 6], 15, -1560198380),
        a = d(a, n, u, i, e[c + 13], 21, 1309151649),
        i = d(i, a, n, u, e[c + 4], 6, -145523070),
        u = d(u, i, a, n, e[c + 11], 10, -1120210379),
        n = d(n, u, i, a, e[c + 2], 15, 718787259),
        a = d(a, n, u, i, e[c + 9], 21, -343485551),
        i = l(i, f),
        a = l(a, p),
        n = l(n, h),
        u = l(u, _)
    }
    return Array(i, a, n, u)
}
function n(e, t, i, a, n, r) {
    return l(u(l(l(t, e), l(a, r)), n), i)
}
function r(e, t, i, a, r, o, s) {
    return n(t & i | ~t & a, e, t, r, o, s)
}
function o(e, t, i, a, r, o, s) {
    return n(t & a | i & ~a, e, t, r, o, s)
}
function s(e, t, i, a, r, o, s) {
    return n(t ^ i ^ a, e, t, r, o, s)
}
function d(e, t, i, a, r, o, s) {
    return n(i ^ (t | ~a), e, t, r, o, s)
}
function l(e, t) {
    var i = (65535 & e) + (65535 & t);
    return (e >> 16) + (t >> 16) + (i >> 16) << 16 | 65535 & i
}
function u(e, t) {
    return e << t | e >>> 32 - t
}
function c(e) {
    for (var t = Array(), i = (1 << h) - 1, a = 0; a < e.length * h; a += h)
        t[a >> 5] |= (e.charCodeAt(a / h) & i) << a % 32;
    return t
}
function f(e) {
    for (var t = p ? "0123456789ABCDEF" : "0123456789abcdef", i = "", a = 0; a < 4 * e.length; a++)
        i += t.charAt(e[a >> 2] >> a % 4 * 8 + 4 & 15) + t.charAt(e[a >> 2] >> a % 4 * 8 & 15);
    return i
}
var p = 0
  , h = 8;
function authkey(e) {
    return f(a(c(e), e.length * h))
}
// console.log(authkey(authkey("")+"1558939218094"+"2494954900"))
var args = process.argv.slice(2);
tm = args[0]
tvid = args[1]
console.log(authkey("d41d8cd98f00b204e9800998ecf8427e" + tm + tvid));

---2019/04/27---
失效的112开头ip这个之前有效期长达十几个小时(没有仔细测)
目前正常的一般是两个小时有效期

http://112.17.40.140/PLTV/88888888/224/3221226809/index.m3u8 已失效
http://39.134.176.157/PLTV/88888888/224/3221226539/index.m3u8 已失效
http://223.94.71.23/PLTV/88888888/224/3221226758/index.m3u8 正常
http://223.94.71.24/PLTV/88888888/224/3221226758/index.m3u8 正常
http://223.94.71.48/PLTV/88888888/224/3221226809/index.m3u8 正常
http://39.134.185.69/PLTV/88888888/224/3221226758/index.m3u8 正常

官方wiki有下面三个例子:

ffmpeg -ss 00:01:00 -i video.mp4 -to 00:02:00 -c copy cut.mp4
ffmpeg -i video.mp4 -ss 00:01:00 -to 00:02:00 -c copy cut.mp4
ffmpeg -ss 00:01:00 -i video.mp4 -to 00:02:00 -c copy -copyts cut.mp4

-t-to两者不可同时出现,如果同时使用,则以-t为准

  • -t是在-ss指定的时间后持续的时间
  • -to是结束时间

测试后,第二种方式最为稳妥,但速度较慢,一三两种方式很快但是会出现时间误差。

对于bt2020等,使用这样的方法提取均会保留。

批量提取视频vid,样本如下

vlist = ['x0030wh28ov', 'p0024ht72c2', ..., 'x002483emfm', 'o0024m4oidi', 'n0024mvc1b8']

通过简单观察,可以发现第2、3、4、5位存在明显的递增关系,通过其他手段,可以验证vid和时间存在关系。
现在计划分析vid的一些规律。

字符频率

首先将2、3、4、5位剔除,因为他们有明显的规律,但其他位的字符都是0-9和a-z范围。现在用下面的脚本统计这些字符的信息。

def cc(s):
    ac = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    cres = [s.count(c) for c in ac]#统计字符出现次数
    cresd = [x-y for x, y in zip(cres, cres[1:])]#相邻字符的差值
    print(cres)
    print(cresd)
    print(sum(cresd))
string = ""
for vid in vlist:
    string = string + vid[:1] + vid[5:]
    cc(string)

随加入统计的vid增加,对各个字符出现的频率进行统计,绘制曲线,情况如下(共333个vid):
各字符频率变化

可以发现随着vid的数量越来越多,单个字符的频率稳定在一个值附近,但并不是同一个频率。
这样看起来依然不够直观,在此对每个字符的统计进行拟合,鉴于前面部分的数据属于小样本情况,对拟合可能造成较大误差,所以用于拟合的数据从100个vid之后开始,采用指数函数拟合(a * exp(-b * x) + c)。结果如下:
将x轴起始坐标偏移至1(这个图可能有点问题,但我不想改了)
1
将x轴起始坐标保持
101

在原位置拟合结果比较明显,各个字符概率分布情况也比较清晰了。
不过我觉得再增加一定数量vid,现在总vid数量是407,效果如下
将x轴起始坐标偏移至1
1
将x轴起始坐标保持
101

可以看到各个字符的频率已经可以认为是稳定了,得到拟合函数的具体系数,得到极限值,就可以认为极限值是字符对应的频率。
完整视角的拟合情况:
全视角

将vid看做一个向量,按一定映射关系,计算其长度,下面是样本中vid的分布情况:
vid分布

横轴也这样计算,分布如下:
x轴的分布

即使样本不够多,但可以明显看到的是,vid的长度分布比较均匀,分布在某一个数的前后,横轴亦是如此。
考虑连续的一串数字,比如1-10000,将其每一个数字转为字符串,计算总的距离,下面是距离分布:
连续数字

如果是y = x^3 + 11 * x^2 + 1.5这样的函数,结果如下:
三次多项式

可以看到这样的规律性都很强。就这样的结果来看,可以排除数字和vid的映射关系应该不是高次多项式,更不是线性关系。下面再试试其他函数。
比如y = a * cos(b * x) + c * sin(d * x) + e其中e能使整个函数始终大于0,这个规律性更明显了。
三角函数

对10进制到16进制的变化,可见整体走势依然和10进制一样。
hex(x)

到这里,我认为原vid的向量长度的样本过少,不足以更全面直观体现它的分布,所以现在先去提取更多的vid。

---分割线---
在多次尝试后,发现随机提取某三个索引,在三维空间中显示出来,发现也是随机分布的,并没有明显特征(如下)。
三维的向量分布

至此,除了单个字符的出现存在稳定的概率外,没有其他发现。
另外尝试将有着明显时间差的vid进行简单的36进制转换在!7这么多种情况下,依然不能满足递增的关系。如果说有什么规律,至少不是按某一种进制转换的。
还尝试了将vid按36进制换算后,计算向量长度,结果如下图,样本有限,不过似乎能看出整体分布可能接近三角函数的样子。
向量长度