一、AES‑128 加密里容易被忽略的 IV 参数
做版权保护的 HLS 点播直播,会使用 AES‑128 对 TS 分片加密。很多新手只关注密钥本身,很容易忽略 IV 初始化向量。很多故障现象很迷惑:密钥文件本身 16 字节完全正确,但是分片解密依旧失败,播放器黑屏转圈。
很多示例 M3U8 样本没有写 IV,这时候 hls.js 会默认使用分片序列号 MEDIA‑SEQUENCE 作为 IV;但是业务如果手动指定IV=,一旦格式写错、长度不对,解密直接失效。
IV 是 AES 加密的初始化向量,必须 16 字节十六进制字符串,写法以0X开头。很多新手抄网上示例,写错大小写、少字符、多空格,肉眼看差别不大,但解密完全不对。
坑点隐蔽:M3U8 索引、密钥接口全部 200,控制台不会报密钥 404,只会报 FRAG_DECRYPT_ERROR 解密错误。很多人拿到报错第一反应怀疑密钥文件,排查很久才发现是 IV 向量的问题。
遇到加密流解密失败的问题,我会使用 m3u8live.cn 网页调试工具,查看 M3U8 原始 #EXT‑X‑KEY 标签,确认 IV 书写格式,快速定位解密故障。
二、IV 向量常见踩坑现象
坑 1:IV 没有以 0X 开头
HLS 协议要求 IV 值必须以0X作为前缀。漏掉前缀,hls.js 无法正确解析向量,解密直接失败。
坑 2:十六进制字符长度不对
AES‑128 的 IV 对应 16 字节,转十六进制一共 32 个字符。多一个字符、少一个字符,都会解密失败。肉眼看一串字符串,很难数出字符长度。
坑 3:字符串中间存在空格、换行、不可见字符
复制粘贴配置的时候带入空格换行,IV 参数被破坏,解密出错。
坑 4:部分分片指定 IV,部分分片没有指定
同一份 M3U8 里面,一部分 #EXT‑X‑KEY 带 IV,一部分不带。不带 IV 会复用分片序列号作为向量,前后加密向量不一致,部分分片解密成功,部分分片解密失败,出现播放中途黑屏。
坑 5:手动写死固定 IV,多份视频共用同一个 IV
安全上也不推荐全部视频使用同一个 IV;同时切片脚本如果自动生成 IV,手动写死会和服务端加密时使用的向量不匹配。
三、区分:不写 IV 和手动写 IV 的区别
- M3U8 的 #EXT‑X‑KEY 标签不写 IV 字段:hls.js 自动取 MEDIA‑SEQUENCE 分片序列号作为初始化向量。很多简单加密点播示例就是这种写法。
- M3U8 里面明确写
IV=0Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:播放器直接使用给出的十六进制向量,不再使用分片序列号。
重点:服务端加密 TS 分片时使用什么 IV,M3U8 标签里面就必须填写完全一样的 IV,大小写也要匹配。
四、新手排查简单步骤
第一步,加密 M3U8 地址粘贴网页调试工具,查看原始 M3U8 文本,读取 #EXT‑X‑KEY 完整内容。
- 如果写了 IV:检查是否 0X 开头,统计后面字符总长度等于 32;检查有没有空格换行;
- 如果没有写 IV:确认业务加密分片时确实是使用分片序列号作为 IV。
第二步,确认密钥文件严格 16 字节,排除密钥本身问题。 第三步,复现解密报错 FRAG_DECRYPT_ERROR,区分是密钥获取失败,还是 IV 解析错误。
五、开发运维建议
- 如果切片程序自动生成 IV,直接使用程序输出的完整字符串,不要手动复制改写 IV 值,避免引入空格、字符缺失。
- IV 必须以 0X 开头,后续严格 32 位十六进制字符,不要随便简写。
- 同一份 M3U8 内部,不要出现一部分 KEY 带 IV、一部分不带 IV 的混合写法。
- 测试加密流,不要只看 VLC 播放,VLC 容错较高,网页 hls.js 环境才是业务验收基准。
六、总结
AES‑128 解密失败,不要只盯着密钥文件。IV 初始化向量格式错误,同样会造成解密黑屏,而 M3U8、密钥接口 HTTP 请求全部返回 200,迷惑性很强。IV 要注意 0X 前缀、32 位十六进制字符长度,不能混入空格换行。借助网页调试工具查看原始 #EXT‑X‑KEY 标签,可以快速定位 IV 向量书写错误,解决加密分片解密失败的疑难问题。